Я путаюсь.
MF_POPUP
0x00000010L
Указывает, что элемент меню открывает раскрывающееся меню или подменю.
uIDNewItem
параметр указывает дескриптор раскрывающегося меню или подменю. Этот флаг используется для добавления имени меню в строку меню или меню. элемент, который открывает подменю в раскрывающемся меню, подменю или ярлыке меню.
(https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-appendmenua)
Да, но как нам теперь указать uID Меню и обратиться к нему в WindowProcedure,
если параметр uIDNewItem
теперь является дескриптором раскрывающегося меню или подменю.
Вы не будете получать сообщения WM_COMMAND
для пункта меню MF_POPUP
, поэтому вам не нужно искать идентификатор. Однако вместо этого вы можете получать сообщения WM_MENUCOMMAND
и WM_MENUCHAR
, что даст вам HMENU
подменю.
Это простой пример кода, на который вы можете ссылаться,
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define EXIT_ID 1
#define SUB_ID 2
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message)
{
case WM_CREATE:
{
HMENU hMenubar = CreateMenu();
HMENU hFileMenu = CreateMenu(); //file is a regular menu.. Exit is a regular sub-menu..
HMENU hDisplayMenu = CreatePopupMenu(); //display is a popup-menu because it has children.
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hFileMenu, "File");
AppendMenu(hFileMenu, MF_STRING | MF_POPUP, (UINT_PTR)hDisplayMenu, "Display");
AppendMenu(hDisplayMenu, MF_STRING, SUB_ID, "Sub");
AppendMenu(hFileMenu, MF_STRING, EXIT_ID, "Exit");
SetMenu(hwnd, hMenubar);
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case SUB_ID:
MessageBox(hwnd, "You click Sub menu", " ", MB_OK);
break;
case EXIT_ID:
DestroyWindow(hwnd);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
};
HINSTANCE hinst;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
HWND hwnd;
hinst = GetModuleHandle(NULL);
// create a window class:
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hinst;
wc.lpszClassName = "win32";
// register class with operating system:
RegisterClass(&wc);
// create and show window:
hwnd = CreateWindow("win32", "My program", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 0, 1000, 800, NULL, NULL, hinst, NULL);
if (hwnd == NULL) {
return 0;
}
ShowWindow(hwnd, SW_SHOW);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Отлаживать:
EXIT_ID
и SUB_ID
— идентификатор подменю. Вам нужно определить их вручную.
#define EXIT_ID 1
#define SUB_ID 2
Обновлено:
Вы можете использовать WM_MENUSELECT, чтобы получить дескриптор меню, по которому щелкнули, и сравнить их меню.
Отправляется в окно владельца меню, когда пользователь выбирает пункт меню.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HMENU hMenubar;
switch (message)
{
case WM_CREATE:
{
hMenubar = CreateMenu();
HMENU hFileMenu = CreateMenu(); //file is a regular menu.. Exit is a regular sub-menu..
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hFileMenu, L"File");
SetMenu(hWnd, hMenubar);
}
break;
case WM_MENUSELECT:
{
HMENU hmenu = (HMENU)lParam;
if (hmenu == hMenubar)
{
MessageBox(hWnd, L"You click main menu", L" ", MB_OK);
}
}
break;
...
Так,
Вопрос в основном касается самого меню «Файл»: как мы можем обрабатывать и реагировать на нажатие кнопки меню «Файл», точно так же, как пункты меню и подменю в вашем примере.
@user3789797 user3789797 Извините, я неправильно понимаю, что вы имеете в виду. Как сказано в документе, если для параметра uFlags
установлено значение MF_POPUP
, дескриптор раскрывающегося меню или подменю. Другими словами, вы не можете установить UID отдельно в стиле MF_POPUP
. Я хочу знать, почему вам нужно отдельно обрабатывать нажатие кнопки FILE.
Это больше личное упражнение на последовательность в дизайне программирования win32. Чтобы иметь ответ под поясом, если когда-нибудь понадобится. Это действительно не здорово и не полезно иметь вопросы без ответов в затылке. Хотя это может помочь с некоторыми идеями в будущем, такими как лучшая поддержка Drag N Drop в некоторых приложениях или уникальный пользовательский интерфейс, который более очевиден. Обработка зависания и временного вспомогательного всплывающего окна - также может использоваться с этим видом обработки меню. Вкратце: множество применений, которые могут быть практичными и действительно полезными.
Всплывающее меню обрабатывается системой за вас. Ваша оконная процедура должна быть задействована. Когда пользователь выбирает пункт меню из всплывающего меню, оконная процедура получает соответствующее сообщение WM_COMMAND.