Допустим, я получил объект / дескриптор HBITMAP из встроенной функции Windows. Я могу преобразовать его в управляемое растровое изображение, используя Bitmap.FromHbitmap (nativeHBitmap) , но если собственное изображение содержит информацию о прозрачности (альфа-канал), оно теряется при таком преобразовании.
Есть несколько вопросов по переполнению стека относительно этой проблемы. Используя информацию из первого ответа на этот вопрос ( Как нарисовать растровое изображение ARGB с использованием 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);
}