ShowMyText(HWND hWnd)関数は自作の関数です。 このままプロシージャの所に記述してもいいのですが 長ったらしくなるので関数にしてみました。 では、この中身を見てみましょう。void ShowMyText(HWND hWnd) { HDC hdc; PAINTSTRUCT paint; char *str = "猫でもわかるプログラミング"; hdc = BeginPaint(hWnd, &paint); TextOut(hdc, 10, 10, (LPCSTR)str, strlen(str)); EndPaint(hWnd, &paint); return; }
まず、文字とかイメージを描くときはその旨宣言?しなくてはいけません。 これが、BeginPaint関数です。この時戻り値として デバイスコンテキストハンドル が得られます。以後、文字を書いたり絵を描いたりするときはこのハンドルが 必要になります。また、この関数の2番目の引数のPAINTSTRUCT構造体について 少し説明します。これは、次のように定義されています。
しかし、この中身については知らなくてもあまり問題になりません。typedef struct tagPAINTSTRUCT { // ps HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[32]; } PAINTSTRUCT;
BeginPaint関数を実行したならば必ずEndPaint関数を実行して下さい。 BeginPaint関数を書いたならばすぐ次の行にEndPaint関数を書いておいて 必要なものはこの2つの関数の間に挿入していくようにすれば 忘れることがありません。
テキストの表示はTextOut関数を使います。 最初の引数はデバイスコンテキストハンドル、次の2つが 書き始めるx,y座標、4番目が文字列のアドレス、5番目が文字数です。
最後にEndPaintを実行します。
ところで、TextOut関数では改行文字などは表現できません。 どうなるかやってみましょう。
最初のとはちょっと変えてみました。 strをLPCSTRで宣言しています。こうするとTextOutの最後の引数は lstrlen(str)としなくてはいけません。ま、横道にそれましたが strの中に\nを入れてみました。void ShowMyText(HWND hWnd) { HDC hdc; PAINTSTRUCT paint; LPCSTR str = "猫でもわかるプログラミング\n粂井康孝"; hdc = BeginPaint(hWnd, &paint); TextOut(hdc, 10, 10, str, lstrlen(str)); EndPaint(hWnd, &paint); return; }
改行は表現されず黒い四角形が
現れました。
もうちょっと便利な関数にDrawText関数があります。 これは、改行も表現してくれます。 VC++4.2のヘルプでこの関数の引数などを見てみましょう。
最初の引数はデバイスコンテキストハンドル、2番目は表示する文字列です。 3番目の引数は文字列の長さ(バイト)ですが、これを−1に指定すると 自動的に文字列の長さになります。4番目の引数は文字列を表示する 領域でRECT構造体へのポインタです。これについては、あとで解説します。 最後の引数はいろいろなものを設定できます。代表的なものは DT_WORDBREAKです。これはlpRectで指定した 領域に行が収まらないとき自動的に折り返しをしてくれるものです。 他にもいろいろ指定できますのでヘルプで確認してみて下さい。int DrawText( HDC hDC, // handle to device context LPCTSTR lpString, // pointer to string to draw int nCount, // string length, in characters LPRECT lpRect, // pointer to structure with formatting dimensions UINT uFormat // text-drawing flags );
さて、次はRECT構造体ですが、これは非常に簡単です。
のように定義されています。四角形を考えると 左上の座標が(left, top)右下の座標が(right, bottom)となると、 覚えておくとわかりやすいでしょう。typedef struct _RECT { // rc LONG left; LONG top; LONG right; LONG bottom; } RECT;
ついでにもう少しよく使う関数について説明します。 sprintfはMS-DOSのプログラムの時よく使いました。 WINDOWSのプログラムではこれに変わってwsprintfがよく使われます。 引数のデータ型が少し違うので注意して下さい。 入門書によってはsprintfの方は問題が起きることがあるので なるべく使わないようにと書いてあるものもあります。 でも、使っても差し支えありません。 (どうも言っていることが矛盾しているな)
2番目と3番目の引数の型に注意して下さい。int wsprintf( LPTSTR lpOut, // pointer to buffer for output LPCTSTR lpFmt, // pointer to format-control string ... // optional arguments );
それと、表示するテキストの色を変えるのは SetTextColor関数で簡単に行うことができます。
データ型COLORREFは色を表す32ビット値です。 普通はマクロRGBを使って簡単に表現することができます。 RGB(255, 0, 0)なら赤、RGB(0, 255, 0)なら緑、 RGB(0, 0, 255)なら青、RGB(255, 255, 255)なら白を表します。 ホームページを書いたことのある人ならピンときますね。 <FONT COLOR="#FF0000">などというタグを書いた経験はありませんか? さて、それでは今までの知識を使って少しプログラムを書き換えてみましょう。COLORREF SetTextColor( HDC hdc, // handle of device context COLORREF crColor // text color );
GetClientRect関数は読んで字のごとくクライアント 領域の範囲(大きさ)を取得してRECT構造体に納めるものです。 そして、この値をwsprintf関数でstrxに書き込んでいます。void ShowMyText(HWND hWnd) { HDC hdc; char *str_org = "left=%d top=%d right=%d bottom=%d"; char strx[256]; PAINTSTRUCT paint; RECT rt; LPCSTR str = "猫でもわかるプログラミング\n粂井康孝 制作\n" "わかりやすくてためになる!"; GetClientRect(hWnd, &rt); wsprintf((LPSTR)strx, (LPCSTR)str_org, rt.left, rt.top, rt.right, rt.bottom); rt.top += 40; rt.bottom -= 40; rt.right -= 40; rt.left += 40; hdc = BeginPaint(hWnd, &paint); SetTextColor(hdc, RGB(255, 0, 0)); TextOut(hdc, 10, 10, (LPSTR)strx, strlen(strx)); SetTextColor(hdc, RGB(0, 0, 255)); DrawText(hdc, str, -1, &rt, DT_WORDBREAK); EndPaint(hWnd, &paint); return; }
それでは、このプログラムを実行してみましょう。
改行文字もきちんと表現されています。
ウィンドウの大きさをいろいろに変えると
赤字で表示されている数値も変化します。
青字の周りは40ドット以上あいています。
ウィンドウ幅を狭くするとTextOutで書いた
赤字の表示は切れてしまいますが、
DrawTextで書いた青字の表示はうまいこと折り返して
います。青字の周りは40ドットあいています。
テキストの表示に関する細かい指定は
まだまだたくさんあります。必要が生じたら
その都度説明します。
Update Mar/22/1997 By Y.Kumei