О меню

Меню — это список элементов, определяющих параметры или группы параметров (подменю) для приложения. При щелчке элемента меню открывается подменю или приложение выполняет команду. В этом разделе содержатся сведения о следующих разделах:

Меню упорядочено в иерархии. На верхнем уровне иерархии находится строка меню, содержащая список меню, которые, в свою очередь, могут содержать подменю. Строка меню иногда называется меню верхнего уровня, а меню и подменю также называются всплывающих меню.

Элемент меню может выполнить команду или открыть подменю. Элемент, выполняющий команду, называется элементом команды или командой.

Элемент в строке меню почти всегда открывает меню. В строках меню редко содержатся элементы команды. Меню, открывающееся в раскрывающемся меню из строки меню, иногда называется раскрывающимся меню. При отображении раскрывающегося меню он присоединяется к строке меню. Элемент меню в строке меню, открывающий раскрывающееся меню, также называется именем меню.

Имена меню в строке меню представляют основные категории команд, которые предоставляет приложение. Выбор имени меню в строке меню обычно открывает меню, элементы меню которого соответствуют командам в категории. Например, строка меню может содержать имя меню "Файл", которое при щелчке пользователя активирует меню с такими элементами меню, как "Создать", "Открыть" и "Сохранить". Чтобы получить сведения о строке меню, вызовите GetMenuBarInfo.

В строке меню может содержаться только перекрывающееся или всплывающее окно; Дочернее окно не может содержать одно. Если в окне есть строка заголовка, система размещает строку меню прямо под ней. Строка меню всегда отображается. Однако подменю не отображается, пока пользователь не выберет элемент меню, который активирует его. Дополнительные сведения о перекрывающихся и всплывающих окнах см. в разделе "Типы окон".

Каждое меню должно иметь окно владельца. Система отправляет сообщения в окно владельца меню, когда пользователь выбирает меню или выбирает элемент из меню.

В этом разделе рассматриваются следующие разделы.

Контекстные меню

Система также предоставляет контекстные меню. Контекстное меню не присоединено к строке меню; он может отображаться в любом месте экрана. Приложение обычно связывает контекстное меню с частью окна, например клиентской областью или определенным объектом, например значком. По этой причине эти меню также называются контекстными меню.

Контекстное меню остается скрытым, пока пользователь не активирует его, как правило, щелкнув правой кнопкой мыши выделение, панель инструментов или кнопку панели задач. Меню обычно отображается в расположении курсора или курсора мыши.

Меню окна

Меню окна (также известное как меню "Система" или "Управление") — это всплывающее меню, определенное и управляемое почти исключительно операционной системой. Пользователь может открыть меню окна, щелкнув значок приложения в строке заголовка или щелкнув правой кнопкой мыши в строке заголовка.

Меню "Окно " предоставляет стандартный набор элементов меню, которые пользователь может выбрать для изменения размера или положения окна или закрытия приложения. Элементы в меню окна можно добавлять, удалять и изменять, но большинство приложений просто используют стандартный набор элементов меню. В перекрывающемся, всплывающем окне или дочернем окне может быть меню окна. Это редкость для перекрывающегося или всплывающего окна, чтобы не включать меню окна.

Когда пользователь выбирает команду из меню "Окно ", система отправляет сообщение WM_SYSCOMMAND в окно владельца меню. В большинстве приложений процедура окна не обрабатывает сообщения из меню окна. Вместо этого он просто передает сообщения функции DefWindowProc для обработки сообщения по умолчанию системы. Если приложение добавляет команду в меню окна, процедура окна должна обработать команду.

Приложение может использовать функцию GetSystemMenu для создания копии меню окна по умолчанию для изменения. Любое окно, которое не использует функцию GetSystemMenu для создания собственной копии меню окна, получает стандартное меню окна.

Идентификатор справки

Связанная с каждой строкой меню, меню, подменю и контекстным меню является идентификатором справки. Если пользователь нажимает клавишу F1 во время активности меню, это значение отправляется в окно владельца в рамках сообщения WM_HELP.

Доступ к меню с помощью клавиатуры

Система предоставляет стандартный интерфейс клавиатуры для меню. Этот интерфейс можно улучшить, предоставив ключи mnemonic access и сочетания клавиш (акселератор) для элементов меню.

В следующих разделах описан стандартный интерфейс клавиатуры, клавиши доступа и сочетания клавиш:

Стандартный интерфейс клавиатуры

Система предназначена для работы с мышью или без другого указателя устройства. Так как система предоставляет стандартный интерфейс клавиатуры, пользователь может использовать клавиатуру для выбора элементов меню. Этот интерфейс клавиатуры не требует специального кода. Приложение получает командное сообщение, выбирает ли пользователь пункт меню с помощью клавиатуры или с помощью мыши. Стандартный интерфейс клавиатуры обрабатывает следующие нажатия клавиш.

Клавиши Действие
Алфавитный символ Выбирает первый пункт меню с указанным символом в качестве ключа доступа. Если выбранный элемент вызывает меню, отображается меню и выделен первый элемент. В противном случае выбран элемент меню.
ALT Переключатель в режиме строки меню и вне него.
ALT + ПРОБЕЛ Отображает меню окна.
ВХОД В СИСТЕМУ Активирует меню и выбирает первый пункт меню, если элемент связан с ним. В противном случае этот нажатие клавиши выбирает элемент, как если пользователь выпустил кнопку мыши во время выбора элемента.
ESC Завершает режим меню.
СТРЕЛКА ВЛЕВО Циклирует предыдущий пункт меню верхнего уровня. Элементы меню верхнего уровня включают имена меню и меню окна. Если выбранный элемент находится в меню, выбран предыдущий столбец в меню или выбран предыдущий элемент меню верхнего уровня.
СТРЕЛКА ВПРАВО Работает как клавиша СТРЕЛКА ВЛЕВО, за исключением противоположного направления. В меню этот нажатие клавиши перемещается вперед по одному столбцу; Если выбранный элемент находится в правом верхнем столбце, то выбрано следующее меню.
СТРЕЛКИ ВВЕРХ ИЛИ ВНИЗ Активирует меню при нажатии имени меню. При нажатии в меню нажатие клавиш СТРЕЛКА ВВЕРХ выбирает предыдущий элемент; Нажатие клавиш СТРЕЛКА ВНИЗ выбирает следующий элемент.

 

Стандартный интерфейс клавиатуры для меню можно расширить, добавив клавиши доступа (mnemonics) в пункты меню. Ключ доступа — это подчеркнутая буква в тексте элемента меню. Если меню активно, пользователь может выбрать пункт меню, нажав клавишу, соответствующую подчеркиваемой букве элемента. Пользователь активен в строке меню, нажав клавишу ALT, чтобы выделить первый элемент в строке меню. Меню активно при отображении.

Чтобы создать ключ доступа для элемента меню, предшествуйте любому символу текстовой строки элемента с амперсандом. Например, текстовая строка "&Move" приводит к тому, что система подчеркивает букву "M".

Помимо наличия ключа доступа, элемент меню может иметь ярлык ключа, связанный с ним. Сочетание клавиш отличается от ключа доступа, так как меню не должно быть активным для работы сочетания клавиш. Кроме того, ключ доступа всегда связан с элементом меню, а сочетание клавиш обычно (но не обязательно) связано с элементом меню.

Текст, определяющий сочетание клавиш, добавляется в текстовую строку элемента меню. Контекстный текст отображается справа от имени элемента меню после обратной косой черты и символа табуляции (\t). Например, "&Close\tAlt+F4" представляет команду Close с сочетанием клавиш ALT+F4 в качестве ярлыка и буквой "C" в качестве ключа доступа. Дополнительные сведения см. в разделе "Ускорители клавиатуры".

Можно создать меню с помощью шаблона меню или функций создания меню. Шаблоны меню обычно определяются как ресурсы. Ресурсы шаблонов меню можно загрузить явным образом или назначить в качестве меню по умолчанию для класса окна. Вы также можете динамически создавать ресурсы шаблонов меню в памяти.

В следующих разделах подробно описано создание меню:

Большинство приложений создают меню с помощью ресурсов шаблона меню. Шаблон меню определяет меню, включая элементы в строке меню и все меню. Сведения о создании ресурса шаблона меню см. в документации, включенной в средства разработки.

После создания ресурса шаблона меню и добавления его в исполняемый файл приложения (.exe) можно использовать функцию LoadMenu для загрузки ресурса в память. Эта функция возвращает дескриптор в меню, которое затем можно назначить окну с помощью функции SetMenu. Меню можно назначить любому окну, которое не является дочерним окном.

Реализация меню в качестве ресурсов упрощает локализацию приложения для использования в нескольких странах или регионах. Для каждого языка необходимо локализовать только файл определения ресурсов, а не исходный код приложения.

Меню можно создать из шаблона меню, встроенного в память во время выполнения. Например, приложение, позволяющее пользователю настраивать его меню, может создать шаблон меню в памяти на основе предпочтений пользователя. Затем приложение может сохранить шаблон в файле или реестре для дальнейшего использования. Чтобы создать меню из шаблона в памяти, используйте функцию LoadMenuIndirect . Описание форматов шаблонов меню см. в разделе "Ресурсы шаблона меню".

Стандартный шаблон меню состоит из структуры MENUITEMTEMPLATEHEADER, за которой следует одна или несколько структур MENUITEMTEMPLATE.

Шаблон расширенного меню состоит из MENUEX_TEMPLATE_HEADER структуры, за которой следует одна или несколько MENUEX_TEMPLATE_ITEM структур.

Система создает уникальный дескриптор для каждого меню. Дескриптор меню — это значение типа HMENU. Приложение должно указать дескриптор меню во многих функциях меню. Вы получаете дескриптор в строке меню при создании меню или загрузке ресурса меню.

Чтобы получить дескриптор в строке меню для созданного или загруженного меню, используйте функцию GetMenu . Чтобы получить дескриптор в подменю, связанном с элементом меню, используйте функцию GetSubMenu или GetMenuItemInfo. Чтобы получить дескриптор в меню окна, используйте функцию GetSystemMenu .

С помощью функций создания меню можно создавать меню во время выполнения или добавлять элементы меню в существующие меню. Функцию CreateMenu можно использовать для создания пустой строки меню и функции CreatePopupMenu для создания пустого меню. Некоторые параметры можно сохранить для меню с помощью структуры MENUINFO . Чтобы получить или получить параметры меню, используйте GetMenuInfo или SetMenuInfo. Чтобы добавить элементы в меню, используйте функцию InsertMenuItem . Старые функции AppendMenu и InsertMenu по-прежнему поддерживаются, но InsertMenuItem следует использовать для новых приложений.

После загрузки или создания меню оно должно быть назначено окну, прежде чем система сможет отобразить ее. Вы можете назначить меню, определив меню класса. Дополнительные сведения см. в меню классов окон. Кроме того, можно назначить меню окну, указав дескриптор в меню в качестве параметра hMenu функции CreateWindow или CreateWindowEx или вызвав функцию SetMenu.

Чтобы отобразить контекстное меню, используйте функцию TrackPopupMenuEx . Контекстные меню, также называемые всплывающими меню или контекстными меню, обычно отображаются при обработке сообщения WM_CONTEXTMENU .

Меню можно назначить любому окну, которое не является дочерним окном.

Старая функция TrackPopupMenu по-прежнему поддерживается, но новые приложения должны использовать функцию TrackPopupMenuEx.

Меню классов окон

При регистрации класса окна можно указать меню по умолчанию, называемое меню класса. Для этого назначьте имя ресурса-шаблона меню участнику lpszMenuName структуры WNDCLASS, используемой для регистрации класса.

По умолчанию каждое окно назначается меню класса для своего класса окна, поэтому не нужно явно загружать меню и назначать его каждому окну. Можно переопределить меню класса, указав другой дескриптор меню в вызове функции CreateWindowEx . Вы также можете изменить меню окна после его создания с помощью функции SetMenu. Дополнительные сведения см. в разделе "Классы окон".

В следующих разделах рассматриваются действия системы, когда пользователь выбирает пункт меню, а также способы управления внешним видом и функциональностью элемента.

Командные элементы и элементы, открытые подменю

Когда пользователь выбирает элемент команды, система отправляет командное сообщение в окно, которое владеет меню. Если элемент команды находится в меню окна, система отправляет сообщение WM_SYSCOMMAND. В противном случае он отправляет сообщение WM_COMMAND.

Связан с каждым элементом меню, открывающим подменю, является дескриптором соответствующего подменю. Когда пользователь указывает на такой элемент, система открывает подменю. Командное сообщение не отправляется в окно владельца. Однако система отправляет WM_INITMENUPOPUP сообщение в окно владельца перед отображением подменю. Вы можете получить дескриптор в подменю, связанном с элементом, с помощью функции GetSubMenu или GetMenuItemInfo.

Строка меню обычно содержит имена меню, но также может содержать элементы команд. Подменю обычно содержит элементы команд, но они также могут содержать элементы, открытые вложенные подменю. Добавив такие элементы в подменю, вы можете вложить меню в любую глубину. Для предоставления визуального подсказки для пользователя система автоматически отображает небольшую стрелку справа от текста элемента меню, открывающего подменю.

Связанный с каждым элементом меню — это уникальное целое число, определенное приложением, которое называется идентификатором элемента меню. Когда пользователь выбирает элемент команды из меню, система отправляет идентификатор элемента в окно владельца в рамках сообщения WM_COMMAND. Процедура окна проверяет идентификатор для определения источника сообщения и обрабатывает сообщение соответствующим образом. Кроме того, можно указать элемент меню с помощью его идентификатора при вызове функций меню; Например, чтобы включить или отключить элемент меню.

Элементы меню, открытые подменю, имеют идентификаторы так же, как и элементы команд. Однако система не отправляет командное сообщение при выборе такого элемента в меню. Вместо этого система открывает подменю, связанную с элементом меню.

Чтобы получить идентификатор элемента меню в указанной позиции, используйте функцию GetMenuItemID или GetMenuItemInfo.

Помимо уникального идентификатора, каждый элемент меню в строке меню или меню имеет уникальное значение позиции. Самый левый элемент в строке меню или верхний элемент в меню имеет нулевое положение. Значение позиции увеличивается для последующих элементов меню. Система назначает значение позиции всем элементам в меню, включая разделители. На следующем рисунке показаны значения позиции элементов в строке меню и в меню.

menu bar and menu

При вызове функции меню, которая изменяет или извлекает сведения о определенном элементе меню, можно указать элемент с помощью идентификатора или его позиции. Для получения дополнительных сведений см. следующий раздел.

Доступ к элементам меню программным способом

Большинство функций меню позволяют указать пункт меню по позиции или по команде. Некоторые функции используют флаги MF_BYPOSITION и MF_BYCOMMAND для указания алгоритма поиска; другие имеют явный параметр fByPosition . Если указать элемент меню по позиции, номер элемента является отсчитываемым от нуля индексом в меню. Если указать пункт меню по командам, меню и его подменю будут искать элемент, идентификатор меню которого равен указанному номеру элемента. Если несколько элементов в иерархии меню совпадают с номером элемента, оно не указано, какое из них используется. Если в меню содержатся повторяющиеся идентификаторы меню, следует использовать операции меню на основе позиции, чтобы избежать этой неоднозначности.

Элементы меню по умолчанию

Подменю может содержать один элемент меню по умолчанию. Когда пользователь открывает подменю, дважды щелкнув его, система отправляет сообщение команды в окно владельца меню и закрывает меню, как если бы выбран элемент команды по умолчанию. Если элемент команды по умолчанию отсутствует, подменю остается открытым. Чтобы получить и задать элемент по умолчанию для подменю, используйте функции GetMenuDefaultItem и SetMenuDefaultItem.

Выбранные и очистить элементы меню

Элемент меню можно выбрать или очистить. Система отображает растровое изображение рядом с выбранными элементами меню, чтобы указать их выбранное состояние. Система не отображает растровое изображение рядом с очищаемыми элементами, если не указана определяемая приложением растровая карта. Можно выбрать только элементы меню в меню; Элементы в строке меню не могут быть выбраны.

Приложения обычно проверка или очищают элемент меню, чтобы указать, действует ли параметр. Например, предположим, что у приложения есть панель инструментов, которую пользователь может показать или скрыть с помощью команды панели инструментов в меню. Когда панель инструментов скрыта, элемент меню панели инструментов очищается. Когда пользователь выбирает команду, приложение проверка элемент меню и отображает панель инструментов.

Атрибут проверка пометки определяет, выбран ли элемент меню. Атрибут знака проверка элемента меню можно задать с помощью функции CheckMenuItem. Функцию GetMenuState можно использовать для определения того, выбран ли элемент меню в данный момент или снят.

Вместо CheckMenuItem и GetMenuState можно использовать функции GetMenuItemInfo и SetMenuItemInfo для получения и задания состояния проверка элемента меню.

Иногда группа элементов меню соответствует набору взаимоисключающих параметров. В этом случае можно указать выбранный параметр с помощью выбранного элемента меню радио (аналогично элементу управления переключателем). Выбранные элементы радио отображаются с растровым изображением маркера вместо проверка пометки растрового изображения. Чтобы проверка элемент меню и сделать его радиоэлементом, используйте функцию CheckMenuRadioItem.

По умолчанию в системе отображается проверка пометка или точечный рисунок маркера рядом с выбранными элементами меню и не отображается растровое изображение рядом с очищаемыми элементами меню. Однако вы можете использовать функцию SetMenuItemBitmaps для связывания выбранных и очищаемых в приложении растровых изображений с элементом меню. Затем система использует указанные растровые изображения, чтобы указать выбранное или снятое состояние элемента меню.

Определяемые приложением растровые изображения, связанные с элементом меню, должны иметь тот же размер, что и по умолчанию, проверка пометить растровое изображение, размеры которого могут отличаться в зависимости от разрешения экрана. Чтобы получить правильные измерения, используйте функцию GetSystemMetrics . Можно создать несколько ресурсов растрового изображения для разных разрешений экрана; при необходимости создайте один ресурс растрового изображения и масштабируйте его; или создайте растровое изображение во время выполнения и нарисуйте в нем изображение. Растровые изображения могут быть монохромными или цветными. Тем не менее, поскольку элементы меню перевернуты при выделении, внешний вид некоторых перевернутых растровых изображений цвета может оказаться нежелательным. Дополнительные сведения см. в разделе "Растровые карты".

Включенные, серые и отключенные элементы меню

Элемент меню может быть включен, серый или отключен. По умолчанию элемент меню включен. Когда пользователь выбирает включенный пункт меню, система отправляет командное сообщение в окно владельца или отображает соответствующий подменю в зависимости от типа элемента меню.

Если элементы меню недоступны пользователю, они должны быть серыми или отключены. Не удается выбрать серые и отключенные элементы меню. Отключенный элемент выглядит так же, как и включенный элемент. Когда пользователь щелкает отключенный элемент, элемент не выбран, и ничего не происходит. Отключенные элементы могут быть полезны, например, в руководстве, представляющее меню, которое выглядит активным, но не является.

Приложение серым цветом недоступного элемента меню, чтобы предоставить пользователю визуальный сигнал о том, что команда недоступна. Вы можете использовать серый элемент, если действие не подходит (например, команду "Печать" в меню "Файл" можно серым цветом, если у системы не установлен принтер).

Функция EnableMenuItem включает, серый или отключает элемент меню. Чтобы определить, включен ли элемент меню, серый или отключен, используйте функцию GetMenuItemInfo .

Вместо GetMenuItemInfo можно также использовать функцию GetMenuState, чтобы определить, включен ли элемент меню, серый или отключен.

Выделенные пункты меню

Система автоматически выделяет элементы меню в меню, так как пользователь выбирает их. Однако выделение можно явно добавить или удалить из имени меню в строке меню с помощью функции HiliteMenuItem. Эта функция не влияет на элементы меню в меню. Если HiliteMenuItem используется для выделения имени меню, однако имя будет выбрано только. Если пользователь нажимает клавишу ВВОД, выделенный элемент не выбран. Эта функция может оказаться полезной, например, в обучающем приложении, демонстрирующем использование меню.

Элементы меню "Нарисованный владельцем"

Приложение может полностью контролировать внешний вид элемента меню с помощью элемента, нарисованного владельцем. Элементы, нарисованные владельцем, требуют от приложения общей ответственности за рисование выбранных (выделенных), выбранных и очищенных состояний. Например, если приложение предоставило меню шрифта, оно может нарисовать каждый пункт меню с помощью соответствующего шрифта; Элемент для Романа будет нарисован с романом, элемент для курсивного будет вырисован в курсиве и т. д. Дополнительные сведения см. в разделе "Создание элементов меню с изображением владельца".

Система предоставляет специальный тип элемента меню, который называется разделителем, который отображается как горизонтальная линия. С помощью разделителя можно разделить меню на группы связанных элементов. Разделитель нельзя использовать в строке меню, и пользователь не может выбрать разделитель.

Если строка меню содержит больше имен меню, чем будет соответствовать одной строке, система упаковывает строку меню, автоматически разбивая ее на две или более строк. Вы можете вызвать разрыв строки в определенном элементе в строке меню, назначив флаг типа MFT_MENUBREAK элементу. Система помещает этот элемент и все последующие элементы в новую строку.

Если меню содержит больше элементов, чем будет соответствовать одному столбцу, меню будет усечено. Вы можете вызвать разрыв столбца в определенном элементе в меню, назначив флаг типа MFT_MENUBREAK элементу или используя параметр MENUBREAK в инструкции MENUITEM . Система помещает этот элемент и все последующие элементы в новый столбец. Флаг типа MFT_MENUBARBREAK имеет тот же эффект, за исключением того, что вертикальная линия отображается между новым столбцом и старым.

Если для назначения разрывов строк используются функции AppendMenu, InsertMenu или ModifyMenu, следует назначить флаги типов MF_MENUBREAK или MF_MENUBARBREAK.

Сообщения, используемые с меню

Действие, связанное с меню системы, отправляет сообщения в процедуру окна окна, владеющего меню. Система отправляет ряд сообщений, когда пользователь выбирает элементы в строке меню или нажимает правую кнопку мыши, чтобы отобразить контекстное меню.

Когда пользователь активирует элемент в строке меню, окно владельца сначала получает сообщение WM_SYSCOMMAND. Это сообщение содержит флаг, указывающий, активировал ли пользователь меню с помощью клавиатуры (SC_KEYMENU) или мыши (SC_MOUSEMENU). Дополнительные сведения см. в разделе "Доступ к меню клавиатуры".

Затем перед отображением любых меню система отправляет сообщение WM_INITMENU в процедуру окна, чтобы приложение могли изменять меню, прежде чем пользователь увидит их. Система отправляет сообщение WM_INITMENU только один раз для активации меню.

Когда пользователь указывает на элемент меню, открывающий подменю, система отправляет окно владельца WM_INITMENUPOPUP сообщение перед отображением подменю. Это сообщение дает приложению возможность изменять подменю перед отображением.

Каждый раз, когда пользователь перемещает выделение из одного элемента в другой, система отправляет WM_MENUSELECT сообщение в процедуру окна окна владельца меню. Это сообщение определяет выбранный в данный момент пункт меню. Многие приложения предоставляют информационную область в нижней части основных окон и используют это сообщение для отображения дополнительных сведений о выбранном элементе меню.

Когда пользователь выбирает элемент команды из меню, система отправляет WM_COMMAND сообщение в процедуру окна. Слово с низким порядком для параметра wParam сообщения WM_COMMAND содержит идентификатор выбранного элемента. Процедура окна должна проверять идентификатор и обрабатывать сообщение соответствующим образом.

Вы можете сохранить сведения для меню с помощью структуры MENUINFO . Если меню определено с помощью MENUINFO.Значение dwStyle MNS_NOTIFYBYPOS система отправляет WM_MENUCOMMAND вместо WM_COMMAND при выборе элемента. Это позволяет получить доступ к данным в структуре MENUINFO , а также предоставить индекс выбранного элемента напрямую.

Не все меню доступны через строку меню окна. Во многих приложениях отображаются контекстные меню, когда пользователь нажимает правую кнопку мыши в определенном расположении. Такие приложения должны обрабатывать сообщение WM_CONTEXTMENU и отображать контекстное меню при необходимости. Если приложение не отображает контекстное меню, оно должно передать сообщение WM_CONTEXTMENU функции DefWindowProc для обработки по умолчанию.

Сообщение WM_MENURBUTTONUP отправляется, когда пользователь освобождает правую кнопку мыши, пока курсор находится в элементе меню. Это сообщение предоставляется, чтобы приложения могли отображать контекстное или контекстное меню для элемента меню.

Существует несколько сообщений, которые включают только меню перетаскивания. WM_MENUGETOBJECT отправляется владельцу меню перетаскивания, когда курсор мыши вводит элемент меню или перемещается из центра элемента в верхнюю или нижнюю часть элемента. Сообщение WM_MENUDRAG отправляется, когда пользователь фактически перетаскивает элемент меню.

При уничтожении раскрывающегося меню или подменю система отправляет WM_UNINITMENUPOPUP сообщение.

Если меню назначено окну и это окно уничтожено, система автоматически уничтожает меню и ее подменю, освобождая дескриптор меню и память, занятую меню. Система не уничтожает меню, которое не назначено окну. Приложение должно уничтожить меню без знака, вызвав функцию DestroyMenu. В противном случае меню продолжает существовать в памяти даже после закрытия приложения. Чтобы завершить активное меню вызывающего потока, используйте EndMenu. Если платформа не поддерживает EndMenu, отправьте владельцу активного меню сообщение WM_CANCELMODE.