4

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

4

0 回答 0