using System; using System.Runtime.InteropServices; namespace Vanara.PInvoke { public static partial class Gdi32 { /// Provides a selection context for graphics objects. /// /// /// using (var screenDC = SafeHDC.ScreenCompatibleDCHandle) /// { /// var brush = CreateSolidBrush(Color.Red); /// using (new GdiObjectContext(screenDC, brush)) /// { /// // Do brush stuff /// } /// /// var pen = CreatePen(PS_SOLID, 1, Color.Black); /// // Alternatively, call the SelectObject method on the SafeHDC object /// using (screenDC.SelectObject(pen)) /// { /// // Do pen stuff /// } /// } /// /// /// public class GdiObjectContext : IDisposable { private readonly HDC hDC; private readonly HGDIOBJ hOld; /// Initializes a new instance of the class. /// The HDC into which is selected. /// The graphics object to select. /// hdc - Device context cannot be null. public GdiObjectContext(HDC hdc, HGDIOBJ hObj) { if (hdc.IsNull) throw new ArgumentNullException(nameof(hdc), "Device context cannot be null."); hDC = hdc; hOld = SelectObject(hdc, hObj); } /// void IDisposable.Dispose() => SelectObject(hDC, hOld); } /// /// Provides a to a graphics bitmap object that releases a created HBITMAP instance at disposal using DeleteObject. /// public class SafeHBITMAP : SafeHANDLE, IGraphicsObjectHandle { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHBITMAP(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHBITMAP() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HBITMAP(SafeHBITMAP h) => h.handle; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HGDIOBJ(SafeHBITMAP h) => h.handle; /// protected override bool InternalReleaseHandle() => DeleteObject(this); } /// /// Provides a to a graphics bitmap object that releases a created HBRUSH instance at disposal using DeleteObject. /// public class SafeHBRUSH : SafeHANDLE, IGraphicsObjectHandle { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHBRUSH(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHBRUSH() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HBRUSH(SafeHBRUSH h) => h.handle; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HGDIOBJ(SafeHBRUSH h) => h.handle; /// protected override bool InternalReleaseHandle() => DeleteObject(this); } /// A SafeHandle to track DC handles. public class SafeHDC : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHDC(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHDC() : base() { } /// Gets the screen compatible device context handle. /// The screen compatible device context handle. public static SafeHDC ScreenCompatibleDCHandle => CreateCompatibleDC(HDC.NULL); /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HDC(SafeHDC h) => h.handle; /// Gets the compatible device context handle. /// A device context handle. public SafeHDC GetCompatibleDCHandle() => CreateCompatibleDC(handle); /// Creates a context into which a graphics object is selected. /// The graphics object to select. /// A selection context for the graphics object. public GdiObjectContext SelectObject(HGDIOBJ hObject) => new GdiObjectContext(handle, hObject); /// protected override bool InternalReleaseHandle() { return DeleteDC(handle); } } /// /// Provides a to a graphics bitmap object that releases a created HFONT instance at disposal using DeleteObject. /// public class SafeHFONT : SafeHANDLE, IGraphicsObjectHandle { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHFONT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHFONT() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HFONT(SafeHFONT h) => h.handle; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HGDIOBJ(SafeHFONT h) => h.handle; /// protected override bool InternalReleaseHandle() => DeleteObject(this); } /// /// Provides a to a graphics color palette object that releases a created HPALETTE instance at disposal /// using DeleteObject. /// public class SafeHPALETTE : SafeHANDLE, IGraphicsObjectHandle { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHPALETTE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHPALETTE() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HGDIOBJ(SafeHPALETTE h) => h.handle; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HPALETTE(SafeHPALETTE h) => h.handle; /// protected override bool InternalReleaseHandle() => DeleteObject(this); } /// /// Provides a to a graphics bitmap object that releases a created HPEN instance at disposal using DeleteObject. /// public class SafeHPEN : SafeHANDLE, IGraphicsObjectHandle { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHPEN(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHPEN() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HGDIOBJ(SafeHPEN h) => h.handle; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HPEN(SafeHPEN h) => h.handle; /// protected override bool InternalReleaseHandle() => DeleteObject(this); } /// /// Provides a to a graphics bitmap object that releases a created HRGN instance at disposal using DeleteObject. /// public class SafeHRGN : SafeHANDLE, IGraphicsObjectHandle { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHRGN(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHRGN() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HGDIOBJ(SafeHRGN h) => h.handle; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HRGN(SafeHRGN h) => h.handle; /// protected override bool InternalReleaseHandle() => DeleteObject(this); } } }