2009年06月04日

第0x03回 初めてのグラフィックプログラム

前回までで、ウィンドウを表示することができました。
実際にウィンドウを表示したら次の段階として、
ウィンドウの中に画像やテキストなどを描画するという
要求が発生します。
今回は、それらの基本的な描画について
説明していきたいと思います。

Windowsでは、テキストや画像をする際に、
ウィンドウに直接要求を出さず、一段階クッションをおき、
抽象化を行っています。
この抽象化の部分を『デバイスコンテキスト』と呼んでいます。
デバイスコンテキストを用いることで、
ウィンドウへの表示はもちろんのこと、
印刷などの作業もデバイステキストを用いて行うので、
共通化させることができるなどのメリットがあります。

描画処理 → デバイスコンテキスト →ウィンドウ
→印刷



それでは早速サンプルプログラムを見ていくことにしましょう。

sample003.cpp(ソースコードのみ)
sample003.zip(VS.NET 2008プロジェクト)


順を追って重要なポイント見ていきましょう。

case WM_PAINT:


WM_PAINTメッセージとは、ウィンドウが再描画されるべきタイミングで
呼ばれるものです。
具体的には、次のような状況でWM_PAINTメッセージが発生します。

・ウィンドウのサイズが変更された
・ウィンドウが最小化から最大化など状態が変化した
・ウィンドウで隠されていた部分が表示された

一般的にはこのWM_PAINTメッセージ処理に
ウィンドウの描画処理を記述します。

ウィンドウに描画するためには、まずウィンドウの
デバイスコンテキストを取得する必要があります。
取得する方法として、次の2種類があります。

hdc = BeginPaint( hWnd , &ps );
// ... 描画処理 ...
EndPaint( hWnd , &ps );



hdc = GetDC( hWnd );
// ... 描画処理 ...
ReleaseDC( hWnd , hdc );


上と下は共にウィンドウのデバイスコンテキストを取得する関数です。
BeginPaint()もしくはGetDC()の戻り値としてHDCが返されます。
HDCは、デバイスコンテキストのハンドルになります。
WM_PAINT内では、GetDC()関数を使うことはできないので、
BeginPaint()関数でデバイスコンテキストを取得します。
取得したデバイスコンテキストは、使用後、解放する必要があります。

デバイスコンテキストが取得できたら、それを使い実際に
描画をしていきます。
線を描画する関数は次のとおりです。

MoveToEx( hdc , 150 , 200 , NULL );
LineTo( hdc , 400 , 450 );


描画を行う関数は、基本的にデバイスコンテキストを引数として
渡します。
まず、MoveToEx()関数で現在のカレントポジションを変更します。
第2引数、第3引数で、移動するカレントポジションを指定します。
続くLineTo()関数で、実際に線を描画します。
LineTo()関数は、現在のカレントポジションから
第2引数、第3引数で指定した座標まで線を引きます。
その後、カレントポジションは指定の場所まで移動します。

四角形や、円なども同様にデバイスコンテキストを用いて
描画することができます。
これらの図形を描画する関数を
『GDI(Graphics Device Interface)』と呼びます。
また、WindowsXPで新しく登場したGDI+というものもあり、
それを使うことにより高度な表現もできるようになりました。

テキストの描画を行う関数は次のとおりです。

TextOut( hdc , 100 , 400 , szBuffer , lstrlen( szBuffer ) );


第2引数、第3引数で表示する座標を指定し、
第4引数で文字列、第5引数で文字列のサイズを指定します。
この関数は、改行することができませんので、
改行が必要な場合、適切に配置する必要があります。


これらの図形描画を行う際に、色や種類を指定することも
できます。
線の形状を指定するものを『ペン』、
塗りつぶしの形状を指定するものを『ブラシ』と呼びます。
これらは、『リソース』と呼ばれているもので、
リソースは不要になった時に必ず解放を行わなければなりません。

ペンの作成は次のとおりです。

hPen = CreatePen( PS_SOLID , 2 , RGB(0,0,255) );
// ... ペンの使用 ...
DeleteObject( hPen );


CreatePen()関数で、ペンの作成を行います。
第1引数でペンのタイプ、第2引数で太さ、第3引数で色を指定します。
戻り値で、作成されたペンのハンドルが返ってきます。
不要になった場合、DeleteObject()関数で解放を行います。

作成されたペンを実際に使用するためには、
デバイスコンテキストに関連付けを行わなければなりません。

hOldPen	= (HPEN)SelectObject( hdc , hPen );


SelectObject()関数で、デバイスコンテキストに関連付けを行います。
この関数は少し特殊で、ペンやブラシなどのリソース全てを
この関数で行います。関数は、引数で渡された変数のタイプにより
判別することになります。
戻り値としてHGDIOBJが返されますが、これは入力された引数に
応じてキャストして使用することになります。
なお、戻り値として以前に関連付けられていたペンが返されます。
元に戻す場合には、このハンドルを使いSelectObject()で
戻すことになります。
関連付けられた状態で、DeleteObject()などで解放してしまうと
予想できない状態になってしまいますので、
DeleteObject()をする前に古いリソースに戻してから
解放するのが行儀のよいプログラムと言えます。
ペンを関連付けられたことにより、
これ以降、線描画などで新たなペンを使用して
描画するようになります。


以上で、基本的な描画ができるようになりました。
次回は、メニューやアイコン、カーソルなどについて
解説したいと思います。


ラベル:ふわ猫
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。