Version 10.17
ステータスバーをクリック!
「今回は、ステータスバーをクリックしたときのメッセージを受け取ってみ
ます」
『……それって意味ある?』
「あんまりないかも。どちらかというと、前に使った【通知メッセージ】の
復習の方が大きいかも」
『通知メッセージって、 Version 5.29 ( No.094 ) とか
Version 8.10 ( No.152 ) とかに出てきたのだね』
「そう、コントロールがなにか操作された時に送られてくるメッセージ。ス
テータスバーはコントロールのひとつだから」
『同じように通知メッセージが送られてくるってことね』
「そういうこと。じゃあ、まずは試してみましょう。この前のステータス
バーを作った部分を次のように修正してください」
HWND g_hStetusBarWnd;
const int ID_STATUS_BAR = 5001; // まずここを追加。
// ウィンドウが作られます。
LRESULT OnCreate
( HWND p_hWnd
, WPARAM p_wParam
, LPARAM p_lParam
)
{
// ステータスバーを作ります。
g_hStetusBarWnd = CreateStatusWindow
( WS_CHILD | WS_VISIBLE
, "テスト"
, p_hWnd
, ID_STATUS_BAR // ここを修正。
);
if( g_hStetusBarWnd == NULL )
{
// ステータスバーが作られませんでした。
return -1;
}
// 分割するコードはあってもなくてもいいです。
return 0;
}
『ほとんど変わんないね』
「 CreateStatusWindow() の第4引数に渡す ID を別にしただけだからね。
さっきも言ったように、ステータスバーはコントロールのひとつ。さて問
題。コントロールにはどんなのがある?」
『どんなのって、いっぱいあるよね。ボタンとかエディットボックスとか』
「そうそう。そういうのに ID ってあったでしょ」
『あ! この ID_STATUS_BAR は、ステータスバーっていうコントロールの
ID ってことなんだ』
「そういうこと。だから、この ID_STATUS_BAR の値は他のコントロールと
重ならないようにね」
『それってどう調べるの?』
「メニューの【表示】−【シンボルブラウザ】のダイアログで確認できる
から。ちなみに、ここで値をセットすることもできるよ」
『どういうこと?』
「右側の【新規作成】ボタンを押して、 ID を ID_STATUS_BAR に、値を
5001 にして登録すれば」
const int ID_STATUS_BAR = 5001; // まずここを追加。
「の行は削除できるから」
『……つまり?』
「つまり、ボタンとかに使う ID を、別に何にも使わずに ID だけ登録でき
るってこと」
『あ、そっか、それをそのままステータスバーに使えるわけね』
「このシンボルブラウザなら割り当てられてる ID を確認してから登録でき
るから、他と間違えて同じ値をつけることがなくて安心かも」
『同じ値を付けることってできるの?』
「うん、シンボルブラウザでも普通にできるから。それをすると、最悪、ス
テータスバーを押すのと〈終了〉コマンドが一緒になっちゃって」
『アプリが閉じちゃう』
「ってこともあり得るから。さて、今度はステータスバーをクリックしたと
きのメッセージを受け取るように、ウィンドウプロシージャを修正します」
// ウィンドウプロシージャ。
LRESULT CALLBACK WndProc
( HWND p_hWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
if( p_uiMessage == WM_CREATE )
{
return OnCreate( p_hWnd, p_wParam, p_lParam );
}
else if( p_uiMessage == WM_DESTROY )
{
return OnDestroy();
}
else if( p_uiMessage == WM_RBUTTONUP )
{
return OnRButtonUp( p_hWnd, p_wParam, p_lParam );
}
else if( p_uiMessage == WM_COMMAND )
{
if( LOWORD( p_wParam ) == ID_MENU_TEST )
{
return OnMenuTest( p_hWnd, p_wParam, p_lParam );
}
}
else if( p_uiMessage == WM_NOTIFY ) // ここから下を追加。
{
if( p_wParam == ID_STATUS_BAR )
{
NMHDR *pNmhdr = (NMHDR*)p_lParam;
if( pNmhdr->code == NM_CLICK )
{
// クリックされました。
OutputDebugString( "クリックされました。\n" );
return 0;
}
}
}
// 標準的な処理をします。
return DefWindowProc( p_hWnd, p_uiMessage, p_wParam, p_lParam );
}
『あ、 WM_NOTIFY って前に出てきたね』
「そう、これが通知メッセージ。 Version 8.18 ( No.160 ) では、ダイ
アログプロシージャで通知メッセージを受け取ってます」
else if( p_uiMessage == WM_NOTIFY )
{
if( p_wParam == IDC_TREE_MAIN )
{
NM_TREEVIEW* pstNmTreeView = (NM_TREEVIEW*)p_lParam;
if( pstNmTreeView->hdr.code == TVN_SELCHANGED )
{
return OnSelchangedTreeMain( pstNmTreeView );
}
}
}
『形式はかなり似てるね』
「通知メッセージそのものを比較するところくらいかな、違いは。一応、ひ
とつひとつ見ておこうか。まず、通知メッセージを受け取ったら、どの ID
のコントロールからのメッセージか調べます」
if( p_wParam == ID_STATUS_BAR )
『ここでさっきの、ステータスバーのコントロールが出てくるのね』
「そういうこと。ボタンとかならボタンの ID 。ステータスバーならス
テータスバーの ID ってこと」
『それで……ここは違うんだね』
NMHDR *pNmhdr = (NMHDR*)p_lParam;
「ツリービューの時は LPARAM には NM_TREEVIEW 構造体のポインタが入っ
てたんだけど、 NM_CLICK の時は NMHDR 構造体のポインタが入ってるか
ら」
『 NM_CLICK が送られてきてるから NMHDR にキャストして……って、そ
れって変じゃん!! だって、 NM_CLICK が送られてきたって分かるの、
キャストしたあとじゃない』
「そう、よく分かったね。これはあとでちゃんと説明するけど、構造体って
こういうことができるようになってるんです。 NM_TREEVIEW の中身は」
[ NMHDR ][ UINT ][ TVITEM ][ TVITEM ][ POINT ]
「って感じに入ってるんです。この最初の所に NMHDR があるでしょ」
『これがあるとどうなの?』
「もしツリーバーの通知メッセージで LPARAM に NM_TREEVIEW へのポイ
ンタが入っていたとしても、それを NMHDR のポインタに変えても問題な
いってこと」
『???』
「……これは来週、ちゃんとやった方がいいかも」
『げ』
「げってことはないでしょ」
『うー』
「話を戻して、キャストをしたら、どんな通知メッセージが送られてきたの
か調べます」
if( pNmhdr->code == NM_CLICK )
『 NM_CLICK はクリックされたときの?』
「そう。正確には右クリックされた時に送られてくる通知メッセージ。これ
はステータスバーに限らずにいろんなコントロールから送られてくるから」
『それこそ、ちゃんと ID を調べないとまずいわけね』
「そういうこと。で、クリックされてたら」
// クリックされました。
OutputDebugString( "クリックされました。\n" );
「の所に入ります」
『これはテスト用で、何かするんだったらちゃんと関数作った方がいいんだ
よね』
「もちろん。その場合の引数はどうするか微妙だけど」
『そっか、 WPARAM と LPARAM にするか、 NMHDR のポインタにするか、
ってことね』
「その辺は好みによるかも。あ、あとひとつ補足。今回、ステータスバーを
作ったときに、前回のいくつかにわけるって部分は省きました」
『そういえばそうだね』
「で、どうも〈分けた中のどれをクリックしたか〉は取得できないみたいで
す」
『げ、そうなんだ』
「マウスの位置を取得して、それでどれがクリックされたか調べるしかない
かもね」
『そんなことできんの?』
「カーソル位置を取得する API は?」
『 GetCursorPos() !』
「分割するときには左側からのサイズを渡すんだから」
『あ、あの配列の数字ねー。あ、できちゃいそう』
「そういうこと」
/*
Preview Next Story!
*/
『やっぱり API って便利じゃないね』
「この辺はノウハウの方が重要かもね」
『つまりカーソル位置を知るための API は、みたいな?』
「そういうこと」
『でもそこまでまだ気が回らないなー』
「そのためには基礎をもっと勉強しないと」
『基礎ねー』
「というわけで次回」
< Version 10.18 構造体の構造 >
『につづく!』
「というわけで基礎を学びましょう!」
『う”、そういうの苦手なんだけど……』