0

有人遇到过这个问题吗?

我在 MDI 应用程序上使用 MFC。我使用 SetMenu() 在菜单之间切换,但是当我最大化子窗口时,系统菜单(最大化、最小化、关闭按钮)的副作用会消失。

CMenu* pMenu = GetMenu();
if (pMenu == NULL) return;
pMenu->Detach();

// Reset application menu
CMenu newMenu;
newMenu.LoadMenu(menuID);
SetMenu(&newMenu);

如果我不调用 SetMenu(),则问题不会发生。

4

2 回答 2

2
CMenu newMenu;
newMenu.LoadMenu(menuID);
SetMenu(&newMenu);

newMenu是一个临时对象。一旦函数退出,它将被销毁。结果是未定义的行为。

CMenu* pMenu = GetMenu();
if (pMenu == NULL) return;
pMenu->Detach();

我不确定这段代码会完成什么。请注意,CWnd::SetMenu将替换旧菜单。它不会破坏旧的菜单句柄,但 MFC 将在最后处理清理(Detach如果这是目标,则不会破坏句柄)


试试这个代码:

将菜单对象声明为类成员:

class CMainFrame : public CMDIFrameWnd
{
    CMenu m_menu1, m_menu2;
    ...
};

加载一次菜单:

CMainFrame::CMainFrame()
{
    m_menu1.LoadMenu(IDR_MENU1);
    m_menu2.LoadMenu(IDR_MENU2);
    ...
}

更改菜单:

void CMainFrame::OnChangeMenu()
{
    if(want_menu1)
    {
        SetMenu(&m_menu1);
    }
    else if (want_menu2)
    {
        SetMenu(&m_menu2);
    }
}
于 2019-02-07T05:19:06.417 回答
1

我会推荐一些不同的东西:只需使用 MFC 最初设计的菜单管理功能。对于典型的 MDI MFC 应用程序,您实际上不需要对菜单做任何事情(我的意思是这些对 的调用SetMenu())。只需定义它们,MFC 将为您完成其余的工作。

更具体地说,向导生成的 MDI 应用程序包含以下菜单:

  • IDR_MAINFRAME,不存在MDI子窗口(打开文档)时显示。通常包含FileViewHelp子菜单。
  • IDR_DocType, 一个用于您定义的每种文档类型。当显示此类型文档的 MDI 子窗口是活动窗口时,会显示此信息。通常包含FileEdit、 View 、WindowHelp子菜单。

请注意:

  • 您只需定义/编辑这些菜单,例如添加更多命令甚至更多子菜单。你不需要切换菜单,框架会为你做这件事。
  • 框架不会合并子菜单或菜单项,它只会选择IDR_MAINFRAME其中之一IDR_DocType,具体取决于当前活动的 MDI 子窗口。
  • 因此,一些子菜单或项目可能是重复的(尽管不一定是完全相同的副本),而另一些则不是。例如,View子菜单IDR_MAINFRAME通常包含两个菜单项,Toolbar(或Toolbars)和Status Bar(切换工具栏和状态栏的显示),而特定于 doctype 的通常包含上述内容,以及一些附加的,确定如何显示文件;例如,如果文档是图像,您通常会添加一些显示选项,例如1:1Fit To WidthFit To HeightBest Fit(在单选按钮设置中),显示在工具栏上方和状态栏,用分隔符菜单项分隔。

我已经开发了很多这样的应用程序,并且从来没有使用过SetMenu(). 我建议您首先将IDR_MAINFRAMEIDR_DocType菜单恢复到原始状态,然后放入任何其他/自定义的菜单。如果您破坏或更改了最初由向导生成的菜单,您可以使用与您的设置相同的设置创建一个新的 MFC 项目/解决方案,然后将菜单复制粘贴到资源文件中。

于 2019-02-07T20:16:26.403 回答