首先,在MFC中,具有PopUp屬性的菜單是不能用來做命令響應的。
在MFC中:
當點擊一個功能表項目的時候,最先接受到功能表項目訊息的是CMainFrame架構類,CMainFrame架構類將會把功能表項目訊息交給它的子視窗View類,由View類首先進行處理;如果View類檢測到沒對該功能表項目訊息做響應,則View類把功能表項目訊息交由文檔類Doc類進行處理;如果Doc類檢測到Doc類中也沒對該功能表項目訊息做響應,則Doc類又把該功能表項目訊息交還給View類,由View類再交還給CMainFrame類處理。如果CMainFrame類查看到CMainFrame類中也沒對該訊息做響應,則最終交給App類進行處理。
所以,其訊息行程順序為:View類--Doc類--CMainFrame類--App類。當然,菜單訊息一旦在其中一個類中響應則不再在其它類中尋找響應函數
windows訊息的分類
(1)標準訊息:除WM_COMMAND之外,所有以WM_開頭的訊息。從CWnd類派生的都可以接收到這些訊息。
(2)命令訊息:來自菜單、加速鍵或工具列按鈕的訊息。這類訊息都以WM_COMMAND呈現。在MFC中,通過功能表項目的標識(ID)來區分不同的命令訊息;在SDK中,通過訊息的wParam參數識別。
(3)通告訊息:由控制項產生的訊息,例如,按鈕的單擊,列表框的選擇等均產生此類訊息,為的是向其父視窗(通常是對話方塊)通知事件的發生。這類訊息也是以 WM_COMMAND形式呈現。——————從CCmdTarget派生的類,都可以接收到[命令訊息]和[通告訊息]。
在menu操作過程中,幾個函數需要瞭解:
1 CMenu* GetMenu( ) ;//CWnd::GetMenu得到視窗功能表列對象指標。
2 CMenu* GetSubMenu( ) ;//CMenu::GetSubMenu獲得指向快顯功能表對象指標
3 UINT CheckMenuItem( );//CMenu::CheckMenuItem添加(add)check marks(選擇標記)或者是刪除(remove)check marks,是針對功能表項目的作用
4 BOOL SetDefaultItem();//CMenu::SetDefaultItem
5 BOOL SetMenuItemBitmaps( );//CMenu::SetMenuItemBitmaps 設定位元影像標題菜單。
6 UINT EnableMenuItem();//CMenu::EnableMenuItem使功能表項目有效,無效,或變灰。
7 BOOL SetMenu( CMenu* pMenu );//CWnd::SetMenu在當前視窗上設定新菜單或移除菜單
8 HMENU Detach( );//CMenu::Detach Detaches a Windows menu from a CMenu object and returns the handle.
建立一個menu項的簡單過程:
1 CMenu menu;//定義為局部對象
2 menu.LoadMenu(IDR_MAINFRAME);
3 SetMenu(&menu);
4 menu.Detach();//因為局部對象
這裡menu對象作為一個局部對象。使用Detach()從menu對象中分離視窗菜單控制代碼,從而當menu對象析構的時候視窗菜單資源不隨之銷毀。
命令更新機制:
功能表項目狀態的維護是依賴於CN_UPDATE_COMMAND_UI訊息,誰捕獲CN_UPDATE_COMMAND_UI訊息,MFC就在其中建立一個CCmdUI對象。
在後台作業系統發出WM_INITMENUPOPUP訊息,然後由MFC的基類如CFrameWnd接管並建立一個CCmdUI對象和第一個功能表項目相關聯,調用對象成員函數DoUpdate()(註:這個函數在MSDN中沒有找到說明)發出CN_UPDATE_COMMAND_UI訊息,這條訊息帶有指向CCmdUI對象的指標。此後同一個CCmdUI對象又設定為與第二個功能表項目相關聯,這樣順序進行,直到完成所有功能表項目。
更新命令UI處理常式僅應用於彈出式功能表項目上的項目,不能應用於永久顯示的頂級功能表項目。
利用調用TrackPopupMenu函數,建立ContextMenu(右鍵菜單):
1 void CMenu2View::OnRButtonDown(UINT nFlags, CPoint point)
2 {
3 CMenu menu;
4 menu.LoadMenu(IDR_MENU1);
5 CMenu *pPopup = menu.GetSubMenu(0);
6 ClientToScreen(&point);//將一個座標點或一個矩形地區座標轉換成螢幕座標。
7 pPopup->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,GetParent());//在指定位置以指定的方式顯示快顯功能表。
8 CView::OnRButtonDown(nFlags, point);
9 }
1)用資源管理員添加一個菜單資源
2)在滑鼠右鍵訊息響應函數中,載入菜單資源,並獲得要顯示的子功能表指標,並用該指標調用TrackPopupMenu函數便完成任務(但要注意:滑鼠響應函數傳進來的座標是客戶區座標,而TrackPopupMenu函數中使用的是螢幕座標,在調用TrackPopupMenu前要調用ClientToScreen客戶區座標到螢幕座標的轉換)
3)快顯功能表上的訊息,在路由的時候,仍然遵循View-DOC-MainFrame-APP的響應順序。
動態菜單編程:
一些有關的比較重要的函數:
1 CMenu::AppendMenu //Appends a new item to the end of a menu.
2 CMenu::CreatePopupMenu //Creates an empty pop-up menu and attaches it to a CMenu object.
3 CMenu::InsertMenu
4 //Inserts a new menu item at the position specified by nPosition and moves other items down the menu.
5 CMenu::GetSubMenu //Retrieves a pointer to a pop-up menu.
6 CWnd::GetMenu //Retrieves a pointer to the menu for this window.
7 CMenu::DeleteMenu //Deletes an item from the menu.
1 CView* GetActiveView( ) const;//擷取當前視視窗指標(單文檔架構中)
記錄下自己的所學,雖然淺薄!!!如果我是一隻蝸牛,只能慢慢向上爬!