<PackageReference Include="System.Drawing.Common" Version="10.0.0-rc.2.25502.107" />

DeviceContextHdcScope

Helper to scope getting a HDC from a IHdcContext object. Releases the HDC when disposed, unlocking the parent IHdcContext object.

Also saves and restores the state of the HDC.

using System; using System.Diagnostics; using System.Drawing; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Windows.Win32.Foundation; namespace Windows.Win32.Graphics.Gdi { [NullableContext(1)] [Nullable(0)] [CompilerFeatureRequired("RefStructs")] internal readonly ref struct DeviceContextHdcScope { private readonly int _savedHdcState; public IHdcContext DeviceContext { get; } public HDC HDC { get; } public DeviceContextHdcScope(IHdcContext deviceContext, bool applyGraphicsState = true, bool saveHdcState = false) { this = new DeviceContextHdcScope(deviceContext, applyGraphicsState ? ApplyGraphicsProperties.All : ApplyGraphicsProperties.None, saveHdcState); } public DeviceContextHdcScope(IHdcContext deviceContext, ApplyGraphicsProperties applyGraphicsState, bool saveHdcState = false) { ArgumentNullException.ThrowIfNull(deviceContext, "deviceContext"); DeviceContext = deviceContext; _savedHdcState = 0; HDC = default(HDC); IGraphicsHdcProvider graphicsHdcProvider = deviceContext as IGraphicsHdcProvider; IGraphics graphics = deviceContext as IGraphics; bool flag = applyGraphicsState != ApplyGraphicsProperties.None; if (graphics == null && graphicsHdcProvider == null) flag = false; else if (graphicsHdcProvider != null && graphicsHdcProvider.IsGraphicsStateClean) { flag = false; } HDC hDC2; if (graphicsHdcProvider != null) { HDC hDC; if (!flag) hDC = graphicsHdcProvider.GetHdc(); else { hDC2 = default(HDC); hDC = hDC2; } HDC = hDC; hDC2 = HDC; if (hDC2.IsNull) { graphics = graphicsHdcProvider.GetGraphics(true); if (graphics == null) throw new InvalidOperationException(); DeviceContext = graphics; } } if (!flag || graphics == null) { hDC2 = HDC; HDC = (hDC2.IsNull ? DeviceContext.GetHdc() : HDC); _savedHdcState = (saveHdcState ? PInvokeCore.SaveDC(HDC) : 0); } else { (HDC, int) hdc = graphics.GetHdc(applyGraphicsState, saveHdcState); HDC = hdc.Item1; _savedHdcState = hdc.Item2; } } public static implicit operator HDC([In] [IsReadOnly] ref DeviceContextHdcScope scope) { return scope.HDC; } public static implicit operator IntPtr([In] [IsReadOnly] ref DeviceContextHdcScope scope) { return scope.HDC; } public static explicit operator WPARAM([In] [IsReadOnly] ref DeviceContextHdcScope scope) { return (WPARAM)scope.HDC; } [Conditional("DEBUG")] private void ValidateHDC() { if (HDC.IsNull) throw new InvalidOperationException("Null HDC"); OBJ_TYPE objectType = (OBJ_TYPE)PInvokeCore.GetObjectType(HDC); if ((uint)(objectType - 3) > 1 && objectType != OBJ_TYPE.OBJ_MEMDC && objectType != OBJ_TYPE.OBJ_ENHMETADC) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(17, 1); defaultInterpolatedStringHandler.AppendLiteral("Invalid handle ("); defaultInterpolatedStringHandler.AppendFormatted(objectType); defaultInterpolatedStringHandler.AppendLiteral(")"); throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear()); } } public void Dispose() { if (_savedHdcState != 0) PInvokeCore.RestoreDC(HDC, _savedHdcState); if (!(DeviceContext is IGraphicsHdcProvider)) DeviceContext?.ReleaseHdc(); } } }