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;
}
}
}