Edited at

GDIとGDI+の共存

More than 1 year has passed since last update.


この文書について

以下のドキュメントの和訳

https://support.microsoft.com/en-us/help/311221/info-interoperability-between-gdi-and-gdi

公式の翻訳が機械翻訳で読みにくかったため


GDI と GDI+ の 共存・混在


概要

同じアプリケーションにおいて、描画処理でGDIとGDI+を混在させることが望ましいことがあります。

GDI と GDI+ の相互運用をするにあたり、実装するにあたって留意すべき点がいくつかあります。

この文書はそうした留意点を要約し、前述した実装の一助となる追加情報を提供します。

この文書では以下の4つの主要な相互運用ケースを対象としています。


  • GDIをGDI+で描画したスクリーン上で使う

  • GDIをGDI+で描画したビットマップ上で使う

  • GDI上のHDCをGDI+で使う

  • GDIのHBITMAPをGDI+で使う


追加情報


GDIをGDI+で描画したスクリーン上で使う

GDI+で描画したスクリーンでGDIを使うときは、「ラバーバンド矩形」もしくは「フォーカス矩形」として描画される必要があります。

現状、GDI+は ラスターオペレーション(ROPs)を提供しませんので、R2_XORペンオペレーションが必要とされたときはGDIをそのまま使わなければなりません。

このケースにおいては、GDIの出力先となるHDCを Graphics::GetHDC() から取得する必要があります。

GDI+の出力は (Graphics::ReleaseHDC()が呼び出されない限り) HDCを破棄しません。

【訳者注】

MFC の CWnd::GetDC や Win32API の GetDC と同様にHDCのライフサイクルは実装者側で管理する。


GDIをGDI+で描画したビットマップ上で使う

ビットマップ上のグラフィックスオブジェクトに対して Graphics::GetHDC() が呼び出されたとき、メモリHDCが生成され、同時に新しいHBITMAPが生成されてHDCがこのHBITMAPを選択します。

この新しいメモリ上のビットマップはオリジナルのビットマップを使って初期化されていません。

Graphics::ReleaseHDC()が呼ばれると、変更がもとのビットマップに適用されます。

メモリ上のビットマップはビットマップの画像データによって初期化されていないため、得られたHDCは"書き込み専用"であり、R2_XORのようなターゲットの読み込み能力を要求されるようなラスターオペレーションには利用できません。

またGDI+が元のビットマップに変更を適用する処理のため、性能面にも影響があります。

【訳者注】


This new memory bitmap is not initialized with the original bitmap's image but rather with a sentinel pattern, which allows GDI+ to track changes to the bitmap. Any changes that are made to the memory bitmap through the use of GDI code become apparent in changes to the sentinel pattern.


sentinel patternについて理解不足のため、まだ訳ができていない


GDI上のHDCをGDI+で使う

GDI+のGraphicsのコンストラクタの引数にHDCを渡すことで、HDCに対してGDI+が利用可能です。

この場合、HDCに対してGraphicsの関数で描画できます。

一度、HDCにGraphicsオブジェクトがアタッチされると、Graphicsオブジェクトが破棄されるかもしくはスコープ外になるまでいかなるGDIオペレーションもHDCに対して適用されません。

もしHDCに対してGDI出力が必要であれば、Graphicsオブジェクトを破棄してからHDCを使うか、Graphics::GetHDC()から新しいHDCを取得して以前に説明したGDI+オブジェクト上でGDIを使う方法に従ってください。


GDIのHBITMAPをGDI+で使う

GDI+のビットマップのコンストラクタはHBITMAPを引数にとりますが、実際のところそれがそのまま利用されることはないです。

むしろ、引数のHBITMAPに対してコンストラクタでそのコピーが作成され、デストラクタの実行されるまでは元になるビットマップに変更が適用されません。

新しいビットマップは"生成時のコピー"と考えることができ、そのためGDIから取得したメモリ上のビットマップにGDI+から描画し、その変更を適用するための手順は以下のような流れになります


  1. DIBSectionを作成する

  2. メモリ上のHDCでDIBSectionを選択する

  3. GDI+でDIBSectionに描画する

  4. 途中でDIBSectionをGDIから利用する場合、Graphicsオブジェクトを破棄し、GDIでHDCを利用する

  5. Graphicsオブジェクトを破棄し、HDCからDIBSectionをクリアする

ビットマップはBIBSectionから作成することができ、 Graphics::DrawImage()のソース画像としても利用可能です。


訳者による参考資料

以下のリンクは元の文書にはありません。


Sentinel Pattern


ラスターオペレーション


ラバーバンド矩形 もしくは フォーカス矩形