【问题标题】:GDI Objects not deletingGDI 对象不删除
【发布时间】: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() 返回值。

标签: vb.net gdi


【解决方案1】:

来自GetWindowDC function

GetWindowDC 用于在窗口的非客户区内实现特殊的绘画效果。不建议在任何窗口的非客户区绘画。

绘制完成后,必须调用ReleaseDC函数来释放设备上下文。不释放窗口设备上下文会严重影响应用程序请求的绘制。

您的代码在多个地方调用 GetWindowDC。尝试只在变量中调用一次,然后在完成后对其使用 ReleaseDC。

【讨论】:

  • 效果非常好!使用Dim MainWindowDC As System.IntPtr = GetWindowDC(frmDynamicsMDI.MainControl.fraAnimation.Handle)再调用DeleteDC(MainWindowDC)成功清理资源
  • @user3565590 不要忽略 ReleaseDC,以及 Hans 对 SelectObject 函数的评论中的建议。
  • ReleaseDC 与 DeleteDC 有何不同?删除还不释放资源吗?
  • @user3565590 你没有创建 DC,你借了它,所以你应该释放它,而不是删除它。毕竟,它仍然被它来自的对象使用。
  • 嗯,有道理,我更新它来代替发布。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
相关资源
最近更新 更多