如何在Windows中的控制台应用程序中捕获系统菜单事件?

时间:2013-12-17 22:33:45

标签: c++ winapi console hook systemmenu

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

0 个答案:

没有答案