在MFC中的app類的InitInstance函數中,我們會看到這樣一個函數,InitContextMenuManager,從它的字面意義可以看出是“初始化上下文菜單管理器”。像這樣,在初始化函數中調用了這個函數,那麼MFC架構就會為你建立一個類型為CContextMenuManager的對象,另外我們也可以手動建立這個對象,但是如果手動建立,那麼就不要在使用這個函數了,否則會出錯,MFC中由這個對象來管理程式中的快捷菜單,當然,我們也可以使用win32的那種方法來實作快捷菜單的功能。那麼MFC的一個優勢就是使用面向對象的方法來管理程式中的各個對象,對于菜單,MFC也提供了一個對象來專門管理快捷菜單,首先來看看在由MFC向導生成的單文檔程式中,對菜單管理器的使用。
當我們使用MFC向導生成一個單文檔程式之後,我們在客戶區點選右鍵,就有一個快捷菜單,如下:

由于我們沒有添加指令響應,是以菜單上面的項目都是灰色的。現在來看看它是如何做到的,首先在app類的PreLoadState函數中有如下語句:
void CcontextmenuApp::PreLoadState()
{
BOOL bNameValid;
CString strName;
bNameValid = strName.LoadString(IDS_EDIT_MENU);
ASSERT(bNameValid);
GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EDIT);
}
在這裡GetContextMenuManager是app類的一個方法,但是這裡要注意的是這個函數是CWinAppEx函數,在CWinApp類中沒有,這個我們可以修改我們自己的app類的基類就可以了,但是使用VS2010這不是什麼問題。GetContextMenuManager函數會傳回CContextMenuManager類型的對象指針,然後調用AddMenu方法,就将一個菜單資源添加到了這個對象當中,那麼這個對象指針由架構儲存,為了我們友善使用,我們可以在我們的類中聲明一個CContextMenuManager類型的對象指針,來儲存對象的位址,這樣我們在使用的時候比較友善。
在這裡已經将菜單資源添加到了快捷菜單管理器中,現在我們就可以使用了,那麼在什麼時候應該彈出快捷菜單呢,有的人使用的滑鼠右鍵按下或是右鍵彈起的時候,進行彈出響應。這樣做也是可以達到效果的,但是在windows中,有一個消息,是專門用來處理快捷菜單的,那就是WM_CONTEXTMENU,那麼這個消息也是在當 WM_RBUTTONUP 或是WM_NCRBUTTONUP(非客戶區滑鼠右鍵彈起)傳遞給預設視窗過程函數DefWindowProc時由預設視窗過程處理生成的。是以,這裡我們就要注意,當我們自己處理了WM_RBUTTONUP之後,應該繼續調用基類處理。否則,不會有WM_CONTEXTMENU消息生成,另外,還需要注意的一個是WM_RBUTTONUP的消息參數中傳遞的坐标是客戶區坐标,而我們要使用的,應該是螢幕坐标,是以,需要做一個轉換或是使用GetCursorPos來擷取光标的位置。現在看由MFC架構生成的對快捷菜單的調用,它是在View類中處理的WM_CONTEXTMENU消息中處理的,如下:
oid CcontextmenuView::OnContextMenu(CWnd* , CPoint point)
{
#ifndef SHARED_HANDLERS
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}
這樣,當我們點選滑鼠右鍵的時候,就會生成一個WM_CONTEXTMENU消息,這時候,我們響應快捷菜單彈出的消息,這裡它就是是用快捷菜單管理器來彈出的快捷菜單,ShowPopuMenu就是CContextMenuManager類的成員函數。如果我們是使用win32的方法來實作快捷菜單,也可以在這裡做出相應的處理,而不使用MFC提供的快捷菜單管理器。下面我們做一個自己的快捷菜單,來看看快捷菜單管理器的使用。
首先我們在資源編輯器中,插入自定義的菜單,如下:
現在回到App類的PreLoadState函數做,做出修改,加載我們自己定義的菜單,修改後如下:
void CcontextmenuApp::PreLoadState()
{
GetContextMenuManager()->AddMenu(L"MYMENU", IDR_MYMENU);
}
接着,我在View類的WM_CONTEXTMENU消息響應函數下,也做出修改,修改後如下:
void CcontextmenuView::OnContextMenu(CWnd* , CPoint point)
{
#ifndef SHARED_HANDLERS
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_MYMENU, point.x, point.y, this, TRUE);
#endif
}
現在可以運作一下,看看效果:
這樣就實作了我們功能,我們看見菜單項目仍然是灰色,當我們為它們添加指令響應之後,那麼就不會是灰色狀态,以第一個菜單項目為例:
我在View類中做響應,如下:
void CcontextmenuView::OnMymenu32771()
{
// TODO: 在此添加指令處理程式代碼
this->MessageBox(L"菜單項目一");
}
下面再次運作:
現在我們看見“菜單項目一”,由于添加了指令響應,現在已經不再是灰色了,我們點選響應一次:
在快捷菜單管理器其中,我們可以使用AddMenu添加多個菜單,但是同一個菜單不應多次添加。另外,如果是自己手動建立的快捷菜單管理器對象,那麼在使用的時候,需要多點注意事項,例如,新菜單彈出來之後,是否應該自動關閉原來的那個快捷菜單,如果遇到問題,可以查閱msdn,獲得解決方法。推薦使用由MFC的這個快捷菜單管理器來管理我們的快捷菜單,省去了使用win32彈出快捷菜單的很多步驟和資源回收的工作。更加安全可靠。
更多資訊,參考MSDN,推薦大家用好MSDN,是我不懈的努力!^_^
推薦程式設計者通路網站:http://www.panshy.com 擷取更多知識。
本文代碼:http://download.csdn.net/detail/xinzhiyounizhiyouni/6793861