Почему я не получаю сообщение 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 или делать с ним что угодно. Я попробовал это (делал что-то другое, чем это), и это работает.

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