Системные меню исчезают, когда я увеличиваю дочернее окно

Кто-нибудь сталкивался с этой проблемой?

Я использую MFC в приложении MDI. Я переключаюсь между меню с помощью SetMenu(), но побочный эффект системных меню (кнопки "Развернуть", "Свернуть", "Закрыть") исчезает при развертывании дочерних окон.

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

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

Если я не вызываю SetMenu(), проблема не возникает.

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);
    }
}

Я бы порекомендовал что-то другое: просто используйте функциональность управления меню, как первоначально предполагалось MFC. Для типичного приложения MDI MFC вам не нужно ничего делать с меню (и я имею в виду эти вызовы SetMenu()). Только определите их, и MFC сделает все остальное за вас.

В частности, приложение MDI, созданное мастером, содержит следующие меню:

  • IDR_MAINFRAME, который будет отображаться при отсутствии дочернего окна MDI (открытый документ). Обычно содержит подменю File, View и Help.
  • IDR_DocType по одному для каждого типа документа, который вы определили. Это отображается, когда дочернее окно MDI, отображающее документ этого типа, является активным. Обычно содержит подменю File, Edit, View, Window и Help.

Обратите внимание, что:

  • Вам нужно только определить / отредактировать эти меню, например, добавить больше команд или даже больше подменю. Вам не нужно переключать меню, фреймворк сделает это за вас.
  • Фреймворк НЕ объединит подменю или пункты меню, вместо этого он просто выберет IDR_MAINFRAME или один из IDR_DocType в зависимости от активного дочернего окна MDI.
  • Следовательно, некоторые из подменю или пунктов могут быть дубликатами (хотя и не обязательно точными копиями), а некоторые нет. Например, подменю Просмотр для IDR_MAINFRAME обычно содержит два элемента меню, Панель инструментов (или Панели инструментов) и Строка состояния (переключение отображения панели инструментов и строки состояния), в то время как специфичные для doctype, как правило, содержат вышеперечисленное, а также некоторые дополнительные, определяющие способ отображения документа; Например, если документ представляет собой изображение, вы обычно добавляете некоторые варианты отображения, такие как 1: 1, Подогнать по ширине, Подогнать по высоте и Подогнать по размеру (в настройках переключателя), показанные над панелью инструментов и строкой состояния, разделенные разделитель меню-пункт.

Я разработал много таких приложений, и мне никогда не приходилось использовать SetMenu(), Я хотел бы предложить вам сначала восстановить IDR_MAINFRAME а также IDR_DocType меню в исходное состояние, а затем вставьте любые дополнительные / пользовательские. Если вы уничтожили или значительно изменили меню, изначально созданные мастером, вы можете создать новый проект / решение MFC с теми же настройками, что и у вас, и скопировать и вставить меню в файл ресурсов.

Другие вопросы по тегам