来自Image.FromHbitmap()
在http://msdn.microsoft.com/en-us/library/k061we7x%28VS.80%29.aspx上的文档:
-- FromHbitmap方法复制GDI位图;因此,在创建新图像之后,可以立即使用GDIDeleteObject方法释放传入的GDI位图。
这非常明确地声明,位图句柄可以在创建位图实例后立即用DeleteObject删除。
然而,看看Reflector的Image.FromHbitmap()
实现,就会发现它是GDI+函数GdipCreateBitmapFromHBITMAP()
的一个非常薄的包装器。
关于GDI+平面API函数的文档很少,但是http://msdn.microsoft.com/en-us/library/ms533971%28VS.85%29.aspx说GdipCreateBitmapFromHBITMAP()
对应于以HBITMAP
和HPALETTE
作为参数的Bitmap::Bitmap()
构造函数。
这个版本的Bitmap::Bitmap()
构造函数在http://msdn.microsoft.com/en-us/library/ms536314%28VS.85%29.aspx上的文档中有这样的内容:
您负责删除GDI位图和GDI调色板。但是,在GDI+位图::位图对象被删除或超出范围后,您不应该删除GDI位图或GDI调色板。
不要传递给GDI+位图::位图构造器、GDI位图或当前(或以前)被选中到设备上下文中的GDI调色板。
此外,在GdiPlusBitmap.h中GDI+的GDI+部分的源代码中可以看到,所讨论的Bitmap::Bitmap()
构造函数本身就是平面API中的GdipCreateBitmapFromHBITMAP()
函数的包装器:
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+位图。
因此,总括而言:
是否需要保留原始位图处理,直到disposed?
GdipCreateBitmapFromHBITMAP()
、复制源位图或仅保留original?
发布于 2010-06-21 17:39:18
从经验上看,.Net文档似乎是正确的。人们确实可以立即调用DeleteObject()
,将HBITMAP传递给Image.FromHbitmap()
,这样做似乎没有任何不良影响。
根据我通过逆向工程了解到的代码,同样的情况也适用于GDI+ Bitmap::Bitmap()
构造函数和GDI+ GdipCreateBitmapFromHBITMAP()
函数,尽管这与已发布的文档相矛盾。
也许GDI+文档过于保守--保留在未来版本中保留所提供的HBITMAP句柄的权利。如果在GDI+中发生这种更改,则.Net框架将不得不进行更改,以便在将位图副本传递给GDI+之前保留其已发布的合同。
https://stackoverflow.com/questions/3057002
复制相似问题