假設我從本機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