程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 如何動態添加菜單/菜單項、子菜單、右鍵菜單,菜單項子菜單

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

編輯:C++入門知識

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


 

有關菜單的操作主要用到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();

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved