diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs
index 9428febc1a763..fef8416d462be 100644
--- a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs
@@ -243,38 +243,32 @@ public void CopyFromScreen(int sourceX, int sourceY, int destinationX, int desti
int destWidth = blockRegionSize.Width;
int destHeight = blockRegionSize.Height;
- using (DeviceContext dc = DeviceContext.FromHwnd(IntPtr.Zero))
+ IntPtr screenDC = Interop.User32.GetDC(IntPtr.Zero);
+ try
{
- // The DC of the screen.
- IntPtr screenDC = dc.Hdc;
-
- // The DC of the current graphics object.
IntPtr targetDC = GetHdc();
-
- try
- {
- int result = Interop.Gdi32.BitBlt(
- targetDC,
- destinationX,
- destinationY,
- destWidth,
- destHeight,
- screenDC,
- sourceX,
- sourceY,
- (Interop.Gdi32.RasterOp)copyPixelOperation);
-
- //a zero result indicates a win32 exception has been thrown
- if (result == 0)
- {
- throw new Win32Exception();
- }
- }
- finally
+ int result = Interop.Gdi32.BitBlt(
+ targetDC,
+ destinationX,
+ destinationY,
+ destWidth,
+ destHeight,
+ screenDC,
+ sourceX,
+ sourceY,
+ (Interop.Gdi32.RasterOp)copyPixelOperation);
+
+ //a zero result indicates a win32 exception has been thrown
+ if (result == 0)
{
- ReleaseHdc();
+ throw new Win32Exception();
}
}
+ finally
+ {
+ Interop.User32.ReleaseDC(IntPtr.Zero, screenDC);
+ ReleaseHdc();
+ }
}
public Color GetNearestColor(Color color)
diff --git a/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContext.cs b/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContext.cs
index 209445ea3f38e..5ca8b91b9c5c8 100644
--- a/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContext.cs
+++ b/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContext.cs
@@ -14,7 +14,7 @@ namespace System.Drawing.Internal
/// This class is divided into two files separating the code that needs to be compiled into retail builds and
/// debugging code.
///
- internal sealed partial class DeviceContext : MarshalByRefObject, IDeviceContext, IDisposable
+ internal sealed partial class DeviceContext : MarshalByRefObject, IDisposable
{
///
/// This class is a wrapper to a Win32 device context, and the Hdc property is the way to get a
@@ -63,10 +63,6 @@ internal sealed partial class DeviceContext : MarshalByRefObject, IDeviceContext
private bool _disposed;
- // We cache the hWnd when creating the dc from one, to provide support forIDeviceContext.GetHdc/ReleaseHdc.
- // This hWnd could be null, in such case it is referring to the screen.
- private readonly IntPtr _hWnd = (IntPtr)(-1); // Unlikely to be a valid hWnd.
-
private IntPtr _hInitialPen;
private IntPtr _hInitialBrush;
private IntPtr _hInitialBmp;
@@ -88,34 +84,7 @@ internal sealed partial class DeviceContext : MarshalByRefObject, IDeviceContext
/// This object's hdc. If this property is called, then the object will be used as an HDC wrapper, so the hdc
/// is cached and calls to GetHdc/ReleaseHdc won't PInvoke into GDI. Call Dispose to properly release the hdc.
///
- public IntPtr Hdc
- {
- get
- {
- if (_hDC == IntPtr.Zero)
- {
- if (_dcType == DeviceContextType.Display)
- {
- Debug.Assert(!_disposed, "Accessing a disposed DC, forcing recreation of HDC - this will generate a Handle leak!");
-
- // Note: ReleaseDC must be called from the same thread. This applies only to HDC obtained
- // from calling GetDC. This means Display DeviceContext objects should never be finalized.
- _hDC = ((IDeviceContext)this).GetHdc(); // _hDC will be released on call to Dispose.
- CacheInitialState();
- }
-#if GDI_FINALIZATION_WATCH
- else
- {
- try { Debug.WriteLine($"Allocation stack:\r\n{AllocationSite}\r\nDeallocation stack:\r\n{DeAllocationSite}"); } catch {}
- }
-#endif
- }
-
- Debug.Assert(_hDC != IntPtr.Zero, "Attempt to use deleted HDC - DC type: " + _dcType);
-
- return _hDC;
- }
- }
+ public IntPtr Hdc => _hDC;
// Due to a problem with calling DeleteObject() on currently selected GDI objects, we now track the initial set
// of objects when a DeviceContext is created. Then, we also track which objects are currently selected in the
@@ -129,24 +98,6 @@ private void CacheInitialState()
_hCurrentFont = _hInitialFont = Interop.Gdi32.GetCurrentObject(new HandleRef(this, _hDC), Interop.Gdi32.ObjectType.OBJ_FONT);
}
-
- ///
- /// Constructor to construct a DeviceContext object from an window handle.
- ///
- private DeviceContext(IntPtr hWnd)
- {
- _hWnd = hWnd;
- _dcType = DeviceContextType.Display;
-
- DeviceContexts.AddDeviceContext(this);
-
- // the hDc will be created on demand.
-
-#if TRACK_HDC
- Debug.WriteLine( DbgUtil.StackTraceToStr(string.Format( "DeviceContext( hWnd=0x{0:x8} )", unchecked((int) hWnd))));
-#endif
- }
-
///
/// Constructor to construct a DeviceContext object from an existing Win32 device context handle.
///
@@ -158,10 +109,6 @@ private DeviceContext(IntPtr hDC, DeviceContextType dcType)
CacheInitialState();
DeviceContexts.AddDeviceContext(this);
- if (dcType == DeviceContextType.Display)
- {
- _hWnd = Interop.User32.WindowFromDC(new HandleRef(this, _hDC));
- }
#if TRACK_HDC
Debug.WriteLine(DbgUtil.StackTraceToStr($"DeviceContext(hDC=0x{(int)hDC:X8}, Type={dcType})"));
#endif
@@ -188,19 +135,6 @@ public static DeviceContext CreateIC(string driverName, string deviceName, strin
return new DeviceContext(hdc, DeviceContextType.Information);
}
- ///
- /// Creates a DeviceContext object wrapping a memory DC compatible with the specified device.
- ///
- public static DeviceContext FromCompatibleDC(IntPtr hdc)
- {
- // If hdc is null, the function creates a memory DC compatible with the application's current screen.
- // Win2K+: (See CreateCompatibleDC in the MSDN).
- // In this case the thread that calls CreateCompatibleDC owns the HDC that is created. When this thread is destroyed,
- // the HDC is no longer valid.
- IntPtr compatibleDc = Interop.Gdi32.CreateCompatibleDC(hdc);
- return new DeviceContext(compatibleDc, DeviceContextType.Memory);
- }
-
///
/// Used for wrapping an existing hdc. In this case, this object doesn't own the hdc so calls to
/// GetHdc/ReleaseHdc don't PInvoke into GDI.
@@ -211,11 +145,6 @@ public static DeviceContext FromHdc(IntPtr hdc)
return new DeviceContext(hdc, DeviceContextType.Unknown);
}
- ///
- /// When hwnd is null, we are getting the screen DC.
- ///
- public static DeviceContext FromHwnd(IntPtr hwnd) => new DeviceContext(hwnd);
-
~DeviceContext() => Dispose(false);
public void Dispose()
@@ -237,10 +166,6 @@ internal void Dispose(bool disposing)
switch (_dcType)
{
- case DeviceContextType.Display:
- Debug.Assert(disposing, "WARNING: Finalizing a Display DeviceContext.\r\nReleaseDC may fail when not called from the same thread GetDC was called from.");
- ((IDeviceContext)this).ReleaseHdc();
- break;
case DeviceContextType.Information:
case DeviceContextType.NamedDevice:
Interop.Gdi32.DeleteDC(new HandleRef(this, _hDC));
@@ -261,48 +186,6 @@ internal void Dispose(bool disposing)
DbgUtil.AssertFinalization(this, disposing);
}
- ///
- /// Explicit interface method implementation to hide them a bit for usability reasons so the object is seen as
- /// a wrapper around an hdc that is always available, and for performance reasons since it caches the hdc if
- /// used in this way.
- ///
- IntPtr IDeviceContext.GetHdc()
- {
- if (_hDC == IntPtr.Zero)
- {
- Debug.Assert(_dcType == DeviceContextType.Display, "Calling GetDC from a non display/window device.");
-
- // Note: for common DCs, GetDC assigns default attributes to the DC each time it is retrieved.
- // For example, the default font is System.
- _hDC = Interop.User32.GetDC(new HandleRef(this, _hWnd));
-#if TRACK_HDC
- Debug.WriteLine( DbgUtil.StackTraceToStr( string.Format("hdc[0x{0:x8}]=DC.GetHdc(hWnd=0x{1:x8})", unchecked((int) _hDC), unchecked((int) _hWnd))));
-#endif
- }
-
- return _hDC;
- }
-
-
- ///
- /// If the object was created from a DC, this object doesn't 'own' the dc so we just ignore this call.
- ///
- void IDeviceContext.ReleaseHdc()
- {
- if (_hDC != IntPtr.Zero && _dcType == DeviceContextType.Display)
- {
-#if TRACK_HDC
- int retVal =
-#endif
- Interop.User32.ReleaseDC(new HandleRef(this, _hWnd), new HandleRef(this, _hDC));
- // Note: retVal == 0 means it was not released but doesn't necessarily means an error; class or private DCs are never released.
-#if TRACK_HDC
- Debug.WriteLine( DbgUtil.StackTraceToStr( string.Format("[ret={0}]=DC.ReleaseDC(hDc=0x{1:x8}, hWnd=0x{2:x8})", retVal, unchecked((int) _hDC), unchecked((int) _hWnd))));
-#endif
- _hDC = IntPtr.Zero;
- }
- }
-
///
/// Restores the device context to the specified state. The DC is restored by popping state information off a
/// stack created by earlier calls to the SaveHdc function.
diff --git a/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContextType.cs b/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContextType.cs
index 9e73c71a84d38..afd80b750b67b 100644
--- a/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContextType.cs
+++ b/src/libraries/System.Drawing.Common/src/misc/GDI/DeviceContextType.cs
@@ -11,9 +11,6 @@ internal enum DeviceContextType
// Unknown device
Unknown = 0x00,
- // Display DC - obtained from GetDC/GetDCEx/BeginPaint.
- Display = 0x01,
-
// Window DC including non-client area - obtained from GetWindowDC
NCWindow = 0x02,