雞啄米在上一節中講的是VS2010的菜單資源,本節主要講菜單及CMenu類的使用。

       CMenu類的主要成員函數

       MFC為菜單的操作提供了CMenu類,下面雞啄米就常用的幾個成員函數進行簡單的介紹。

       BOOL LoadMenu(UINT nIDResource);

       加載菜單資源,并將其附加到CMenu對象上。參數nIDResource指定了要加載的菜單資源的ID。如果菜單加載成功則返回TRUE,否則返回FALSE。

       BOOL DeleteMenu(UINT nPosition,UINT nFlags);

       在菜單中刪除一個菜單項。參數nPosition指定要刪除的菜單項。參數nFlags就用來解釋nPosition的意義,為MF_BYCOMMAND時說明nPosition表示菜單項的ID,為MF_BYPOSITION時說明nPosition表示菜單項的位置,第一個菜單項的位置為0。如果刪除菜單項成功則返回TRUE,否則返回FALSE。

       BOOL TrackPopupMenu(UINT nFlags,int x,int y,CWnd* pWnd,LPCRECT lpRect = 0);

       用來在指定位置顯示一個浮動的彈出式菜單。參數nFlags指定屏幕坐標和鼠標位置的標志,可以是以下取值:

       TPM_CENTERALIGN:菜單在水平方向上相對于參數x指定的坐標值居中顯示
       TPM_LEFTALIGN:菜單的左側與參數x指定的坐標值對齊
       TPM_RIGHTALIGN:菜單的右側與參數x指定的坐標值對齊
       TPM_BOTTOMALIGN:菜單的底部與參數y指定的坐標值對齊
       TPM_TOPALIGN:菜單項的頂部與參數y指定的坐標值對齊
       TPM_VCENTERALIGN:菜單在垂直方向上相對于參數y指定的坐標值居中顯示

       這里先介紹這幾個比較常用的,其他可參見MSDN。參數x指定彈出式菜單的水平方向的屏幕坐標,參數y指定菜單頂部垂直方向上的屏幕坐標,參數pWnd指明哪個窗口擁有此彈出式菜單,不能為NULL,參數lpRect忽略。

       UINT CheckMenuItem(UINT nIDCheckItem,UINT nCheck);

       在彈出菜單中為菜單項增加選中標記或移除選中標記。參數nIDCheckItem指定要選中或取消選中的菜單項。參數nCheck指定菜單項的選中狀態和如何根據nIDCheckItem確定菜單項的位置,可以是MF_CHECKED或MF_UNCHECKED與MF_BYPOSITION或MF_BYCOMMAND的組合,這幾個標志的含義如下:

       MF_BYCOMMAND:為默認值。說明參數nIDCheckItem表示菜單項的ID
       MF_BYPOSITION:說明參數nIDCheckItem表示菜單項的位置,第一個菜單項的位置是0
       MF_CHECKED:為菜單項添加選中標記
       MF_UNCHECKED:為菜單項移除選中標記

       該函數返回菜單項之前的狀態:MF_CHECKED或MF_UNCHECKED, 如果菜單項不存在則返回0xFFFFFFFF。

       UINT EnableMenuItem(UINT nIDEnableItem,UINT nEnable);

       激活、禁用菜單項或使其變灰。參數nIDEnableItem指定要激活、禁用或變灰的菜單項。參數nEnable指定操作的類型,可以是MF_DISABLED、MF_ENABLED或MF_GRAYED與MF_BYCOMMAND或MF_BYPOSITION的組合,這些值的含義如下:

       MF_BYCOMMAND:同CheckMenuItem
       MF_BYPOSITION:同CheckMenuItem
       MF_DISABLED:禁用菜單項,使其不能被選擇但不變灰
       MF_ENABLED:激活菜單項,使其能夠被選擇并由變灰狀態恢復
       MF_GRAYED:禁用菜單項,使其不能被選擇并變灰

       該函數返回菜單項之前的狀態:MF_DISABLED、MF_ENABLED或MF_GRAYED

       CMenu* GetSubMenu(int nPos) const;

       獲取彈出菜單的CMenu對象。參數nPos指定彈出菜單在菜單中的位置,不能使用ID。返回值是CMenu對象的指針,該CMenu對象的m_hMenu成員為由nPos指定的彈出菜單的句柄,如果不存在這樣的CMenu對象則返回NULL,然后創建一個臨時彈出菜單。

       CMenu類的成員函數先講這些,如果大家需要用其他的函數可以到MSDN中查看,解釋的很清楚。

       菜單消息

       菜單主要能發送兩種消息:COMMAND消息和UPDATE_COMMAND_UI消息。下面分別講解:

       COMMAND消息:在菜單項被點擊時發送該消息。

       UPDATE_COMMAND_UI消息:用來維護菜單項的各項狀態,包括激活、禁用、變灰、選中、未選中等。在下拉菜單每次打開的時候,所有菜單項的此消息都會被發送出去。如果所屬類中為菜單項的該消息添加了處理函數,則執行相應函數更新菜單狀態,如果菜單項沒有此消息處理函數,也沒有COMMAND消息的處理函數,那么它就會變灰。

       菜單的應用實例

       雞啄米先講一下本實例要實現的功能,此實例是在上一節創建的單文檔工程Example34的基礎上完成的,上一節中為主菜單欄添加了“Tools”菜單項,并設置它的第一個子菜單項為“Draw”,另外我們還要為主菜單欄添加“Settings”項,然后為其添加一個子菜單項“Draw Enable”,我們通過“Draw Enable”菜單項的選中狀態控制菜單項“Draw”的激活狀態,如果“Draw Enable”菜單項選中,則“Draw”菜單項激活,點擊它彈出一個MessageBox,否則“Draw”菜單項禁用。程序中已經在Example34View類中自動生成了OnRButtonUp(UINT /* nFlags */, CPoint point)函數,并在其中實現了彈出右鍵菜單的功能,這里雞啄米用CMenu類的TrackPopupMenu成員函數重新做一遍。

       注意:Example34的CMainFrame類中定義的菜單并沒有使用常用的CMenu類,而是用的CMFCMenuBar類(自VS2008起提供),但菜單的消息處理函數的添加是相同的。

       下面是具體步驟:

       1. 打開Example34工程的IDR_MAINFRAME菜單資源,在“Help”菜單項前通過“Insert New”操作插入一個菜單項,Caption設為“Settings”,在新菜單項的子菜單中再添加一個菜單項,Caption設為“Draw Enable”,ID默認為ID_SETTINGS_DRAWENABLE。

       2. 因為此菜單為CMainFrame所擁有,所以我們在CMainFrame類中對菜單進行操作。在“MainFrm.h”中為CMainFrame類添加成員變量bool m_bDraw,以標識當前是否可以點擊Tools->Draw菜單項,并在CMainFrame類的構造函數中為m_bDraw初始化:m_bDraw = TRUE。

       3. 為菜單項Tools->Draw的COMMAND消息和UPDATE_COMMAND_UI消息分別添加處理函數CMainFrame::OnToolsDraw()和OnUpdateToolsDraw(CCmdUI *pCmdUI),這里要注意,添加處理函數時class list中應選擇CMainFrame,修改兩個函數的實現為:

C++代碼
  1. void CMainFrame::OnToolsDraw()   
  2. {   
  3.     // TODO: Add your command handler code here   
  4.     // 彈出提示框   
  5.     MessageBox(_T("Draw"));   
  6. }   
  7.   
  8. void CMainFrame::OnUpdateToolsDraw(CCmdUI *pCmdUI)   
  9. {   
  10.     // TODO: Add your command update UI handler code here   
  11.     // 根據m_bDraw的值設置是否激活   
  12.     pCmdUI->Enable(m_bDraw);   
  13. }  

       4. 為菜單項Settings->Draw Enable的COMMAND消息和UPDATE_COMMAND_UI消息分別添加處理函數CMainFrame::OnSettingsDrawenable()和OnUpdateSettingsDrawenable(CCmdUI *pCmdUI),并將它們的實現修改為:

C++代碼
  1. void CMainFrame::OnSettingsDrawenable()   
  2. {   
  3.     // TODO: Add your command handler code here   
  4.     // 繪圖使能標識取反   
  5.     m_bDraw = !m_bDraw;   
  6. }   
  7.   
  8.   
  9. void CMainFrame::OnUpdateSettingsDrawenable(CCmdUI *pCmdUI)   
  10. {   
  11.     // TODO: Add your command update UI handler code here   
  12.     // 根據m_bDraw的值設置是否選中   
  13.     pCmdUI->SetCheck(m_bDraw);   
  14. }  

       5. 運行程序,效果圖如下:

VS2010菜單應用實例

       6. 接下來我們要重新實現右鍵菜單。大家以后可以仿照VS2010自動生成的代碼實現右鍵菜單,也可以用雞啄米下面講到的方法。首先將CExample34View::OnRButtonUp(UINT /* nFlags */, CPoint point)函數內的代碼都注釋掉,保證原來的彈出方法失效。

       7. 自動生成代碼是在鼠標彈起時實現的右鍵菜單,我們這里改為在鼠標按下時就彈出右鍵菜單。在class view類視圖中點擊CExample34View,然后在屬性頁的messages列表中找到WM_RBUTTONDOWN,添加其消息響應函數CExample34View::OnRButtonDown(UINT nFlags,CPoint point),修改其實現為:

C++代碼
  1. void CExample34View::OnRButtonDown(UINT nFlags, CPoint point)   
  2. {   
  3.     // TODO: Add your message handler code here and/or call default   
  4.     CMenu menu;       // 菜單(包含主菜單欄和子菜單)   
  5.     CMenu *pSubMenu;  // 右鍵菜單   
  6.   
  7.     // 加載菜單資源到menu對象   
  8.     menu.LoadMenu(IDR_POPUP_EDIT);   
  9.     // 因為右鍵菜單是彈出式菜單,不包含主菜單欄,所以取子菜單   
  10.     pSubMenu = menu.GetSubMenu(0);   
  11.     // 將坐標值由客戶坐標轉換為屏幕坐標   
  12.     ClientToScreen(&point);   
  13.     // 彈出右鍵菜單,菜單左側與point.x坐標值對齊   
  14.     pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);   
  15.   
  16.     CView::OnRButtonDown(nFlags, point);   
  17. }  

       8. 最終的右鍵菜單效果: 

VS2010右鍵菜單的實現

       本節內容不少,大家可以慢慢消化。菜單的講解就到這里了。雞啄米謝謝大家的關注和支持。

除非特別注明,雞啄米文章均為原創
轉載請標明本文地址:http://www.vkzldl.live/software/212.html
2012年7月30日
作者:雞啄米 分類:軟件開發 瀏覽: 評論:24