Search code examples
vb.netgdi

GDI Objects not deleting


I've been asked to debug some code that is trying to make a movie of a graph in VB.Net, by saving a screenshot to a BMP. I have discovered that it is failing after it hits the limit of 10,000 GDI objects and determined that the leak is from this code:

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))

And BitBlt declared as:

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

The 2 System.IntPtr creation calls create 2 GDI objects each and the 'BitBlt' creates 1. The issue I've found is that the DeleteObject() calls only remove 1 GDI object each.

So are the delete calls being done incorrectly? or is there other objects floating around with GDI objects that are not being deleted?


Solution

  • From GetWindowDC function

    GetWindowDC is intended for special painting effects within a window's nonclient area. Painting in nonclient areas of any window is not recommended.

    After painting is complete, the ReleaseDC function must be called to release the device context. Not releasing the window device context has serious effects on painting requested by applications.

    Your code is calling GetWindowDC in multiple places. Try calling it only once into a variable, and then use the ReleaseDC on it after you are done.