在控制台应用程序(GetSystemMenu)上获取系统菜单并添加一些自己的条目(AppendMenu)很容易。但是这些菜单项对应用程序来说毫无用处。有什么方法可以进入消息流来识别单击了哪个菜单项?
我试图挂钩到控制台窗口,但没有任何结果,我的意思是 WH_SYSMSGFILTER,一切正常,但没有消息显示挂钩函数不是由系统运行。
接下来是ReadConsoleInput
这部分工作,即它在系统菜单上显示鼠标事件,但MENU_EVENT_RECORD
结构中没有关于单击哪个菜单项的信息。
这些都是我在一个片段中的尝试,这里控制台应该充斥着消息,但只出现来自 ReadConsoleInput 的那些,但这些不包含任何有用的信息。无论用户单击第一个还是第二个添加的菜单项,都只显示两个代码 278 (0x116) WM_INITMENU 和 287 (0x11F) WM_MENUSELECT,但我无法知道如何获取 WM_MENUSELECT 消息的 wParam。
#include <windows.h>
#include <stdio.h>
HHOOK sysMsgFilterHook;
LRESULT CALLBACK SysMsgFilterCallback(int nCode, WPARAM wParam, LPARAM lParam) {
printf("%i\n", nCode);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
static LRESULT CALLBACK consoleWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
printf("%u\n", uMsg);
WNDPROC origProc = (WNDPROC) GetProp(hWnd, "origProc");
return CallWindowProc(origProc, hWnd, uMsg, wParam, lParam );
}
int main() {
SetLastError(0);
HWND console_hwnd = GetConsoleWindow();
HMENU console_hMenu = GetSystemMenu(console_hwnd, FALSE);
HINSTANCE console_hinstance = (HINSTANCE)GetWindowLong(console_hwnd, GWL_HINSTANCE);
DWORD console_processid = GetWindowThreadProcessId(console_hwnd, NULL);
HANDLE console_input_handle = GetStdHandle(STD_INPUT_HANDLE);
AppendMenu(console_hMenu, MF_STRING | MF_CHECKED, NULL, "test menu item");
AppendMenu(console_hMenu, MF_STRING | MF_CHECKED, NULL, "yet another menu item");
WNDPROC origProc = (WNDPROC)SetWindowLongPtr(console_hwnd, GWL_WNDPROC, (LONG_PTR)&consoleWndProc);
SetProp(console_hwnd, "origProc", (HANDLE)origProc);
sysMsgFilterHook = SetWindowsHookEx(
WH_SYSMSGFILTER,
(HOOKPROC)SysMsgFilterCallback,
console_hinstance,
console_processid
);
DWORD numEvents = 0;
INPUT_RECORD input;
while(ReadConsoleInput(console_input_handle, &input, 1, &numEvents)) {
//printf("input.EventType: %i\n", input.EventType);
if (input.EventType == MENU_EVENT) {
printf("input.Event.MenuEvent.dwCommandId %i\n", input.Event.MenuEvent.dwCommandId);
}
}
//printf("GetLastError: %lu\n", GetLastError());
UnhookWindowsHookEx(sysMsgFilterHook);
system("pause");
return 0;
}
我已经成功地为鼠标事件创建了钩子,即 WH_MOUSE_LL。但所有其他钩子都不起作用。
我打算完成的是获取某种 WM_MENUCOMMAND 消息,然后使用 GetMenuItemInfo 休息。
我听说挂钩程序应该在另一个 dll 中,但怎么做呢?有任何工作片段吗?