如何動態添加菜單/菜單項、子菜單、右鍵菜單

 

有關菜單的操做主要用到CMenu類,固然也可用相應API函數,CMenu類只是MFC對API中操做菜單的函數的封裝而已。 不過能用類就儘可能用類,類的組織方式好唄,代碼看着也舒服。 如果SDK編程,那就用API吧 。 編程

CMenu menuMain,menu1; //首先 定義CMenu對象 ide

1、 建立菜單,有兩種方法

1. 用LoadMenu函數從資源加載 函數

menuMain.LoadMenu(IDR_MAINFRAME); //從資源加載,這裏使用SDI的主菜單資源 ui

2. 用CreateMenu函數建立 this

menu1.CreateMenu(); //建立菜單,尚未菜單項 spa

2、 添加菜單項,可用AppendMenu()在菜單的最後加、InsertMenu()在指定的位置加.
// 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"); // 在第二項菜單項前添加新菜單項
3、 添加子菜單

一樣用AppendMenu()、InsertMenu()函數。不過要注意參數的設置。 code

menu1.AppendMenu(MF_BYPOSITION|MF_POPUP|MF_STRING,(UINT) menuMain.GetSubMenu(0) ->m_hMenu,"子菜單");

//第二個參數是菜單的句柄HMENU 對象

4、 刪除菜單

用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刪除。

5、 添加右鍵菜單
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();
6、 響應菜單的事件

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()
2) 在.cpp文件中,

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的返回值來處理。在參數uFlags中設置TPM_ RETURNCMD,這樣返回值就是你選擇的菜單項的ID,而後能夠根據ID來處理。
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.

7、 其餘

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();
相關文章
相關標籤/搜索