using System; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; using static Vanara.PInvoke.Gdi32; namespace Vanara.PInvoke { /// Extension methods to convert GdiObj handle variants to their .NET equivalents. public static class GdiObjExtensions { /// Converts the generic GDI object handle to a specific handle. /// The handle type to which to convert. /// The generic GDI object handle. /// The converted handle of type . /// The conversion type specified is not valid for the supplied GDI object. public static T ConvertTo(this IGraphicsObjectHandle hObj) where T : IGraphicsObjectHandle { var ot = GetObjectType(hObj.DangerousGetHandle()); if (ot == 0) Win32Error.ThrowLastError(); if (!CorrespondingTypeAttribute.CanGet(ot, typeof(T))) throw new ArgumentException($"The conversion type specified is not valid for the supplied GDI object."); return (T)(object)hObj.DangerousGetHandle(); } /// Draws on a device context () via a DIB section. This is useful when you need to draw on a transparent background. /// The device context. /// The bounds of the device context to paint. /// The draw method. public static void DrawViaDIB(this SafeHDC hdc, in RECT bounds, Action drawMethod) => DrawViaDIB((HDC)hdc, bounds, drawMethod); /// Draws on a device context () via a DIB section. This is useful when you need to draw on a transparent background. /// The device context. /// The bounds of the device context to paint. /// The draw method. public static void DrawViaDIB(this in HDC hdc, in RECT bounds, Action drawMethod) { // Create a memory DC so we can work off screen using var memoryHdc = CreateCompatibleDC(hdc); // Create a device-independent bitmap and select it into our DC var info = new BITMAPINFO(bounds.Width, -bounds.Height); using (memoryHdc.SelectObject(CreateDIBSection(hdc, info, DIBColorMode.DIB_RGB_COLORS, out var pBits))) { // Call method drawMethod(memoryHdc, bounds); // Copy to foreground BitBlt(hdc, bounds.Left, bounds.Top, bounds.Width, bounds.Height, memoryHdc, 0, 0, RasterOperationMode.SRCCOPY); } } /// Determines whether the bitmap is a bottom-up DIB. /// The handle of the bitmap to assess. /// if the specified bitmap is a bottom-up DIB; otherwise, . public static bool IsBottomUpDIB(this in HBITMAP hbmp) { var dibSz = Marshal.SizeOf(typeof(DIBSECTION)); using var mem = GetObject(hbmp, dibSz); return mem.Size == dibSz && mem.ToStructure().dsBmih.biHeight > 0; } /// Determines whether the bitmap is a bottom-up DIB. /// The handle of the bitmap to assess. /// if the specified bitmap is a bottom-up DIB; otherwise, . public static bool IsDIB(this in HBITMAP hbmp) { var dibSz = Marshal.SizeOf(typeof(DIBSECTION)); using var mem = GetObject(hbmp, dibSz); return mem.Size == dibSz; } } }