我的一個工具,使用vs2015mfc寫的,單文檔方式。
在打開一個文件的時候,想在當前的菜單中添加我自己的一個頂級菜單,文件關閉的時候,就刪除它。
在插入之前的樣子:
插入之後的樣子:
以下爲實現過程(以下都是在CMainFrame類中添加代碼):
首先定義兩個變量:
int m_plugMenuIndex; // 如果爲-1,則表示沒有插入
CMenu m_menuFromPlug;
第一個變量用於記錄這個頂級菜單插入的位置,第二個是插入的菜單內容,在OnCreateClient()初始化:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
...
m_plugMenuIndex = -1;
m_menuFromPlug.CreatePopupMenu();
}
當然,放在OnCreate()中初始化也可以。
添加菜單創建函數:
void CMainFrame::UpdateMenuFromPlug()
{
int menuCount = m_vecMenu.size();
if (menuCount == 0)
return;
CMenu *pmenu = GetMenu();
unsigned int flag = MF_POPUP | MF_STRING | MF_BYPOSITION;
// 先創建子菜單,注意,先刪除之前加入的項,因爲這些項在不同狀態下可能會變化
CString plugMStr = TEXT("高級功能");
while (m_menuFromPlug.GetMenuItemCount())
{
m_menuFromPlug.DeleteMenu(0, MF_BYPOSITION);
}
int im;
flag = MF_ENABLED | MF_STRING;
for (im = 0; im < menuCount; im++)
{
m_menuFromPlug.AppendMenu(flag, IDM_PLUGMENUSTART + im, m_vecMenu[im].strText);
}
MENUITEMINFOW menuStru;
memset(&menuStru, 0, sizeof(menuStru));
menuStru.cbSize = sizeof(menuStru);
menuStru.hSubMenu = m_menuFromPlug.GetSafeHmenu();
menuStru.fMask = MIIM_SUBMENU | MIIM_STRING;
menuStru.fType = MIIM_STRING;
menuStru.dwTypeData = (LPWSTR)plugMStr.GetString();
menuStru.cch = plugMStr.GetLength();
m_plugMenuIndex = 3; // 插到第三個位置
if (!pmenu->InsertMenuItem(m_plugMenuIndex, &menuStru, MF_BYPOSITION))
{
// 插入菜單失敗
m_plugMenuIndex = -1;
}
}
其中的m_vecMenu是要加入的菜單項列表,定義爲:vector<CString> m_vecMenu; ,在合適的地方插入內容就可以了。
這個函數是先創建這個要插入的頂級菜單,在創建之前,需要刪除之前插入的項,因爲打開不同的文件時,插入的菜單項可能不一樣,所以需要刪除。如果你沒有這些不同,那就沒有必要刪除它,自然,只要創建一次,後面也就不用再去創建它了。
這裏插入的位置設置爲第四項,如果最後在插入到系統菜單時失敗,則置插入的位置爲-1,這樣在文件關閉時就不用刪除它了。
在打開文件的接口中調用該函數 UpdateMenuFromPlug();
這樣就完成了菜單的加載。
在文件關閉時,刪除添加的菜單項,使菜單欄恢復打開文件之前的狀態:
if (m_plugMenuIndex >= 0)
{
CMenu *pmenu = GetMenu();
pmenu->RemoveMenu(m_plugMenuIndex, MF_BYPOSITION);
m_plugMenuIndex = -1;
DrawMenuBar();
}
注意,刪除之後的 DrawMenuBar() 函數必需調用,否則菜單欄不會刷新,只有當窗口變化的時候它纔會刷新,這樣就影響了界面的顯示效果。