none
关于image.fromhbitmap的错误 RRS feed

  • 问题

  • textbox1 是窗口句柄,截图后,用  转成图片,执行次数多了,就会报错

    于是我做了循环测试如下,大约执行一分到两分钟就报错,这是它报出来的错误,请问是哪里错了,该如何解决,谢谢

    错误图片 :social.msdn.microsoft.com/Forums/getfile/1501111


            Do While True
    
                SourceDC = GetWindowDC(TextBox1.Text)
                DestDC = CreateCompatibleDC(SourceDC)
                Bhandle = CreateCompatibleBitmap(SourceDC, Width, Height)
                SelectObject(DestDC, Bhandle)
                BitBlt(DestDC, 0, 0, Width, Height, SourceDC, Left, Top, &HCC0020)
                ReleaseDC(TextBox1.Text, SourceDC)
    
    
                PictureBox1.Image = Image.FromHbitmap(Bhandle)
    
    
                GC.Collect()
                Application.DoEvents()
    
            Loop


    2019年11月6日 14:36

答案

  • 應該是在 Image.FromHbitmap 後要釋放記憶體

    參考在 Image.FromHbitmap 方法 中的注解 :  DeleteObject GDI GDI Image方法会生成GDI位图的副本; 因此,可以在创建新的后立即使用方法释放传入的位图。 FromHbitmap

    使用 DeleteObject 請參考 : Bitmap.GetHbitmap 方法 中的示例


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2019年11月6日 18:41
  • DeleteObject对正在被Select的对象无效所以SelectObject的返回值要保存起来,用完了就恢复上一次的值。

    ReleaseDC的参数是HWND类型,传字符串地址进去显然不会有效果。

    CreateCompatibleDC创建的DC要用DeleteDC删除。

    函数不熟一定要把文档先看一遍,这些都是MSDN的文档里的内容……

    这些函数都是有返回值指示成功或者失败的,写代码要养成检查返回值的习惯。



    Visual C++ MVP

    2019年11月8日 1:11
    版主

全部回复

  • 應該是在 Image.FromHbitmap 後要釋放記憶體

    參考在 Image.FromHbitmap 方法 中的注解 :  DeleteObject GDI GDI Image方法会生成GDI位图的副本; 因此,可以在创建新的后立即使用方法释放传入的位图。 FromHbitmap

    使用 DeleteObject 請參考 : Bitmap.GetHbitmap 方法 中的示例


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

    2019年11月6日 18:41
  • 應該是在 Image.FromHbitmap 後要釋放記憶體

    參考在 Image.FromHbitmap 方法 中的注解 :  DeleteObject GDI GDI Image方法会生成GDI位图的副本; 因此,可以在创建新的后立即使用方法释放传入的位图。 FromHbitmap

    使用 DeleteObject 請參考 : Bitmap.GetHbitmap 方法 中的示例


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。 https://skilltree.my/

            Do While True
    
                SourceDC = GetWindowDC(TextBox1.Text)
                DestDC = CreateCompatibleDC(SourceDC)
                Bhandle = CreateCompatibleBitmap(SourceDC, Width, Height)
                SelectObject(DestDC, Bhandle)
                BitBlt(DestDC, 0, 0, Width, Height, SourceDC, Left, Top, &HCC0020)
                ReleaseDC(TextBox1.Text, SourceDC)
    
                DeleteObject(Bhandle)
    
    
                PictureBox1.Image = Image.FromHbitmap(Bhandle)
    
    
    
    
                GC.Collect()
                Application.DoEvents()
    
            Loop
    你好,谢谢你的回答,我加了 DeleteObject 还是在 
    PictureBox1.Image = Image.FromHbitmap(Bhandle)

    这一行提示同样的错误
    2019年11月7日 4:56
  • up up
    2019年11月7日 14:41
  • DeleteObject对正在被Select的对象无效所以SelectObject的返回值要保存起来,用完了就恢复上一次的值。

    ReleaseDC的参数是HWND类型,传字符串地址进去显然不会有效果。

    CreateCompatibleDC创建的DC要用DeleteDC删除。

    函数不熟一定要把文档先看一遍,这些都是MSDN的文档里的内容……

    这些函数都是有返回值指示成功或者失败的,写代码要养成检查返回值的习惯。



    Visual C++ MVP

    2019年11月8日 1:11
    版主
  • DeleteObject对正在被Select的对象无效所以SelectObject的返回值要保存起来,用完了就恢复上一次的值。

    ReleaseDC的参数是HWND类型,传字符串地址进去显然不会有效果。

    CreateCompatibleDC创建的DC要用DeleteDC删除。

    函数不熟一定要把文档先看一遍,这些都是MSDN的文档里的内容……

    这些函数都是有返回值指示成功或者失败的,写代码要养成检查返回值的习惯。



    Visual C++ MVP

    你好,谢谢你的回答,找到问题了,这个代码是为了提问写的,没注意到,感谢您的提醒,问题出在了实际代码中的声明,我声明错了。非常感谢

    2019年11月8日 6:53
  • 你好,

    可以尝试下我下面这个例子,测试了一下,没有出现报错的情况。

    应当传入句柄值,你传入的是Text.text。

    另外,为什么你要使用Do while true。。。Loop呢?下面这种调用方式可能更好。

    Private Sub TextBox4_TextChanged(sender As Object, e As EventArgs) Handles TextBox4.TextChanged
            PictureBox1.Image = CaptureWindow(TextBox4.Handle)
        End Sub

    Imports System.Runtime.InteropServices
    Public Class Form1
        Public Class GDI32
            Public Const SRCCOPY As Integer = &HCC0020
            <DllImport("gdi32.dll")>
            Public Shared Function BitBlt(ByVal hObject As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hObjectSource As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean
    
            End Function
    
            <DllImport("gdi32.dll")>
            Public Shared Function CreateCompatibleBitmap(ByVal hDC As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
    
            End Function
            <DllImport("gdi32.dll")>
            Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr
    
            End Function
            <DllImport("gdi32.dll")>
            Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean
    
            End Function
            <DllImport("gdi32.dll")>
            Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
    
            End Function
            <DllImport("gdi32.dll")>
            Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr
    
            End Function
        End Class
    
        Public Class User32
            <StructLayout(LayoutKind.Sequential)>
            Public Structure RECT
                Public left As Integer
                Public top As Integer
                Public right As Integer
                Public bottom As Integer
            End Structure
    
            <DllImport("user32.dll")>
            Public Shared Function GetDesktopWindow() As IntPtr
    
            End Function
            <DllImport("user32.dll")>
            Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
    
            End Function
            <DllImport("user32.dll")>
            Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As IntPtr
    
            End Function
            <DllImport("user32.dll")>
            Public Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef rect As RECT) As IntPtr
    
            End Function
        End Class
    
        Public Function CaptureWindow(ByVal handle As IntPtr) As Image
    
            Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
            Dim windowRect As User32.RECT = New User32.RECT()
            User32.GetWindowRect(handle, windowRect)
            Dim width As Integer = windowRect.right - windowRect.left
            Dim height As Integer = windowRect.bottom - windowRect.top
            Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
            Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
            Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY)
            GDI32.SelectObject(hdcDest, hOld)
            GDI32.DeleteDC(hdcDest)
            User32.ReleaseDC(handle, hdcSrc)
            Dim img As Image = Image.FromHbitmap(hBitmap)
            GDI32.DeleteObject(hBitmap)
    
            GC.Collect()
            Application.DoEvents()
    
            Return img
        End Function
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Do While True
                PictureBox1.Image = CaptureWindow(TextBox4.Handle)
            Loop
        End Sub
    
        'Private Sub TextBox4_TextChanged(sender As Object, e As EventArgs) Handles TextBox4.TextChanged
        '    PictureBox1.Image = CaptureWindow(TextBox4.Handle)
        'End Sub
    End Class

    希望对您有所帮助。

    Julie


    如果您对Visual Studio Microsoft Azure相关产品感兴趣,请点击此链接,或扫描以下二维码注册获取相关信息。



    2019年11月8日 7:17
    版主