MFC菜单打开标签页动态菜单

MFC menus Open tabs dynamic menu

我正在使用 MFC 应用程序,想删除显示在“排列图标”下的动态条目。

我不确定这是如何添加到应用程序中的,或者我该如何关闭它?

打开 windows 的列表由 MFC 框架添加到“Window”菜单,在 WM_INITMENUPOPUP 命令的应用程序主 window 处理程序中。 (实际上,框架将项目添加到所有已经包含 ID 介于 AFX_IDM_WINDOW_FIRSTAFX_IDM_WINDOW_LAST 之间的命令的菜单 - 其中包括“Cascasde”、“Tile...”和“Arrange Icons”默认值。)

您可以通过将 ON_WM_INITMENUPOPUP() 处理程序添加到框架 window 的消息映射并覆盖该框架的 OnInitMenuPopup() member function.

来删除这些项目

假设您的主框架派生自 CMDIFrameWnd class,此覆盖将如下所示:

void MyFrameWnd::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
    CMDIFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);// Call base class FIRST
    // <Insert any other code for your override>
    UINT commID = AFX_IDM_FIRST_MDICHILD; // MFC gives the first item this ID
    BOOL hadID;
    do {
        hadID = pPopupMenu->RemoveMenu(commID, MF_BYCOMMAND);
        ++commID;
    } while (hadID);
    return;
}

你的 class 中函数的 声明 应该正确地具有 afx_msg 属性,如下所示,虽然这通常被定义为 'nothing' 在最近的 MFC 版本中:

class MyFrameWnd : public CMDIFrameWnd
{
    //...
protected:
    afx_msg void OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu);
    //...

如果您更喜欢这样的压缩代码,您还可以将删除 'loop' 代码减少到以下单行:

    for (UINT commID = AFX_IDM_FIRST_MDICHILD; Menu->RemoveMenu(commID, MF_BYCOMMAND); ++commID) ; // Empty loop

请注意,此删除过程会在您应用程序的“Window”菜单底部留下一个 'separator';删除它也会涉及更多的工作,因为该分隔符没有命令 ID – 因此您需要确定它在菜单中的位置(索引)并使用该索引调用 RemoveMenu() 函数,并且MF_BYPOSITION 标记为第二个参数。

使用第一个代码段中的代码,并假设分隔符位于菜单的最后,这可以通过在删除循环之后添加以下代码来实现:

    if (commID > AFX_IDM_FIRST_MDICHILD + 1) { // We removed at least one item, so ...
        int nItems = Menu->GetMenuItemCount(); // ... remove the separator,
        pPopupMenu->RemoveMenu(nItems - 1, MF_BYPOSITION); // assuming it's the last item!
    }