よくウィンドウの中で右クリックをすると、ポップアップメニューが出ますね。 これを実現する方法は簡単です。
ポップアップメニューを右クリックで出したいので、
まずCViewの派生クラス(ここではCTestViewとします)の
WM_RBUTTONDOWNのハンドラのOnRButtonDownを用意します。
そして、CMenuのCreatePopupMenuでメニューを初期化し、
AppendMenu等でメニューを準備して
TrackPopupMenuで表示し、最後にDesytroyMenuを呼び出して終了です。
class CTestView : public CView { 〜 // 生成されたメッセージ マップ関数 protected: //{{AFX_MSG(CTestView) afx_msg void OnRButtonDown(UINT nFlags, CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP() };TestView.cpp:
〜 BEGIN_MESSAGE_MAP(CTestView, CView) //{{AFX_MSG_MAP(CTestView) ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP 〜 END_MESSAGE_MAP() 〜 void CTestView::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください CMenu menu; menu.CreatePopupMenu(); menu.AppendMenu(MF_STRING|MF_ENABLED,ID_EDIT_UNDO ,"元に戻す(&U)"); menu.AppendMenu(MF_SEPARATOR); menu.AppendMenu(MF_STRING|MF_ENABLED,ID_EDIT_CUT ,"切り取り(&T)"); menu.AppendMenu(MF_STRING|MF_ENABLED,ID_EDIT_COPY ,"コピー(&C)"); menu.AppendMenu(MF_STRING|MF_ENABLED,ID_EDIT_PASTE,"貼り付け(&P)"); ClientToScreen(&point); menu.TrackPopupMenu( TPM_LEFTALIGN | //クリック時のX座標をメニューの左辺にする TPM_RIGHTBUTTON, //右クリックでメニュー選択可能とする point.x,point.y, //メニューの表示位置 this //このメニューを所有するウィンドウ ); menu.DestroyMenu(); // CView::OnRButtonDown(nFlags, point); }
通常のメニューバーのメニューだと、メニュー描画時に
メニューID毎に作られた「OnUpdateほにゃらら」関数が呼び出されて
選択不可になったりチェックが付いたりするのですが、
AppendMenuの時はそれは行われません。
したがって、自分で選択可能(MF_ENABLED)・選択不可(MF_GRAYED)・
チェック(MF_CHECKED/MF_UNCHECKED)を指定してやらないといけません。
メニューIDに対してハンドラを作ってやらないと 実際に メニューをクリックした時に何も動作しません。 が、メニューIDがメニューリソースに入っていないIDだった場合、 ClassWizardの「オブジェクトID」リストにメニューIDが表示されません。 この場合は、自分でハンドラをコーディングするか、もしくは 他のどこにも使わないメニューリソースを作って そこに メニューIDを加えてClassWizardを使ってください。
上記の例だと、実はメニューバーのデフォルトの「編集」メニューのサブメニューと同じ内容ですね。 これを一々コーディングせずに、メニューバーから持ってくることが出来ます。
TestView.cpp:void CTestView::OnRButtonDown(UINT nFlags, CPoint point) { CWnd *pFrm =GetParentFrame(); //メインフレーム取得 CMenu *pMain=pFrm ->GetMenu(); //メニュー取得 CMenu *pMenu=pMain->GetSubMenu(1); //「編集」メニュー取得 ClientToScreen(&point); pMenu->TrackPopupMenu( TPM_LEFTALIGN | //クリック時のx座標をメニューの左辺にする TPM_RIGHTBUTTON, //右クリックでメニュー選択可能とする point.x,point.y, //メニューの表示位置 this //このメニューを所有するウィンドウ ); }
この場合は、DestroyMenuは不要です。というか、実行したら、 メニューバーのメニューを選択する時にハングアップする(爆)
これを応用して、メニューリソースを使って オリジナルのポップアップメニューを作ることが出来ます。
IDR_MENU_POPUPというメニューリソースを新規に作成し、 popup1配下のメニューを作りました。
TestView.cpp:void CTestView::OnRButtonDown(UINT nFlags, CPoint point) { CMenu menu; menu.LoadMenu(IDR_MENU_POPUP); CMenu *pMenu=menu.GetSubMenu(0); //「popup1」メニューを取得 ClientToScreen(&point); pMenu->TrackPopupMenu( TPM_LEFTALIGN | //クリック時のx座標をメニューの左辺にする TPM_RIGHTBUTTON, //右クリックでメニュー選択可能とする point.x,point.y, //メニューの表示位置 this //このメニューを所有するウィンドウ ); menu.DestroyMenu(); }
GetSubMenuの使い方に関して、「メニューリソースが変更された時に GetSubMenuの引数も コーディングし直さなちゃいけないじゃないか」という正常な感覚をお持ちの方は、 メニューバーの説明を参考にしてみて下さい。