在控制台应用程序(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中,但怎么办呢?有没有工作片段?