5

http://msdn.microsoft.com/en-us/library/k061we7x%28VS.80%29.aspxImage.FromHbitmap()のドキュメントから:

FromHbitmapメソッドは、GDIビットマップのコピーを作成します。そのため、新しいイメージを作成した直後に、GDIDeleteObjectメソッドを使用して着信GDIビットマップを解放できます。

これは、ビットマップインスタンスが作成されるとすぐに、DeleteObjectを使用してビットマップハンドルをすぐに削除できることを明確に示しています。

ただし、with Reflectorの実装を見るとImage.FromHbitmap()、GDI+関数のかなり薄いラッパーであることがわかりますGdipCreateBitmapFromHBITMAP()

GDI +フラットAPI関数に関するドキュメントはほとんどありませんが、http://msdn.microsoft.com/en-us/library/ms533971%28VS.85%29.aspxによると、GdipCreateBitmapFromHBITMAP()これBitmap::Bitmap()は、パラメーター。HBITMAPHPALETTE

http://msdn.microsoft.com/en-us/library/ms536314%28VS.85%29.aspxにあるこのバージョンのBitmap::Bitmap()コンストラクターのドキュメントには、次のように書かれています。

GDIビットマップとGDIパレットを削除するのはあなたの責任です。ただし、GDI + Bitmap :: Bitmapオブジェクトが削除されるか、スコープ外になるまで、GDIビットマップまたはGDIパレットを削除しないでください。

GDI + Bitmap :: Bitmapコンストラクターに、デバイスコンテキストで現在(または以前に)選択されているGDIビットマップまたはGDIパレットを渡さないでください。

さらに、GdiPlusBitmap.hのGDI+のC++部分のソースコードで、問題のコンストラクター自体がフラットAPIの関数Bitmap::Bitmap()のラッパーであることがわかります。GdipCreateBitmapFromHBITMAP()

inline 
Bitmap::Bitmap(
    IN HBITMAP hbm, 
    IN HPALETTE hpal
    )
{
    GpBitmap *bitmap = NULL;

    lastResult = DllExports::GdipCreateBitmapFromHBITMAP(hbm, hpal, &bitmap);

    SetNativeImage(bitmap);
}

私が簡単に理解できないのはGdipCreateBitmapFromHBITMAP()、この機能のコアである実装ですが、ドキュメントの2つの注釈は矛盾しているようです。.Netのドキュメントには、ビットマップハンドルをすぐに削除できると記載されており、GDI +のドキュメントには、ラッピングオブジェクトが削除されるまでビットマップハンドルを保持する必要があると記載されていますが、どちらも同じGDI+関数に基づいています。

さらに、GDI +ドキュメントは、デバイスコンテキストで現在または以前に選択されたソースHBITMAPを使用しないように警告しています。現在、ビットマップがデバイスコンテキストで選択されるべきではない理由は理解できますが、以前にデバイスコンテキストで選択されたビットマップを使用することに対する警告がある理由は理解できません。これにより、標準のGDIを使用してメモリ内に作成されたGDI+ビットマップを使用できなくなるようです。

したがって、要約すると:

  1. .Net Bitmapオブジェクトが破棄されるまで、元のビットマップハンドルを保持する必要がありますか?
  2. GDI +関数はGdipCreateBitmapFromHBITMAP()、ソースビットマップのコピーを作成しますか、それとも単にオリジナルへのハンドルを保持しますか?
  3. 以前にデバイスコンテキストに選択されたHBITMAPを使用しないのはなぜですか?
4

1 に答える 1

2

経験的に、.Netのドキュメントは正しいようです。DeleteObject()実際、渡されたHBITMAPをすぐに呼び出すことができImage.FromHbitmap()、そうしても悪影響はないようです。

コードをリバースエンジニアリングして学んだことに基づいて、GDI+Bitmap::Bitmap()コンストラクターとGDI+GdipCreateBitmapFromHBITMAP()関数にも同じことが当てはまりますが、これは公開されているドキュメントと矛盾します。

おそらく、GDI +のドキュメントは過度に保守的であり、将来のバージョンでは、提供されているHBITMAPハンドルを保持する権利を留保します。その変更がGDI+で発生した場合、.Netフレームワークは、GDI +に渡す前にビットマップのコピーを作成することにより、公開されたコントラクトを保持するように変更する必要があります。

于 2010-06-21T17:39:18.220 に答える