Version 9.06
メニューアイテムのハンドラを作る!
「前回まででメニューの基本的な部分はほとんど教えました」
『ほとんど?』
「そう、まだ重要なのが残ってます。今までは【ファイルを開く】とかの最
初からあるアイテムしか使わなかったけど」
『あ! まだアイテム追加して……で、それでイベントハンドラ呼ばせたり
とかできるんたよね、そーゆーのまだだね』
「そうそう。今回はその辺を見ていきます。じゃ、まずは普通のメニューア
イテムを追加してみます」
『 Version 9.02 ( No.163 ) のだよね』
「あのときと同じようにすればいいから。えーっと、ファイルサブメニュー
でいいかな、その一番下に空欄があるから、そのプロパティを表示して」
『 ID とキャプションはっと。そういえば、これってダイアログのボタン
作ったりするのと同じでいーの?』
「うん、基本的な仕組みは同じだから」
『そーゆーもんなんだ。じゃあ ID は ID_MENU_TEST で、キャプションは
【テスト(&T)】、プロンプトは〈テストだよ〉っと』
「他のチェックボックスは全部オフでいいから。とりあえずそれでビルドし
てみて」
『ほい。うん、ビルドして実行してメニュー……にあることはあるんだけ
ど……淡色だ……』
「そうなんです。 MFC の仕組みとして、イベントハンドラのないメニュー
アイテムは自動的に淡色表示されることになってるんです」
『なんだかいい迷惑』
「まぁそれはたいがいの人が思ってるから我慢して。というわけでイベント
ハンドラを作ります。まず ClassWizard 出して」
『ほい』
「例によって【メッセージマップ】のページで、左下のオブジェクト ID の
中に」
『 ID_MENU_TEST がある!』
「ところが!」
『な、なに?』
「右上の【クラス名】は何になってる?」
『 CMainFrame だよ』
「そこを CSdiTestView にして、同じようにオブジェクト ID を見てみる
と……」
『あれ??? こっちでも ID_MENU_TEST がある!』
「実は、メニューのイベントハンドラはフレームウィンドウでもビューウィ
ンドウでも受け取れるんです」
『うわ! 何それ、混乱する!』
「だからどっちにイベントハンドラを作らないといけないかってちゃんと考
えないとダメってこと」
『両方作ったら?』
「試してみたけどビューの方だけ呼ばれるみたいだね。だから両方作るって
いうのは意味ないかな」
『で……どっちに作ればいいのかな』
「この場合はたぶんフレームウィンドウの方。ただ」
『ただ?』
「こういう、どのクラスでどういう処理をするのかっていうのは
〈プログラムの設計〉っていう領域」
『プラグラムの設計?』
「一番悪い例は、あるメニューアイテムはフレームウィンドウで、他のメ
ニューアイテムはビューウィンドウで処理、っていうの」
『バラバラは良くないってことね』
「だから、たとえばフレームウィンドウにまとめることにしたとします」
『うん』
「でも、このプログラムをもう少し進めると、フレームウィンドウはウィン
ドウの処理をするのが仕事だから、実際の処理を入れるとごちゃっとするこ
とがあります」
『実際の処理?』
「複雑な計算をさせたりする場合とか」
『そういう計算式がフレームウィンドウに入ってると確かにぐちゃぐちゃし
そう』
「そうなると、そういう処理をするための専用のクラスを別に作るって話が
出てきます」
『別のクラスを作る!?』
「そういう風に、どの処理をどのクラスにまとめるか考える」
『それが〈プログラムを設計する〉ってことなんだ!』
「そういうこと。これはただのプログラムを組む技術とは違うものだし、身
に着けるのは結構大変」
『水希ちゃんも?』
「もちろん。今も勉強中。ま、プログラムを組むこと自体が大工さんの仕事
なら、設計は」
『建築デザイナーの仕事、そうそう両方できるもんじゃないね。って、そ
れって普通別の仕事なんじゃない?』
「う”。プログラミング業界ってのはそこまで人材資源に緩くないんだよ
ね……」
『ダメじゃん』
「う”。まぁそれは置いといて」
『きっと永遠に置いとかれるんだ……』
「この場合はフレームウィンドウにイベントハンドラを置いた方がいいか
な」
『前回も、ポップアップメニューのはフレームウィンドウに渡してたもん
ね』
「一応それを踏まえてね。というわけで、クラス名に CMainFrame を選択し
て、オブジェクト ID に ID_MENU_TEST を選んで」
『メッセージは? COMMAND と UPDATE_COMMAND_UI とがあるけど』
「 COMMAND の方を選んで」
『ほい、じゃあ COMMAND 選んで【関数の追加】っと。うん、フレームウィ
ンドウに追加されたよ』
void CMainFrame::OnMenuTest()
{
// TODO: この位置にコマンド ハンドラ用のコードを追加してください
}
『ブレークポイント置いてビルドして実行! メニューアイテム、淡色表示
されてない! んで選ぶと……ちゃんと引っかかった!』
「というわけでこれでメニューに対してのイベントハンドラが作れたことに
なります」
『おお。ってゆーか、ダイアログのボタンの時と変わんなくない?』
「だね。これは MFC のっていうよりも、ウィンドウズシステムとして、ボ
タンなんかとメニューなんかは共通のシステムってこと」
『あ、ってことはメニューアイテムも WM_COMMAND で送られてくるってこと
なんだ。だから COMMAND なのね』
「そゆこと。だから難しく考える必要はないかな」
『……で?』
「……別にイベントハンドラ作っても、今回は特にすることないんだよね」
『どっちかってゆーと、今回って手段が目的って感じ』
「まーメニュー使うこと自体は使えると思うよ。さて、後半はさっき使わな
かった UPDATE_COMMAND_UI について。これはメニューを淡色表示させる時
に使います」
『メニューを淡色表示?』
「ダイアログのボタンの時と違って、メニューアイテムって状況ごとに淡色
になったりならなかったりするでしょ」
『うん、できることとできないことが変わるもんね』
「それを管理するための MFC のシステムがこれ。とりあえず、さっきと同
じ手順で UPDATE_COMMAND_UI のイベントハンドラを作って」
『ほい。こういうのできたよ』
void CMainFrame::OnUpdateMenuTest(CCmdUI* pCmdUI)
{
// TODO: この位置に command update UI ハンドラ用のコードを(略)
}
「このメンバ関数は、メニューアイテムが表示される直前に呼ばれます」
『メニューアイテムが表示される直前?』
「試しに」
void CMainFrame::OnUpdateMenuTest(CCmdUI* pCmdUI)
{
TRACE0( "OnUpdateMenuTest()\n" );
}
「を試してみて」
『ほい。あー、【ファイル】サブメニューが表示される時に呼ばれるね』
「そうでしょ。そこで、この中でこういう処理を普通はします」
void CMainFrame::OnUpdateMenuTest(CCmdUI* pCmdUI)
{
// 許可/不許可を入れる変数を用意します。
bool bIsSetEnable;
// ここで、現在の状態を調べて TRUE か FALSE を入れます。
// ここではテストってことで FALSE を渡します。
bIsSetEnable = FALSE;
// 許可/不許可をセットします。
pCmdUI->Enable( bIsSetEnable );
}
『ん? なんかよくわかんないコメントが』
「このメンバ関数はメニューアイテムが表示される直前に〈このメニューア
イテムはどう表示するの?〉ってことを訊いてきてる、そう考えてくださ
い」
『そう考える』
「そこで、まずこのメンバ関数の中で、現在の状態を調べます。と言って
も、このアプリだとそういうのないからその部分は割愛」
『だからこういうコメントね』
「その現在の状態によって、引数として渡されてる CCmdUI の Enable()
ってメンバ関数に渡す値を、 TRUE にするか FALSE にするか変えます。
TRUE だとメニューアイテムは使えるし、 FALSE だと淡色表示になります」
『これだと FALSE しか渡してないから淡色表示になるのね』
「試してみて」
『ほい。お、淡色だ』
「このメンバ関数は、メニューアイテムを含むポップアップメニューが表示
される度に呼ばれるから、その都度現在の状態をチェックして」
『 TRUE か FALSE 渡せばいーわけね。……でもさ、これってつまり、全部
のメニューアイテムにしなきゃいけないってことだよね』
「そうだよ。ってゆーか、今の AppWizard が作ってくれたメニューは、全
部 MFC がカバーしてくれてるでしょ」
『ファイルを開くとか、自動的に最初からある、とか?』
「そうそう。だから今は気になってないけど、最終的には」
『げ! そうか、メニュー全部自分で作ったら、全部イベントハンドラ作ら
なきゃいけないんだ!』
「 COMMAND の方もね」
『そっちもあるんだ、ってゆーかそっちの方が大変ね……』
「今までずっとダイアログアプリしか作ってこなかったけど、それは SDI
が複雑で難しいから、ってところがあるんだよね」
『確かに、ただメニュー使うだけでもかなり複雑だもんね』
「それに、今の淡色表示の所、実際に〈今淡色表示すべきか〉を調べたり管
理するのってかなり難しいと思うよ」
『使えるはずなのに淡色表示にしちゃう、とかあり得そう……』
「ま、複雑化するのは避けようがないから、それをいかに解りやすく組んで
いくか……っていうのはもう少し先になってからの話かな」
『んー』
「あ!」
『な、なに?』
「さっきの CMainFrame::OnUpdateMenuTest() の中身、コメントアウトして
おいてね」
『あー、このままだとずっと淡色表示だもんね。でも削除しないの?』
「これは次回使うから」
/*
Preview Next Story!
*/
『でもなんに使うの?』
「ダイアログボックスのボタン代わり」
『そっか、メニューを選んで何かさせるわけね』
「で、させることはアクセラレーターの追加」
『アクセラレーター?』
「というわけで次回」
< Version 9.07 アクセラレーター >
『につづく!』
「アクセラレーターは面倒なんだ……」
『げ、面倒なの嫌い!』
「僕も嫌い……」