Вернусь прямо к сути: пользовательский элемент меню, который я добавил в системное меню каждого окна через глобальные перехватчики Windows, не приводит к вызову GetMsgProc, когда пользователь щелкает по нему.
Вот как я добавляю пункты меню:
void HookCore::AppendTasksMenu(HWND windowHandle)
{
// make the popup menu and set up the appearance flags for the sub-items
m_mnuMoveToTasks = CreatePopupMenu();
UINT tasksAppearanceFlags = MF_STRING | MF_ENABLED;
//TODO: need to make proper iterator for MenuItemList
list<MenuItemInfo*>::iterator iter;
for (iter = m_menuItems->Begin(); iter != m_menuItems->End(); iter++)
{
// check if we are adding a separator
if ((*iter)->GetSpecial() == MenuItemInfo::SEPARATOR)
{
AppendMenu(m_mnuMoveToTasks, MF_SEPARATOR, (*iter)->GetItemId(), NULL);
}
else
{
AppendMenu(m_mnuMoveToTasks,
((*iter)->IsChecked() ? tasksAppearanceFlags | MF_CHECKED : tasksAppearanceFlags),
(*iter)->GetItemId(), (*iter)->GetItemName().c_str());
}
}
// get the system menu and set up the appearance flag for our new system sub-menu
HMENU mnuSystem = GetSystemMenu(windowHandle, FALSE);
UINT itemAppearanceFlags = MF_STRING | MF_ENABLED | MF_POPUP;
AppendMenu(mnuSystem, MF_SEPARATOR, ID_MOVE_TO_TASK_SEP, NULL);
// append the sub-menu we just created
AppendMenu(mnuSystem, itemAppearanceFlags, (UINT_PTR)m_mnuMoveToTasks, MOVE_TO_TASK);
}
Это создает новое подменю в системном меню, и подменю содержит мои дополнительные пункты.Идентификаторы элементов начинаются с 1001
и увеличиваются на 1 для каждого нового элемента.Элементы могут быть отмечены или не отмечены.
Когда пользователь щелкает один из моих элементов, я ожидаю получить сообщение WM_SYSCOMMAND
через GetMsgProc
, но оно никогда не вызывается.Однако GetMsgProc
вызывается несколько раз во время инициализации с другими сообщениями.Я вижу сообщение WM_SYSCOMMAND
в CallWndProcRetProc
, но оно не содержит правильный идентификатор элемента.Я ожидал получить идентификатор элемента из младшего слова wParam
(как указано здесь: [http://www.codeproject.com/KB/dialog/AOTop.aspx]),, но вместо этого он просто содержит SC_MOUSEMENU
.
Вот как я назначаю хук GetMsgProc:
myhookdata[GET_MSG_HOOK].nType = WH_GETMESSAGE;
myhookdata[GET_MSG_HOOK].hkprc = GetMsgProc;
myhookdata[GET_MSG_HOOK].hhook = SetWindowsHookEx(
myhookdata[GET_MSG_HOOK].nType,
myhookdata[GET_MSG_HOOK].hkprc,
AppHandle, 0);
Есть идеи? Неправильные ли идентификаторы моего предмета? Как правильно идентифицировать выбранный предмет?
Спасибо!
Обновление:
Исходя из предложенных ниже советов, я попытался перехватить сообщения WM_SYSCOMMAND и WM_COMMAND в CallWndProc, CallWndProcRetProc, GetMsgProc и SysMsgProc. Сообщение выбора элемента не доставлено.
Я также попытался создать подкласс для окна, к которому принадлежит меню, и мой WndProc так и не получил сообщение о выборе элемента, хотя были доставлены другие сообщения, такие как «WM_MENUSELECT» и «WM_UNINITMENUPOPUP».
Любые указатели, где ещепроверить?
Обновление 2:
Так что, когда я делаю подкласс / отменяю класс окна, я делаю это в своем хуке CallWndProc
. Я делаю подкласс, когда получаю WM_INITMENUPOPUP
сообщение, и я отменяю класскогда я получаю сообщение WM_MENUSELECT
для закрытия меню (когда lParam
равно NULL
и HIWORD(wParam)
равно 0xFFFF
).
Я нажимаю на системное меню (в этот момент WM_INITPOPUPMENU
поднимается), переместите курсор мыши в мое подменю, которое содержит пользовательские элементы, а затем нажмите на один из элементов.Я регистрирую каждое сообщение, которое я получаю в моем новом WndProc во время этого процесса.Вот список сообщений, которые я получаю в своем WndProc во время этого теста:
WM_INITMENUPOPUP
147 (0x0093) - what is this message?
148 (0x0094) [9 times] - what is this message?
WM_NCMOUSELEAVE
WM_ENTERIDLE [2 times]
WM_NOTIFY [2 times]
WM_ENTERIDLE [2 times]
WM_NOTIFY
WM_ENTERIDLE [11 times]
WM_MENUSELECT
WM_ENTERIDLE [5 times]
WM_MENUSELECT
WM_ENTERIDLE [6 times]
WM_MENUSELECT
WM_ENTERIDLE [7 times]
WM_MENUSELECT
WM_ENTERIDLE [8 times]
WM_NOTIFY
WM_ENTERIDLE [5 times]
WM_NOTIFY
WM_ENTERIDLE
WM_NOTIFY
WM_ENTERIDLE
WM_UNINITMENUPOPUP
WM_CAPTURECHANGED
Сообщение, которое я ожидаю увидеть, когда пользователь щелкает элемент, - WM_COMMAND
или WM_SYSCOMMAND
.У меня нет большого опыта работы с сообщениями Windows или работы с Windows API.Правильно ли искать одно из этих двух сообщений?Там нет ни одного сообщения, но оно должно быть, верно?Я что-то упускаю?