Reputation: 13
On the back of a Windows Form, I get a window DC, create a Graphics object with Graphics.FromHdc
, and then dispose the Graphics object before releasing the DC.
Private Declare Function GetWindowDC Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As Integer
Dim hdc As IntPtr = GetWindowDC(Me.Handle)
Try
Using g As Graphics = Graphics.FromHdc(hdc)
' ... use g ...
End Using
Finally
ReleaseDC(Me.Handle, hdc)
End Try
The Microsoft documentation for Graphics.FromHdc
shows similar code. (It uses Graphics.GetHdc
and Graphics.ReleaseHdc
, instead of Win32 GetWindowDc
and ReleaseDC
.) However, they release the DC before disposing the Graphics object:
' Get handle to device context.
Dim hdc As IntPtr = e.Graphics.GetHdc()
' Create new graphics object using handle to device context.
Dim newGraphics As Graphics = Graphics.FromHdc(hdc)
' Draw rectangle to screen.
newGraphics.DrawRectangle(New Pen(Color.Red, 3), 0, 0, 200, 100)
' Release handle to device context and dispose of the Graphics ' object
e.Graphics.ReleaseHdc(hdc)
newGraphics.Dispose()
Why did they do it this way?
Should the DC be released before or after Graphics.Dispose
?
It is possible that the wrong order can cause resource leaks or memory corruption?
Upvotes: 1
Views: 1678
Reputation: 23214
From the Graphics.Dispose method:
private void Dispose(bool disposing)
{
..SNIP...
if (this.nativeGraphics != IntPtr.Zero)
{
try
{
if (this.nativeHdc != IntPtr.Zero) <<---
{
this.ReleaseHdc(); <<---
}
So it seems like it will release the hdc by itself tbh.
[edit]
It's actually :
[DllImport("gdiplus.dll", CharSet = CharSet.Unicode, EntryPoint = "GdipReleaseDC", ExactSpelling = true, SetLastError = true)]
private static extern int IntGdipReleaseDC(HandleRef graphics, HandleRef hdc);
That is getting called, don't know if the gdiplus release dc handles native device contexts too
Upvotes: 2