【发布时间】:2014-09-02 03:56:40
【问题描述】:
我被要求通过将屏幕截图保存到 BMP 来调试一些试图在 VB.Net 中制作图形电影的代码。我发现它在达到 10,000 个 GDI 对象的限制后失败,并确定泄漏来自此代码:
Dim r As Integer
Dim hdcdest As System.IntPtr = CType(CreateCompatibleDC(CInt(GetWindowDC(frmDynamicsMDI.MainControl.fraAnimation.Handle))), IntPtr)
Dim hdcbitmap As System.IntPtr = CType(CreateCompatibleBitmap(GetWindowDC(frmDynamicsMDI.MainControl.fraAnimation.Handle), _
frmDynamicsMDI.MainControl.fraAnimation.Size.Width - (0 + CropRight), _
frmDynamicsMDI.MainControl.fraAnimation.Size.Height - (10 + 0)), IntPtr)
SelectObject(hdcdest, CInt(hdcbitmap))
BitBlt(hdcdest, 0, 0, frmDynamicsMDI.MainControl.fraAnimation.Width - (0 + CropRight), frmDynamicsMDI.MainControl.fraAnimation.Height - (10 + 0), _
GetWindowDC(frmDynamicsMDI.MainControl.fraAnimation.Handle), 0, 10, 13369376)
Image = System.Drawing.Image.FromHbitmap(hdcbitmap)
r = DeleteDC(CInt(GetWindowDC(frmDynamicsMDI.MainControl.fraAnimation.Handle)))
DeleteObject(CInt(hdcdest))
DeleteObject(CInt(hdcbitmap))
BitBlt 声明为:
Private Declare Function BitBlt Lib "GDI32" (ByVal hdestDC As IntPtr, ByVal x As Integer, ByVal y As Integer, _
ByVal nwidth As Integer, ByVal nheight As Integer, ByVal HsrcDC As IntPtr, ByVal xsrc As Integer, ByVal ysrc As Integer, ByVal _
dwRop As Int32) As Boolean
2 个System.IntPtr 创建调用每个创建 2 个 GDI 对象,而“BitBlt”创建 1 个。我发现的问题是 DeleteObject() 调用每个只删除 1 个 GDI 对象。
那么删除调用是否执行不正确?或者是否有其他对象与未被删除的 GDI 对象一起浮动?
【问题讨论】:
-
您的 pinvoke 声明不好,请从 pinvoke.net 网站获取更好的声明。有很多泄漏,一个是由您的 SelectObject() 调用引起的。在销毁设备上下文之前,您必须存储其返回值并再次调用 SelectObject() 以恢复原始选择。您还忘记了销毁 GetWindowDC() 返回值。