假设我从本机Windows函数获取HBITMAP对象/句柄。我可以使用Bitmap.FromHbitmap(nativeHBitmap)将其转换为托管位图,但如果本机图像具有透明度信息(Alpha通道),则通过此转换会丢失。在C#中使用本地HBitmap,同时保留Alpha通道/透明度
关于此问题,有几个关于Stack Overflow的问题。使用这个问题的第一个答案(How to draw ARGB bitmap using GDI+?)中的信息,我写了一段我已经尝试过的代码并且可以工作。
它基本上得到天然HBITMAP宽度,高度和使用GetObject的指针的像素数据的位置和BITMAP结构,然后调用管理位图的构造:
Bitmap managedBitmap = new Bitmap(bitmapStruct.bmWidth, bitmapStruct.bmHeight,
bitmapStruct.bmWidth * 4, PixelFormat.Format32bppArgb, bitmapStruct.bmBits);
作为我明白(如果我错了,请纠正我),它不会将本地HBitmap中的实际像素数据复制到托管位图,而只是将托管位图指向本机HBitmap中的像素数据。
而且我不在另一个图形(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);
}
像“请检查此代码,它适用于我的计算机...”真的不属于问题或主题标题。 – 2011-01-07 18:01:34
你说得对,我改了标题。这是一个问题,但它也包含代码。 – AnAurelian 2011-01-07 18:04:40