ネイティブ Windows 関数から HBITMAP オブジェクト/ハンドルを取得するとします。Bitmap.FromHbitmap(nativeHBitmap)を使用してマネージド ビットマップに変換できますが、ネイティブ イメージに透明度情報 (アルファ チャネル) がある場合、この変換によって失われます。
この問題に関して、Stack Overflow でいくつか質問があります。この質問の最初の回答 ( GDI+ を使用して ARGB ビットマップを描画する方法は? ) の情報を使用して、試したコードを書きましたが、動作します。
これは基本的に、 GetObjectとBITMAP構造体を使用して、ネイティブの HBitmap の幅、高さ、およびピクセル データの場所へのポインターを取得し、マネージド 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);
}