假设我从本地Windows函数获取了一个HBITMAP对象/句柄。我可以使用Bitmap.FromHbitmap(nativeHBitmap)将其转换为托管位图,但是如果本地图像具有透明度信息(alpha通道),则此转换会丢失该信息。
关于这个问题,在Stack Overflow上有一些问题。使用这个问题的第一个答案(如何使用GDI+绘制ARGB位图?)中的信息,我编写了一段代码并尝试过它可以工作。
基本上,它获取本地HBitmap的宽度、高度和像素数据位置的指针,使用GetObject和BITMAP结构,然后调用托管位图构造函数:
据我理解(如果我有错,请纠正),这并不是将本地 HBitmap 的实际像素数据复制到托管位图中,而是仅将托管位图指向来自本地 HBitmap 的像素数据。
在此处,我不会在另一个 Graphics(DC)或另一个位图上绘制位图,以避免不必要的内存复制,特别是对于大型位图。
我可以简单地将此位图分配给 PictureBox 控件或 Form BackgroundImage 属性。它能够正确显示位图,并使用透明度。
当我不再使用该位图时,我确保 BackgroundImage 属性不再指向该位图,并且释放了托管位图和本地 HBitmap。
问题是:您能告诉我这个推理和代码是否正确吗?我希望不会出现一些意外的行为或错误。我也希望我正在正确释放所有的内存和对象。
关于这个问题,在Stack Overflow上有一些问题。使用这个问题的第一个答案(如何使用GDI+绘制ARGB位图?)中的信息,我编写了一段代码并尝试过它可以工作。
基本上,它获取本地HBitmap的宽度、高度和像素数据位置的指针,使用GetObject和BITMAP结构,然后调用托管位图构造函数:
Bitmap managedBitmap = new Bitmap(bitmapStruct.bmWidth, bitmapStruct.bmHeight,
bitmapStruct.bmWidth * 4, PixelFormat.Format32bppArgb, bitmapStruct.bmBits);
据我理解(如果我有错,请纠正),这并不是将本地 HBitmap 的实际像素数据复制到托管位图中,而是仅将托管位图指向来自本地 HBitmap 的像素数据。
在此处,我不会在另一个 Graphics(DC)或另一个位图上绘制位图,以避免不必要的内存复制,特别是对于大型位图。
我可以简单地将此位图分配给 PictureBox 控件或 Form BackgroundImage 属性。它能够正确显示位图,并使用透明度。
当我不再使用该位图时,我确保 BackgroundImage 属性不再指向该位图,并且释放了托管位图和本地 HBitmap。
问题是:您能告诉我这个推理和代码是否正确吗?我希望不会出现一些意外的行为或错误。我也希望我正在正确释放所有的内存和对象。
private void Example()
{
IntPtr nativeHBitmap = IntPtr.Zero;
/* Get the native HBitmap object from a Windows function here */
// Create the BITMAP structure and get info from our nativeHBitmap
NativeMethods.BITMAP bitmapStruct = new NativeMethods.BITMAP();
NativeMethods.GetObjectBitmap(nativeHBitmap, Marshal.SizeOf(bitmapStruct), ref bitmapStruct);
// Create the managed bitmap using the pointer to the pixel data of the native HBitmap
Bitmap managedBitmap = new Bitmap(
bitmapStruct.bmWidth, bitmapStruct.bmHeight, bitmapStruct.bmWidth * 4, PixelFormat.Format32bppArgb, bitmapStruct.bmBits);
// Show the bitmap
this.BackgroundImage = managedBitmap;
/* Run the program, use the image */
MessageBox.Show("running...");
// When the image is no longer needed, dispose both the managed Bitmap object and the native HBitmap
this.BackgroundImage = null;
managedBitmap.Dispose();
NativeMethods.DeleteObject(nativeHBitmap);
}
internal static class NativeMethods
{
[StructLayout(LayoutKind.Sequential)]
public struct BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public ushort bmPlanes;
public ushort bmBitsPixel;
public IntPtr bmBits;
}
[DllImport("gdi32", CharSet = CharSet.Auto, EntryPoint = "GetObject")]
public static extern int GetObjectBitmap(IntPtr hObject, int nCount, ref BITMAP lpObject);
[DllImport("gdi32.dll")]
internal static extern bool DeleteObject(IntPtr hObject);
}