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


 

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

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

一、 創建菜單,有兩種方法

1. 用LoadMenu函數從資源加載

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

2. 用CreateMenu函數創建

menu1.CreateMenu(); //創建菜單,還沒有菜單項

二、 添加菜單項,可用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"); // 在第二項菜單項前添加新菜單項
三、 添加子菜單

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

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

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

四、 刪除菜單

用DeleteMenu()、RemoveMenu()函數來刪除指定位置的菜單/菜單項。

兩者區別:如果菜單項是一個彈出式菜單,那么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()
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.

七、 其他

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();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM