我的一个工具,使用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() 函数必需调用,否则菜单栏不会刷新,只有当窗口变化的时候它才会刷新,这样就影响了界面的显示效果。