Version 8.08
ダイアログプロシージャ
「まずは前回のおさらいから」
#include <Windows.h>
#include <stdio.h>
// リソースをインクルードします。
#include "resource.h"
// ダイアログプロシージャ。
BOOL CALLBACK DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
return FALSE;
}
// WinMain() 。
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
int iRet
= DialogBox
( p_hInstance
, MAKEINTRESOURCE( IDD_MAIN )
, NULL
, DialogProc
);
return 0;
}
『ダイアログをこれで作っちゃうんだよね』
「 DialogBox() でね。で、まず確認して欲しいんだけど、 WinMain() の
return 0; にブレークポイントを置いて」
『ほい。んで実行』
「ブレークポイントには止まってないよね」
『あ、ホントだ。ってことは DialogBox() から帰ってきてないんだね』
「そう、ダイアログが閉じるまで DialogBox() は返ってこないんです」
『ってゆーか、まずはダイアログを閉じられるようにならないとね』
「そうだね。で、ここで出てくるのは【メッセージ】ってもの」
『ん? どっかで聞いたような』
「 Version 5.28 ( No.093 ) と Version 5.29 ( No.094 ) を読み返してみ
るといいかも」
『そうそう! Spy++ でメッセージって見てみたんだよねー』
「このメッセージを直接受け取るのが、ウィンドウプロシージャなんです」
『ってことは、あのときの WM_MOUSEMOVE とかが送られてくる?』
「そう。実際に受け取ってみましょう。ダイアログプロシージャをこう書き
換えて」
// ダイアログプロシージャ。
BOOL CALLBACK DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
if( p_uiMessage == WM_MOUSEMOVE )
{
// マウスの位置を取り出します。
char pchPosition[1024];
sprintf
( pchPosition
, "%d, %d\n"
, LOWORD( p_lParam )
, HIWORD( p_lParam )
);
OutputDebugString( pchPosition );
return TRUE;
}
return FALSE;
}
『 if ひとつって感じ。実行、お、ダイアログの上でマウス動かすとちゃん
と位置が出る!』
「今回の例は DialogProc() で全部やってるけど、これを外に関数を作って
呼び出すようにすれば」
『 OnMouseMove() と同じになる!』
「そゆこと。とりあえずひとつずつ見ていこうか。まず引数」
『第1引数はウィンドウハンドルだね』
「これはそのまんま、ダイアログのウィンドウハンドル」
『まんまね』
「ただ……たとえばフォルダのウィンドウとかっていっぱい作れるよね」
『うん』
「このプログラムでそういうふうにいっぱいダイアログを作るとしても、そ
の数の分だけダイアログプロシージャを作れるわけじゃないよね」
『そりゃそーよ、いくつ作るか分かんないのに、関数をその数作るなんてで
きるわけ……げ! ってことはいろんなダイアログで使い回すの!?』
「そう、同じダイアログプロシージャを使っていっぱいダイアログを表示し
たら、それぞれのダイアログのイベントで呼ばれて」
『ってことはウィンドウハンドルもそのダイアログの数だけ……あう〜』
「 MFC の場合はその辺を管理をちゃんとしてくれるから、たとえば
CTestDlg の変数を3つ作ってダイアログを3つ作ったら」
『それぞれ別のが呼ばれる?』
「そのへんは MFC の便利なとこかな」
『ってゆーかかなり便利かも……』
「ま、当分はいっぱいウィンドウを作らないってことになるかな」
『そうなりそうね……次は第2引数、これがメッセージ?』
「そう、メッセージは符号なしの整数値で、これを調べれば大丈夫」
『残りの WPARAM と LPARAM もそうだけど、さっきの2回のとこでやってる
ね』
「あのときは送る側で、今回は受け取る側、でもどっちも同じってこと」
『ってことは、このダイアログプロシージャで、自分のダイアログに
SendMessage() したりってできるの?』
「できるよ。今度やってみようか」
『へー、なんか不思議……』
「今はまず WM_MOUSEMOVE 」
『そうそう。 WPARAM はほっといて、 LPARAM に LOWORD ってのと HIWORD
ってのやってるね』
「 WM_MOUSEMOVE のリファレンス見れば分かるけど、 WPARAM はどのキーを
押しているかっていうのが入ってます」
『コントロールキーとかわかるのねー』
「で、 LPARAM の方に、マウスの位置が入ってます。んーと、ちょっとこう
書き換えてみて」
sprintf
( pchPosition
, "%X, %X\n"
, LOWORD( 0x12345678 )
, HIWORD( 0x12345678 )
);
『ほい実行。お』
5678, 1234
『って出た』
「これで見ると分かるとおり、 LOWORD は32ビット整数値の下位2バイト
だけ抜き取るマクロ」
『 HIWORD は上位2バイトだけ抜き取るマクロってわけね。ってことは』
「そう、マウスの X 方向の位置は LPARAM の下位2バイトに、 Y 方向の位
置は上位2バイトに入ってるんです」
『せっこーい! ひとつの変数にふたつも入れてるなんて!』
「この辺はしょうがないところもあるかな。ウィンドウプロシージャで渡せ
るパラメーターは WPARAM と LPARAM だけだから」
『なんとかその中でやりとりしなきゃいけないってわけね……』
「こういうプログラムはあまり勧められないけど、ウィンドウプロシージャ
を直接扱う上では必要なことなんだよね」
『勧められないって?』
「場合場合で WPARAM の中にどういうデータが入ってるかって知ってないと
いけないからね。そういうのは勘違いひとつで」
『バグ作っちゃうわけねー』
「この辺も MFC のメリットかな。と、話を戻してと」
『 OutputDebugString() は Version 6.18 ( No.118 ) でやったね。
TRACE と同じの』
「そうそう。 Version 8 になってから TRACE 使ってないの気付いた?」
『あ、そういえば』
「 TRACE は MFC のだから」
『げ、使えないんだ。だから sprintf() 使ってたのね……』
「でも sprintf() と OutputDebugString() があれば同じことができるから
大丈夫」
『それをしてるってわけね』
「で、最後に return TRUE; 」
『ん? 重要なの?』
「重要と言えば重要。メッセージをダイアログプロシージャで処理した場合
には TRUE を、処理しなかった場合には FALSE を返す決まりになってます」
『 DialogProc() の戻り値ってことだよね』
「そうそう。処理しなかったってことで FALSE を返すと、ウィンドウズが
諸々の処理を代わりにしてくれます」
『へー、便利』
「実際に……」
// ダイアログプロシージャ。
BOOL CALLBACK DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
return TRUE;
}
『げ! ダイアログがちゃんと表示されない!』
「これは TRUE を返しちゃってるから、ウィンドウズが〈じゃあ表示も代わ
りにしなくていいんだ〉って判断しちゃってるから」
『たったこれだけでこんな違うのねー』
「一応 DialogProc() のリファレンスってあるんだけど、この辺までは細か
く書いてないかな。こういうのでずーっと迷ったりすると面倒だから、この
辺は憶えておいた方がいいかも」
『ずーっと迷ったりしたことあるの?』
「何度かね……」
/*
Preview Next Story!
*/
『この辺って、知ってないとできないことって多いよね』
「自動でって少ないからね。ダイアログ閉じるのもそうだし」
『そうよそうよ、閉じるのひとつ手動だなんて!』
「でも手動で閉じられると便利なこともあるんだよね」
『便利なこと?』
「というわけで次回」
< Version 8.09 ダイアログを閉じてみる >
『につづく!』
「自動が必ずしも便利じゃない!」
『……水希ちゃんが自動で書いてくれれば……』
「それを火美ちゃんに期待してるんだけど……」
『げ! 差別よ差別!』