|
|
|
1-3-10. WM_PAINTApHelloのプロシージャの、WM_PAINT メッセージの処理を説明します。LRESULT CALLBACK ApHelloProc(HWND hWnd,UINT uMsg
,WPARAM wParam,LPARAM lParam)
{
static HFONT hFont;
static UINT idFormat = IDM_CENTER;
static LPSTR pHello = "Hello World.";
switch (uMsg)
{
:
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
RECT rc;
UINT w;
hdc = BeginPaint(hWnd,&ps);
if (hdc)
{
GetClientRect(hWnd,&rc);
SetBkMode(hdc,TRANSPARENT);
SetTextColor(hdc,RGB(0,0,255));
SelectObject(hdc,hFont);
switch (idFormat)
{
case IDM_LEFT: w = DT_LEFT; break;
case IDM_CENTER: w = DT_CENTER; break;
case IDM_RIGHT: w = DT_RIGHT; break;
}
DrawText(hdc,pHello,strlen(pHello)
,&rc,DT_SINGLELINE|DT_VCENTER|w);
}
EndPaint(hWnd,&ps);
return 0;
}
:
ApHelloにとっては、WM_PAINT メッセージがすべてと言っても良いぐらい重要な部分です。しかしこの部分は、GDIと描画の分野ですので、詳細は省きます。SetBkMode 関数で文字だけ描画して文字の背景は抜くモードに設定します。そして、SetTextColor 関数で、文字の色を青に設定し、SelectObject 関数で、WM_CREATE で作成したフォントを選択します。最後に、DrawText 関数でメッセージを表示します。
描画とHDCBeginPaint 描画は、HDCのデバイステキストのハンドルで行ないます。このハンドルがないとWindowsでは描画はできません。ユーザが勝手に描画することは御法度です。HDCの手順に従って描画する必要があります。なぜでしょうか。GUIと関係があります。Windowsは、ウィンドウが普通は描画対象ですが、その対象は、常に表示されているとは限らないからです。描画しようとしているエリアの上に、別のウィンドウが重なり、隠れているかもしれません。WindowsのHDCは、これを考慮します。もし隠れている部分があれば、クリップを設定して、複数に分けて描画して、ちゃんと見える部位にしか表示しません。またHDCには、各種のペンやブラシなどのオブジェクトが、関連付けられています。SelectObject でそれを設定します。よって描画する場合は、通常は座標だけ指定すれば、事足ります。BeginPaintとEndPaint WM_PAINT メッセージでHDCを取得するのが、BeginPaint 関数です。この関数が、他のHDCを取得する関数と違うのは、描画しないといけない範囲を得ることができることです。GetDC,GetWindowDC などはすべてのエリアが対象になります。BeginPaint 関数のパラメータの、PAINTSTRUCT 構造体の rcPaint メンバに矩形域を設定します。ただし、このHDCでクライアントエリア全体を描画できます。その中で、rcPaint には、崩れたので再描画が必要なエリアを設定します。例えば、上にあったウィンドウを移動したので、WM_PAINT が発生しました。そのウィンドウで隠れていたエリアが、rcPaint に設定されます。しかし rcPaint エリアだけ描画するか、クライアントエリア全体を描画するかは、プログラマの自由です。一般に、rcPaint エリアだけを描画する方が高速ですが、コードは面倒です。描画スピードが気にかかるかたは検討してください。ApHelloの場合は、全体を描画します。BeginPaint 関数をつかったら、最後に、EndPaint しなければいけません。
|