有關菜單的操做主要用到CMenu類,固然也可用相應API函數,CMenu類只是MFC對API中操做菜單的函數的封裝而已。 不過能用類就儘可能用類,類的組織方式好唄,代碼看着也舒服。 如果SDK編程,那就用API吧 。 編程
CMenu menuMain,menu1; //首先 定義CMenu對象 ide
1. 用LoadMenu函數從資源加載 函數
menuMain.LoadMenu(IDR_MAINFRAME); //從資源加載,這裏使用SDI的主菜單資源 ui
2. 用CreateMenu函數建立 this
menu1.CreateMenu(); //建立菜單,尚未菜單項 spa
// ID_TEST1 在Resource.h 中定義,隨便給個整數值,不要和已有的重複就好了 menu1.AppendMenu(MF_STRING,ID_TEST1,"Test1"); // 第一項菜單項 menu1.AppendMenu(MF_STRING,ID_TEST2,"Test2"); // 第二項菜單項 menu1.InsertMenu(1,MF_BYPOSITION|MF_STRING,(UINT)ID_TEST1,"ID_TEST1"); // 在第二項菜單項前添加新菜單項
一樣用AppendMenu()、InsertMenu()函數。不過要注意參數的設置。 code
menu1.AppendMenu(MF_BYPOSITION|MF_POPUP|MF_STRING,(UINT) menuMain.GetSubMenu(0) ->m_hMenu,"子菜單");
//第二個參數是菜單的句柄HMENU 對象
用DeleteMenu()、RemoveMenu()函數來刪除指定位置的菜單/菜單項。 blog
二者區別:若是菜單項是一個彈出式菜單,那麼DeleteMenu和RemoveMenu之間的區別就很重要。DeleteMenu清除彈出式菜單,但RemoveMenu不清除它。一個是完全的刪除,一個只是移除. 事件
MSDN:
1.The DeleteMenu function destroys the handle to the menu or submenu and frees the memory used by the menu or submenu.
它使菜單或者子菜單的handle無效(destroys)。
2. RemoveMenu does not destroy the menu or its handle, allowing the menu to be reused.
能夠再利用,並不從內存中將menu刪除。
CMenu menu1; menu1.CreatePopupMenu(); //動態建立彈出式菜單對象 menu1.AppendMenu(MF_STRING,ID_TEST1," 菜單項1"); menu1.AppendMenu(MF_STRING,ID_TEST2," 菜單項2"); menu1.InsertMenu(2,MF_BYPOSITION|MF_POPUP|MF_STRING,(UINT) menuMain.m_hMenu,"子菜單"); //添加子菜單 CPoint pt; GetCursorPos(&pt); menu1.TrackPopupMenu(TPM_RIGHTBUTTON, pt.x, pt.y, this); menu1.DestroyMenu();
1. 如果資源中添加的菜單可用Class Wizard添加菜單的響應事件。
2. 如果經過代碼建立的菜單,要手工實現菜單的消息映射。本例是在CmainFrame類中,固然也可在View類、Doc類中,基於對話框的一樣也能夠。
1) 在.h文件中
// Generated message map functions protected: //{{AFX_MSG(CMainFrame) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnChangmenuitem(); //這裏添加菜單命令處理函數的聲明 //}}AFX_MSG DECLARE_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_COMMAND(IDM_CHANGMENUITEM, OnChangmenuitem) //這裏添加,注意沒有’ ;’ //}}AFX_MSG_MAP END_MESSAGE_MAP() void CMainFrame::OnChangmenuitem() { // 這裏寫你要如何處理的代碼 …… }
若菜單ID值是連續的,最好用ON_COMMAND_RANGE來映射消息處理函數,能夠在一個函數中處理一個範圍內的全部消息。
當用戶按下某個菜單項,會發出一個WM_COMMAND消息,而菜單項的ID號,就包含在參數wParam的低位中.
BOOL CYourView::OnCommand(WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class UINT m_nItemID=LOWORD(wParam); if (m_nItemID==ID_YOURITEM) //ID_YOURITEM爲你加入菜單項時指定的ID號 { //在這裏放入響應的代碼 } return CScrollView::OnCommand(wParam, lParam); }
TrackPopupMenu(TPM_ RETURNCMD ,pt.x,pt.y,this);
MSDN:If you specify TPM_RETURNCMD in the uFlags parameter, the return value is the menu-item identifier of the item that the user selected.
DrawMenuBar () ; //當您改變菜單時,須要重畫菜單才能顯示所作的改變
GetSystemMenu () ; //取得窗口控制窗口
GetMenu() //取得當前程序使用的菜單
GetSubMenu() //取得子菜單
應使用CMenu類的Detach()成員函數從Cmenu對象中分離出菜單句柄,避免對象失效後程序出錯。
如:
CMenu menu; menu.CreatePopupMenu(); //動態建立彈出式菜單對象 menu.AppendMenu(0,ID_TEST1,"Test1"); menu.AppendMenu(0,ID_TEST2,"Test2"); CMenu* menuMain = GetMenu(); //取得程序主菜單 需在CMainFrame類中 menuMain->AppendMenu(MF_BYPOSITION|MF_POPUP|MF_STRING,(UINT)menu.m_hMenu,"子菜單1"); menu.Detach(); //直接用menu.m_hMenu在運行時出錯,menu對象在這個事件結束就銷燬了 DrawMenuBar();