|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Windows.Win32.Graphics.Gdi;
/// <summary>
/// Helper to scope lifetime of an <see cref="Gdi.HDC"/> retrieved via <see cref="PInvokeCore.GetDC(HWND)"/> and
/// <see cref="PInvokeCore.GetDCEx(HWND, HRGN, GET_DCX_FLAGS)"/>. Releases the <see cref="Gdi.HDC"/> (if any)
/// when disposed.
/// </summary>
/// <remarks>
/// <para>
/// Use in a <see langword="using" /> statement. If you must pass this around, always pass by <see langword="ref" />
/// to avoid duplicating the handle and risking a double release.
/// </para>
/// </remarks>
internal readonly ref struct GetDcScope
{
public HDC HDC { get; }
public HWND HWND { get; }
public GetDcScope(HWND hwnd)
{
HWND = hwnd;
HDC = PInvokeCore.GetDC(hwnd);
}
/// <summary>
/// Creates a <see cref="Gdi.HDC"/> using <see cref="PInvokeCore.GetDCEx(HWND, HRGN, GET_DCX_FLAGS)"/>.
/// </summary>
/// <remarks>
/// <para>
/// GetWindowDC calls GetDCEx(hwnd, null, DCX_WINDOW | DCX_USESTYLE).
/// </para>
/// <para>
/// GetDC calls GetDCEx(hwnd, null, DCX_USESTYLE) when given a handle. (When given null it has additional
/// logic, and can't be replaced directly by GetDCEx.
/// </para>
/// </remarks>
public GetDcScope(HWND hwnd, HRGN hrgnClip, GET_DCX_FLAGS flags)
{
HWND = hwnd;
HDC = PInvokeCore.GetDCEx(hwnd, hrgnClip, flags);
}
/// <summary>
/// Creates a DC scope for the primary monitor (not the entire desktop).
/// </summary>
/// <remarks>
/// <para>
/// <see cref="PInvokeCore.CreateDCW(PCWSTR, PCWSTR, PCWSTR, DEVMODEW*)" /> is the
/// API to get the DC for the entire desktop.
/// </para>
/// </remarks>
public static GetDcScope ScreenDC => new(HWND.Null);
public bool IsNull => HDC.IsNull;
public static implicit operator nint(in GetDcScope scope) => scope.HDC;
public static implicit operator HDC(in GetDcScope scope) => scope.HDC;
public void Dispose()
{
if (!HDC.IsNull)
{
PInvokeCore.ReleaseDC(HWND, HDC);
}
}
}
|