当我最大化子窗口时,系统菜单消失

时间:2019-02-07 03:42:32

标签: c++ mfc mdi cview

有人遇到过这个问题吗?

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

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

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

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

2 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分:1)

我建议采取其他措施:只需使用MFC最初打算的菜单管理功能即可。对于典型的MDI MFC应用程序,您实际上不需要对菜单做任何事情(我的意思是这些对SetMenu()的调用)。仅定义它们,MFC就会为您完成其余的工作。

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

  • IDR_MAINFRAME,当不存在MDI子窗口(打开的文档)时将显示。通常包含 File View Help 子菜单。
  • IDR_DocType,用于您定义的每种文档类型。当显示此类文档的MDI子窗口为活动窗口时,将显示该窗口。通常包含文件编辑,视图,窗口 Help 子菜单。

请注意:

  • 您只需要定义/编辑这些菜单,例如添加更多命令或 甚至更多的子菜单。您无需切换菜单,框架 会为您做到这一点。
  • 该框架不会合并子菜单或菜单项,而是仅选择IDR_MAINFRAMEIDR_DocType中的一个,具体取决于当前活动的MDI子窗口。
  • 因此,某些子菜单或项目可能是重复的(尽管不一定是精确的副本),而另一些则不是。例如,IDR_MAINFRAME View 子菜单通常包含两个菜单项,即 Toolbar (或 Toolbars )和状态栏(切换工具栏和状态栏的显示),而特定于doctype的文档通常包含以上内容,另外还包含一些其他内容,以确定如何显示文档;例如,如果文档是图像,则通常会添加一些显示选项,例如 1:1 适合宽度适合高度和< em>最适合(在单选按钮设置中),显示在工具栏状态栏上方,并用分隔符菜单项分隔。

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