DeviceContextHdcScope
struct 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();
}
}
}