GDIとGDIオブジェクト

今回からは、GDI(Graphic Device Interface)のお話になります。
視覚に訴えるグラフィカルなプログラムは楽しいですから
クラスだのなんだのわけわかんねー自分みたいなのでも
やってやるぜー!、という気になります。
(いやちゃんとクラスの勉強しろよ・・・)

・GDIとGDIオブジェクト

GDIというのはWindowsに搭載されたプログラムの一つで、
ディスプレイやプリンタをコントロールするものです。
これを使うことによって、ウィンドウに描画することになります。

他のプログラムがGDIを使うために便利な機能を
GDIはオブジェクトとして用意しています。

   OBJ_DC デバイスコンテキスト
   OBJ_MEMDC メモリデバイスコンテキスト
   OBJ_PEN ペン
   OBJ_BRUSH ブラシ
   OBJ_PAL パレット
   OBJ_FONT フォント
   OBJ_BITMAP ビットマップ
   OBJ_REGION リージョン
   OBJ_ENHMETADC 拡張メタファイルデバイスコンテキスト
   OBJ_ENHMETAFILE 拡張メタファイル

とりあえずPocketGCCの Wingdi.h の中で定義されているのはこれくらいでした。

実際にプログラムからGDIを介してウィンドウに描画するためには
オブジェクトの1つである、デバイスコンテキスト(DC)に対して出力を行う事になります。
よく言われる例えでいうと、GDIは絵を描くための道具(オブジェクト)一式で
デバイスコンテキストが絵を描く紙などの画材で
ペンやブラシは描画するための絵筆など、といった感じでしょうか。

・デバイスコンテキスト

デバイスコンテキストオブジェクトを使うには
今までもWM_PAINT内で使ってきましたが、HDCという
デバイスコンテキストへのハンドルを介して処理を行います。
描画の手順としては、おおまかに2通りあります。

1つ目は今まで使っていたWM_PAINT内で
BeginPaint関数でデバイスコンテキストのハンドルを取得し
描画処理を行った後、EndPaint関数を使って
取得したデバイスコンテキストを解放する方法ですね。

2つ目は、GetDC関数でデバイスコンテキストのハンドルを取得し
描画処理を行った後、ReleaseDC関数により
デバイスコンテキストを解放するやり方です。
(または、CreateDC関数でデバイスコンテキストを作成・取得し
DeleteDC関数で削除することもあります。)

はじめの方法では無効領域ができれば勝手に呼ばれて描画処理をしてくれるのに
後の方法では自分で描画するよう指定してあげないと描画してくれませんね。
しかし、仮想画面を作る、などいろんなところで活躍の場面があります。

両者の共通点は、デバイスコンテキストを取得して用が終わったら
解放して(削除して)あげないといけないところです。

・オブジェクトの作成と削除

デバイスコンテキストに限らず、ペン・ブラシの作成などで
GDIオブジェクトを作成・取得すると、メモリが確保されるので
プログラム内で作成した使用済みのGDIオブジェクトは
そのプログラムが終了するまでに必ず削除する必要があります。
(終了してもメモリは自動的には解放されません)
それを怠るとメモリが解放されず、メモリリークの原因になります。
以下にペンオブジェクトの作成~削除処理の一例を書きます。

     //作成するペン,デフォルトのペン
     HPEN hPen,hPenOld;
     hPen = CreatePen ( BS_SOLID, 1, RGB(0,255,255) );
     …
     hPenOld = SelectObject ( hDC, hPen );
     …
     SelectObject ( hDC, hPenOld );
     DeleteObject(hPen);

ここでは各関数の詳細な説明はしませんが
SelectObjectで、デバイスコンテキストhDCで作成したペンhPenを選択し
そのデバイスコンテキストで作成したペンを使えるようにします。
戻り値として、デバイスコンテキストが以前使用していた(デフォルトの)ペンが
hPenOldに入ります。描画処理が終わればSelectObjectで
デバイスコンテキストとデフォルトのペンを選択し、
用の終わった、作成したペンをDeleteObjectにより削除しています。
(元々存在していた、デフォルトのペンは削除する必要がありません。念のため)

2005/5/22


戻る