代码之家  ›  专栏  ›  技术社区  ›  GBegen

当用image.fromhbitmap()构造位图时,原始位图句柄多久可以被删除?

  •  5
  • GBegen  · 技术社区  · 14 年前

    从文件中 Image.FromHbitmap() http://msdn.microsoft.com/en-us/library/k061we7x%28VS.80%29.aspx :

    fromhbitmap方法复制了gdi位图;因此您可以在创建新图像后立即使用gdieleteObject方法释放传入的gdi位图。

    这非常明确地说明,一旦创建位图实例,就可以立即使用DeleteObject删除位图句柄。

    查看的实现 图片.fromhbitmap()) 然而,使用Reflector,它表明它是围绕gdi+函数的一个非常薄的包装器, GdipCreateBitmapFromHBITMAP() .

    关于gdi+平面API函数的文档很少,但是 http://msdn.microsoft.com/en-us/library/ms533971%28VS.85%29.aspx gdipCreateBitMapFromhBitmap()。 对应于 Bitmap::Bitmap() 采用 HBITMAP 和一个 HPALETTE 作为参数。

    此版本的文档 位图::位图() 构造函数在 http://msdn.microsoft.com/en-us/library/ms536314%28VS.85%29.aspx 必须说明:

    您负责删除gdi位图和gdi调色板。但是,在gdi+bitmap::bitmap对象被删除或超出作用域之前,不应该删除gdi位图或gdi调色板。

    不要向gdi+bitmap::bitmap构造函数传递当前(或以前)选定到设备上下文中的gdi位图或gdi调色板。

    此外,可以在源代码中看到gdi+位图中C++部分的C++部分。 位图::位图() 所讨论的构造函数本身是 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+位图的使用。

    因此,总结如下:

    1. 在释放.NET位图对象之前,是否需要保留原始位图句柄?
    2. gdi+是否起作用? gdipCreateBitMapFromhBitmap()。 ,复制源位图,还是只保留原始位图的句柄?
    3. 为什么我不应该使用以前被选入设备上下文的hbitmap?
    1 回复  |  直到 14 年前
        1
  •  2
  •   GBegen    14 年前

    从经验上看,.NET文档似乎是正确的。一个人确实可以立即打电话 DeleteObject() 在传送给 Image.FromHbitmap() 这样做似乎没有什么不良影响。

    根据我从逆向工程代码中学到的知识,这同样适用于GDI。+ Bitmap::Bitmap() 建造商和GDI+ GdipCreateBitmapFromHBITMAP() 功能也一样,尽管这与已发布的文档相矛盾。

    也许GDI+文档过于保守——保留在未来版本中保留所提供的HBitmap句柄的权利。如果在gdi+中发生这种更改,.NET框架必须进行更改,以便在将位图传递给gdi+之前,通过制作位图的副本来保留其已发布的协定。