在應用程序中,往往要根據當前的操作來增加相應的菜單。動態增加菜單的方法有多種,本文只講述利用資源編輯器預創建菜單資源,然后在程序運行中動態加入(或刪除)到主菜單中去的方法。
一、用AppWizard建立一個單文檔工程,默認一切選項。在WorkSpace(工作空間)的ResourecView頁中右擊Menu資源,加入一個新的菜單,其ID為:IDR_MENU1。為IDR_MENU1加入一個菜單項和相應的子菜單。如(圖一)所示。
二、編輯IDR_MAINFRAME菜單(ID為IDR_MAINFRAME的菜單一般均為主菜單),在【查看(V)】菜單項下面增加二個子菜單項。如(圖二)所示。其屬性如下:
ID
Caption
IDC_ADD
加入菜單
IDC_DELETE
刪除菜單
三、要訪問要菜單,可使用CWnd類的GetMenu()成員函數、或使用全局函數AfxGetMainWnd()―>GetMenu(),它們都返回一個CMenu對象的指針。一旦得到Cmenu指針,就可以對菜單進行各種操作(裝入、增加、插入,刪除,更新等等)。通過Cmenu指針對菜單進行操作后,應使用Cmenu類的Detach()成員函數從Cmenu對象中分離出菜單,避免發生沖突。之后調用CWnd::DrawMenuBar()重畫菜單。
四、為實現加入、刪除操作,我們用“ClassWizard”向導為IDC_ADD和IDC_DELETE增加兩個COMMAND消息映射函數,它們分別為CMainFrame::OnAdd()
和CMainFrame::OnDelete()。接著我們為其編寫代碼如下:
void CMainFrame::OnAdd() //加入菜單操作。
{
CMenu addmenu,*mainmenu;
if(!addmenu.LoadMenu(IDR_MENU1)) //裝入菜單資源。
{
MessageBox("菜單裝入失敗!","錯誤",MB_OK|MB_ICONERROR);
return; //如裝入失敗,顯示消息框,且返回。
}
CString str="顏色(&C)"; //要增加的菜單項的標簽。
mainmenu=AfxGetMainWnd()->GetMenu();
//取得指向窗口菜單的Cmenu對象的指針。
mainmenu->InsertMenu (1,MF_POPUP|MF_BYPOSITION|MF_STRING,
(UINT)addmenu.GetSubMenu(0)-> m_hMenu,str);
//將彈出式菜單插入到第2項菜單之前(菜單項從0開始計算)。
// addmenu.GetSubMenu(0)-> m_hMenu是被裝入菜單的第一個菜單項的彈出式菜單的菜單句柄。
mainmenu->Detach(); //將窗口菜單與Cmenu對象分離。
addmenu.Detach(); //將資源菜單(IDR_MENU1)與Cmenu對象分離。
DrawMenuBar(); //重畫菜單。
}
Cmenu::InsertMenu的函數原形如下:
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR
lpszNewItem = NULL );
參數 nPosition:指定在那個菜單項前插入新菜單項。被參數nFlags用于以下列方式解釋nPosition
NFlags參數
NPosition參數的解釋
MF_BYCOMMAND
指定參數給出巳存在的菜單項的命令ID號。此為缺省值。
MF_BYPOSITION
指定參數給出巳存在的菜單項的位置。第一項位于位置0。如果Nposition為-1,新菜單將添加到菜單尾。
參數 nFlags:指定Nposition、nIDNewItem、lpszNewItem值如何被解釋。
參數 nIDNewItem:指定新菜單項的命令ID號,或者,若nFlags被設置為MF_POPUP,則指定為彈出菜單的菜單句柄(HMENU)。若nFlags被設置為MF_SEPARATOR,那么參數nIDNewItem將被忽略。
參數 lpszNewItem:指定新菜單項的文本。被nFlags以下列方式解釋
NFlags參數
LpszNewItem的解釋
MF_STRING
包含指向以空格位終止符的字符串指針。它為缺省解釋。
MF_SEPARATOR
參數將被忽略。
void CMainFrame::OnDelete() //刪除菜單操作。
{
CMenu *mainmenu;
CString str;
mainmenu=GetMenu(); //取得指向窗口菜單的Cmenu對象的指針。
for(int i=mainmenu->GetMenuItemCount()-1;i>=0;i--) //取得菜單的項數。
{
mainmenu->GetMenuString(i,str,MF_BYPOSITION);
//將指定菜單項的標簽拷貝到指定的緩沖區。MF_BYPOSITION的解釋見上。
if(str=="顏色(&C)") //如果是剛才我們增加的菜單項,則刪除。
{
mainmenu->DeleteMenu(i,MF_BYPOSITION);
break;
}
}
mainmenu->Detach(); //將窗口菜單與Cmenu對象分離。
DrawMenuBar(); //重畫菜單。
}
五、編譯,運行程序,看看到底是怎樣的!用這種方法動態增加菜單有它的好處:即我們可以事先為菜單ID編寫好COMMAND、UPDATE_COMMAND_UI消息映射入口,在程序需要時動態的裝入菜單即可。