Version 10.14
MFC との違い・ポップアップメニュー編
「前回は、ポップアップメニューを表示するために次のように右クリック時
の関数を修正しました」
// 右クリックされました。
LRESULT OnRButtonUp
( HWND p_hWnd
, WPARAM p_wParam
, LPARAM p_lParam
)
{
// 画面上のマウスカーソルの位置を取得します。
POINT stPoint;
GetCursorPos( &stPoint );
// メニューバーを読み込みます。
HMENU hMenuBar
= LoadMenu
( GetModuleHandle( NULL )
, MAKEINTRESOURCE( IDM_MAIN )
);
// サブメニューを取得します。
HMENU hSubMenu
= GetSubMenu( hMenuBar, 0 );
// ポップアップメニューを表示します。
TrackPopupMenu
( hSubMenu
, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON
, stPoint.x
, stPoint.y
, 0
, p_hWnd
, NULL
);
return 0;
}
『長い……けど、ひとつの関数を何行も書いてるからそう見えるだけかな』
「それだけ引数が多いってことだから複雑なのにはかわりないけどね」
『げ、そういえば……』
「さて、これをひとつひとつ解説していきます。と、これの元になった
Version 9.05 ( No.166 ) の方も見ておいてください」
『つまり、あっちは CMenu を使ってて、こっちは HMENU を使ってるわけよ
ね』
「そう、 CMenu は MFC のクラス。でも今は SDK だけで作っているから
MFC は使えない、というわけで CMenu の代わりに HMENU を使います」
『質問! MFC の CMenu だけ使うってことはできないの?』
「できなくはないけど、かなり面倒だし難しいからやめておいた方がいい
よ」
『そういうもんなんだ』
「実際、 CMenu はそれほど便利じゃないからいいんだけど、 CString とか
便利なものは SDK だけの時も使いたかったりするんだよね……」
『 CString って文字列入れるクラスだよね』
「そう。これがあるのとないのとでは結構な差が……と、その辺は次の章ま
で取っておくとして。ではさっそくひとつひとつ見ていきます」
// 画面上のマウスカーソルの位置を取得します。
POINT stPoint;
GetCursorPos( &stPoint );
「これは今あるカーソルの位置を取得してます。 POINT は〈点〉を入れる
ための構造体」
『 POINT って CPoint とどう違うの?』
「 RECT と CRect の関係と同じ」
『あー、 Version 7.07 ( No.127 ) で言ってたのだね。ってことは同じも
のって考えちゃっていいんだ』
「うん、だから同じように GetCursorPos() に渡してるしね。では次」
// メニューバーを読み込みます。
HMENU hMenuBar
= LoadMenu
( GetModuleHandle( NULL )
, MAKEINTRESOURCE( IDM_MAIN )
);
『これって CMenu 使ってた時のとまったく違うよね』
「あの時は、ウィンドウのメニューバーを取得してたけど、今回はリソース
から直接読み込んでるから。ちなみに LoadMenu() に関しては
Version 10.09 ( No.187 ) を参照」
『あ、そっか、今のメニューバーをセットするときにもこれ使ってたんだ
ね。……あれ?? GetModuleHandle() って?』
「これはインスタンスハンドルを取得するための API 。これに NULL を渡
すと自分のインスタンスハンドル、つまり WinMain() の第1引数のが得ら
れるから。これは便利だから憶えておいて」
『……質問質問質問!! じゃあ Version 10.10 ( No.188 ) で
MessageLoop() にわざわざインスタンスハンドル渡してたのはなんで??』
「いや、別にどっちでもいいんだけどね。その他にも、グローバル変数に入
れておいてそれを使うって方法もあるし」
『……結局どれが一番いいの?』
「一番確実でどこからでも取れる GetModuleHandle() がいいと思うよ」
『じゃあやっぱり MessageLoop() の引数で渡すことなかったじゃん』
「まぁ、そうかも……さて次」
『あ』
// サブメニューを取得します。
HMENU hSubMenu
= GetSubMenu( hMenuBar, 0 );
「これはそのまま API に置き換えただけ」
『んーと、受け取るのを CMenu のポインタから HMENU に変えて、あとメ
ニューのハンドルを第1引数に渡してるんだね』
「これは前のと比べてみようか」
// 「ファイル」サブメニューを取得します。
CMenu *pcFileMenu
= pcMenuBar->GetSubMenu( 0 );
「 CMenu::GetSubMenu() ってメンバ関数を呼んでたのを GetSubMenu() っ
て API を呼ぶように変えたんだけど」
『どうやって変えるのかっていうのはなんとなくわかるんだけど、でも、自
分で変えようとしたらちょっと難しいかも』
「だったら、実際に CMenu::GetSubMenu() のソースを見るって手もあるか
も」
『あ、 MFC って全部ソースがあるんだもんね』
「しかも MFC のほとんどは API をそのまま呼んでるだけだから。このメン
バ関数なら AfxWin1.inl ってファイルにあるから」
『えーっと……む、ちょっと難しいかも』
「まぁ呼び出してる部分だけ抜き出すと」
::GetSubMenu(m_hMenu, nPos)
「って感じ。 m_hMenu は CMenu が中に持ってるメニューハンドル」
『つまりこのメニューハンドルを直に HMENU って感じに渡せばいいってこ
と……でいいんだよね』
「うん、そうなるかな。この辺は色々やって慣れるのもいいかも。ちゃんと
教えられるのはもう少し先になっちゃうし」
『げ、そうなの?』
「他に教えることが結構あるから……。さて、最後」
// ポップアップメニューを表示します。
TrackPopupMenu
( hSubMenu
, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON
, stPoint.x
, stPoint.y
, 0
, p_hWnd
, NULL
);
『これもメニューハンドルを直接渡してるわけね』
「これも前のと比べると」
// ポップアップメニューを表示します。
pcFileMenu->TrackPopupMenu
( TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON
, cPoint.x
, cPoint.y
, pcMainFrameWnd
);
『あれ? かなり短いね』
「いくつか省略されてるからね。えっと、まず API の方の5番目の引数」
『 0 渡してるね』
「これは今は使われてなくて、将来は使うかもしれない引数」
『へー、そんなのあるんだ』
「って言っても、まず使われないだろうけど」
『なんだー』
「 API にはそういうの結構あるから。リファレンスには 0 を渡してくださ
いって書いてあるからそのまま 0 を渡します」
『6番目の引数は、 API のはウィンドウプロシージャが受け取ったウィン
ドウハンドルだね。そういえば、前の例の方は、なんか面倒なことしてたよ
うな……』
「フレームウィンドウのポインタを渡していたからね。というより」
『というより?』
「 SDK だけのって、ビューウィンドウは作ってないでしょ」
『あ! そういえば。それってなんで?』
「面倒だから」
『……それだけ?』
「今のところはね。ちゃんとしたアプリを作ろうってことになったら必要だ
から。今のままだとグレーのままだしね」
『でも、ウィンドウが増えたらウィンドウプロシージャも増えるわけで……
結構混乱するねー』
「って言っても、 MFC が肩代わりしてただけだけどね」
『そうだけどー』
「と、話を戻して」
『7番目の引数は…… NULL 渡してるね』
「これは、メニューの外をクリックしてもメニューが消えないようにするた
めの引数」
『……それってなんの意味があるの?』
「さぁ……それに試してもうまく機能しないし……で、そういう機能が必要
ないときは NULL を渡します」
『で、なんで CMenu の方は渡してないの?』
「引数としてはちゃんとあるんだけど、省略してるから。リファレンスには
こう書かれてるでしょ」
BOOL TrackPopupMenu
( UINT nFlags, int x, int y, CWnd* pWnd
, LPCRECT lpRect = NULL
);
「この = NULL っていうのは、その引数を省略すると NULL が渡されるって
こと。 Version 8.11 ( No.153 ) とかでやったでしょ」
『あー、あれと同じなんだ』
「で、 Version 5.11 ( No.076 ) でも触れたけど、この省略機能は C++ の
もの。 API は C 言語時代のものだから」
『省略機能はないわけね。面倒〜』
「実際、 MFC の便利な部分の多くは省略機能かも」
『なんだかんだ言って、やっぱ MFC の方が便利だよね』
「それはそうだね……」
/*
Preview Next Story!
*/
『って、認めちゃっていいの?』
「便利なのは便利だし。次回のステータスバーも」
『そういえばステータスバーって最初っからあるもんね』
「そういうのも自分でしなきゃいけないのは大変かな」
『大変なのはヤダなー』
「でも仕組みを知るためにも、一から作るのは重要だよ?」
『重要って言われても〜』
「というわけで次回」
< Version 10.15 ステータスバーを作ってみよう! >
『につづく!』
「作るのは結構面白いよ?」
『面白いって言われても〜』