Почему я не получаю сообщение WM_MENUCHAR?
Я реализовал IContextMenu3
интерфейс, и я пытаюсь захватить нажатия клавиш для моего собственного ускорителя. Проблема в том, что если я наведусь на мое подменю в корневом меню, я не получу WM_MENUCHAR
сообщения, тогда как, если я наведите курсор на подменю, которое находится внутри одного из моих подменю, то я делаю.
Я знаю что WM_INITMENUPOPUP
сообщение отправляется только если есть ребенок. WM_MENUCHAR
имеет оговорку, что никакие ускорители не связаны с ключом. Я знаю, что это предостережение должно соблюдаться, так как, когда я нажимаю клавишу, я получаю отчетливый звуковой сигнал "без ускорителя".
Есть ли еще одна оговорка, о которой я не знаю?
Это самый маленький код, который я могу получить, который воспроизводит проблему:
HRESULT CFolderViewImplContextMenu::QueryContextMenu(HMENU hmenu, UINT uMenuIndex, UINT idCmdFirst, UINT idCmdLast, UINT /* uFlags */)
{
UINT uID = idCmdFirst;
HMENU hSubmenu = CreatePopupMenu();
MENUITEMINFO mii = { 0 };
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_SUBMENU | MIIM_ID | MIIM_STRING;
mii.dwTypeData = str_toWchar("test");
mii.wID = uID++;
mii.hSubMenu = hSubmenu;
InsertMenuItem ( hmenu, 0, TRUE, &mii );
InsertMenu ( hSubmenu, 0, MF_BYPOSITION, uID++, L"&Notepad" );
InsertMenu ( hSubmenu, 1, MF_BYPOSITION , uID++, L"&Internet Explorer" );
HMENU hSubmenu2 = CreatePopupMenu();
MENUITEMINFO mii2 = {0};
mii2.cbSize = sizeof(MENUITEMINFO);
mii2.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
mii2.fType = MFT_OWNERDRAW;
mii2.wID = uID++;
mii2.hSubMenu = hSubmenu2;
InsertMenuItem ( hSubmenu, 0, TRUE, &mii2 );
InsertMenuA ( hSubmenu2, 0, MF_BYPOSITION, uID++, "");
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, uID - idCmdFirst );
}
3 ответа
Проблема - первый пункт в подменю. Если первый элемент в подменю также является подменю, то сообщение не будет передано. Поэтому я вместо этого положил туда обычный предмет.
WM_MENUCHAR
пересылается только для подменю. (Он не может быть перенаправлен для пунктов меню верхнего уровня, потому что это будет Catch-22. Вы хотите перенаправить его в обработчик контекстного меню для пункта меню, которому соответствует клавиша, но вы не можете этого сделать пока у вас нет ответа на WM_MENUCHAR
!)
Как насчет этого: если вы обрабатываете сообщения IContextMenu3, следовательно, WM_DRAWITEM, вы можете использовать WindowFromDC(), чтобы получить HWND окна меню из WM_DRAWITEM, затем создать его подкласс и поймать WM_KEYDOWN или делать с ним что угодно. Я попробовал это (делал что-то другое, чем это), и это работает.