Version 10.21
ツールバーとクライアントエリア
「前回はウィンドウに文字列を表示してみました」
『前にやったのの SDK 版ってことだったんだよね。でも』
TextOut
( hDC
, 0
, 28
, pchText
, strlen( pchText )
);
『の 28 ってのが謎なのよねー』
「試しに 0 にしてみると?」
『ビルドして実行。あ”、なんも表示されなくなっちゃった……』
「実はこの時、文字列はツールバーの裏に表示されてるんです」
『えっ? あっ、ってことは 28 ってツールバーの高さ!?』
「そう。【クライアントエリア】って憶えてる?」
『うん、 Version 7.02 ( No.122 ) でやったね。タイトルバーやメニュー
じゃない、こっちが描画していい部分のことだよね』
「そのクライアントエリアはメニューの中、つまり、ツールバーはそのクラ
イアントの中に置いてあるんです」
『げ! ツールバー置いたらその分クライアントエリアが狭くなるわけじゃ
ないの???』
「そうじゃないんです。だから、その分ずらして描画する必要があるわけ」
『うー』
「ちなみに、この 28 って数字はツールバーの状態で変わるから、実際には
実行時に取得した値を使った方がいいかな」
『どゆこと?』
「えっとね……ツールバーって OnCreate() で作ってるよね」
『うん』
「その上にこの変数を置いて」
int g_iToolBarHeight; // ツールバーの高さ。
『グローバル変数ってヤツ?』
「そういうこと。で、 OnCreate() の最後に3行追加します」
// ウィンドウが作られます。
LRESULT OnCreate
( HWND p_hWnd
, WPARAM p_wParam
, LPARAM p_lParam
)
{
// 中略。 Version 10.19 ( No.197 ) のと同じ。
// ツールバーの高さを取得します。
RECT stRect;
GetWindowRect( hToolBarWnd, &stRect );
g_iToolBarHeight = stRect.bottom - stRect.top;
return 0;
}
『 GetWindowRect() ってウィンドウの位置とか高さとか取得するのだよ
ね。 hToolBarWnd はツールバーのウィンドウハンドル……そっか、これで
ツールバーの高さがわかるんだ』
「この API でツールバーのウィンドウの上側の位置と下側の位置を取得し
て、それを引けば高さになるから。で、さっきの 28 の所は」
TextOut
( hDC
, 0
, g_iToolBarHeight
, pchText
, strlen( pchText )
);
『ってするとちょうどツールバーの高さの分だけ下に表示するわけね』
「あ、ちなみに、 MFC の場合にはまた違った状態だから。 Version 9.01
( No.162 ) で紹介したビューウィンドウって憶えてる?」
『うん、ウィンドウの真ん中の白い四角いウィンドウ……あ!』
「そういうこと。今は大元のウィンドウのクライアントエリアに描いてたか
らツールバーを避けなきゃいけなかったけど」
『そもそも、そのツールバーの中にウィンドウひとつ作って、そこに表示す
ればいいんだ!』
「それが MFC のビューウィンドウにあたるってことだね」
『ってことは、今はフレームウィンドウに直に描いてるようなもんなのね。
じゃあさ、 SDK でもビューウィンドウ……って作れないの?』
「もちろん作れるよ。 MFC だって SDK の上に成り立ってるものなんだか
ら。ただ……」
『ただ?』
「実際には管理とか難しいから。たとえば、今ツールバーの問題が出たけ
ど、同じようにツールバーやステータスバーの中に入るように」
『ウィンドウのサイズ決めて、表示しなきゃいけない……』
「しかも、フレームウィンドウのリサイズをしたら」
『げっ、それにもあわせなきゃいけない!!』
「そういうこと。 MFC はそこまでの枠組みがしっかりできてるからいいけ
ど」
『 SDK だけだと、そこも自分で作らなきゃいけないわけね……ふー』
「だから、今回はとりあえずフレームウィンドウだけで、ね。では、目的
だった、テキストエディタもどきを作ります。まず、さっきみたいにグロー
バル変数を OnCreate() を置きます」
// 入力文字列を取っておくための変数。
const int TEXT_MAX_LENGTH = 256;
char g_pchText[TEXT_MAX_LENGTH + 1];
『前にテキストエディタもどきを作ったときには、メンバ変数に入れていた
し、 String クラス使ってたよね』
「そう、その辺は MFC との違いだし、実はその辺は非常に大きな意味を
持ってるんだけど」
『それはまた先の話?』
「そういうこと。で、この変数には入力した文字列を入れておきます。入れ
るのはもちろん、キー入力したときのハンドラ」
『 OnChar() ね』
「そういうこと」
// キー入力がありました。
LRESULT OnChar
( HWND p_hWnd
, WPARAM p_wParam
, LPARAM p_lParam
)
{
// 入力された文字を取り出して、文字列にします。
char ch[2];
ch[0] = (char)p_wParam;
ch[1] = '\0';
// それをくっつけます。
if( strlen( g_pchText ) < TEXT_MAX_LENGTH )
{
// 文字列サイズをオーバーしてないのでくっつけまず。
strcat( g_pchText, ch );
}
// そして再描画。
InvalidateRect( p_hWnd, NULL, TRUE );
return 0;
}
『 strcat() って?』
「第1引数の文字配列に、第2引数の文字列をくっつけるランタイム。一応
Version 5.07 ( No.072 ) でやったんだけどね」
『そんな昔のこと忘れたし……1回しか出てきてないし……』
「あとわかりにくいのはこれかな」
char ch[2];
ch[0] = (char)p_wParam;
ch[1] = '\0';
「まず、 WM_CHAR は、入力された文字を WPARAM に入れて渡してきます」
『それを char にキャストして受け取るわけよね。でも配列?』
「そう、 strcat() に渡すためには文字列じゃないといけないから」
『その辺、ちょっとわかんないかも』
「ま、それは少ししたらみっちり教えるから大丈夫」
『少ししたら?』
「うん、結構すぐ。 InvalidateRect() はいいよね」
『再描画する API だね。だから、これを呼ぶと再描画されるから……どう
なるんだっけ』
「再描画するメッセージは?」
『 WM_PAINT だから、 OnPaint() が呼ばれる!』
「そういうこと」
// 再描画します。
LRESULT OnPaint
( HWND p_hWnd
, WPARAM p_wParam
, LPARAM p_lParam
)
{
PAINTSTRUCT stPaintStruct;
HDC hDC
= ::BeginPaint
( p_hWnd
, &stPaintStruct
);
// この行は削除。
TextOut
( hDC
, 0
, g_iToolBarHeight
, g_pchText // ここと、
, strlen( g_pchText ) // ここを修正。
);
::EndPaint
( p_hWnd
, &stPaintStruct
);
return 0;
}
『表示する文字をさっきのに変えたのね』
「こうすれば」
『おおっ、またもやテキストエディタもどきに!!』
「ここまでは、はっきり言ってこれまでの復習だから、よく読み返して、ど
こがどう継ながってるのか理解してね」
『はーい』
/*
Preview Next Story!
*/
「 SDK 編は来週で終わりです」
『そっか、 MFC でやったのはもうだいたいやったんだね。次は?』
「みっちり基礎を勉強してもらいます」
『げげ!』
「でも実用度はかなり高いと思うよ」
『ほんとかなー』
「本当……だけど、つまらないと思う」
『げげげ!』
「というわけで次回」
< Version 10.22 SDK のまとめ、そして文字列へ >
『につづく!』
「でも絶対役に立つから!!」
『ほんとかなー』