Из документации Image.FromHbitmap()
в http://msdn.microsoft.com/en-us/library/k061we7x%28VS.80%29.aspx:
Метод FromHbitmap создает копию растрового изображения GDI; так что вы можете освободить входящее растровое изображение GDI, используя метод GDIDeleteObject, сразу после создания нового образа.
Это довольно явно говорит о том, что дескриптор растрового изображения может быть немедленно удален с помощью DeleteObject, как только будет создан экземпляр растрового изображения.
Однако, глядя на реализацию Image.FromHbitmap()
с Reflector, видно, что это довольно тонкая оболочка для функции GDI +, GdipCreateBitmapFromHBITMAP()
.
Существует довольно скудная документация по функциям плоского API GDI +, но http://msdn.microsoft.com/en-us/library/ms533971%28VS.85%29.aspx говорит, что GdipCreateBitmapFromHBITMAP()
соответствует конструктору Bitmap::Bitmap()
, который принимает HBITMAP
и HPALETTE
в качестве параметров.
Документация для этой версии Bitmap::Bitmap()
конструктора в http://msdn.microsoft.com/en-us/library/ms536314%28VS.85%29.aspx содержит следующее:
Вы несете ответственность за удаление растрового изображения GDI и палитры GDI. Однако не следует удалять растровое изображение GDI или палитру GDI до тех пор, пока объект GDI + Bitmap :: Bitmap не будет удален или выйдет из области видимости.
Не передавайте в конструктор GDI + Bitmap :: Bitmap растровое изображение GDI или палитру GDI, которые в настоящее время (или ранее) были выбраны в контексте устройства.
Кроме того, в исходном коде для C ++ части GDI + в GdiPlusBitmap.h можно увидеть, что рассматриваемый конструктор Bitmap::Bitmap()
сам является оболочкой для функции GdipCreateBitmapFromHBITMAP()
из плоского API:
inline
Bitmap::Bitmap(
IN HBITMAP hbm,
IN HPALETTE hpal
)
{
GpBitmap *bitmap = NULL;
lastResult = DllExports::GdipCreateBitmapFromHBITMAP(hbm, hpal, &bitmap);
SetNativeImage(bitmap);
}
Что я не могу легко увидеть, так это реализацию GdipCreateBitmapFromHBITMAP()
, которая является ядром этой функциональности, но два замечания в документации кажутся противоречивыми. В документации .Net говорится, что я могу немедленно удалить дескриптор растрового изображения, а в документации GDI + говорится, что дескриптор растрового изображения должен храниться до тех пор, пока объект обертки не будет удален, но оба они основаны на одной и той же функции GDI +.
Кроме того, документация GDI + предостерегает от использования исходного HBITMAP, который в настоящее время или ранее выбран в контексте устройства. Хотя я могу понять, почему растровое изображение не следует выбирать в контексте устройства в настоящее время, я не понимаю, почему существует предупреждение против использования растрового изображения, которое ранее было выбрано в контексте устройства. Это могло бы предотвратить использование растровых изображений GDI +, созданных в памяти с использованием стандартного GDI.
Итак, в итоге:
- Нужно ли сохранять исходный дескриптор растрового изображения до тех пор, пока объект .Net Bitmap не будет удален?
- Делает ли функция GDI +,
GdipCreateBitmapFromHBITMAP()
, копию исходного растрового изображения или просто удерживает маркер на оригинале?
- Почему я не должен использовать HBITMAP, который был ранее выбран в контексте устройства?