4

コンソール アプリケーションでシステム メニューを取得し (GetSystemMenu)、独自のエントリを追加する (AppendMenu) のは簡単です。しかし、これらのメニュー項目はアプリには役に立ちません。どのメニュー項目がクリックされたかを識別するメッセージ ストリームに入る方法はありますか?

コンソール ウィンドウにフックしようとしましたが、結果はありません。WH_SYSMSGFILTER を意味します。すべて正常にコンパイルされていますが、フック関数がシステムによって実行されていないことを示すメッセージはありません。

次に、これは部分的に機能します。つまり、システム メニューにマウス イベントが表示されますが、クリックされたメニュー項目に関するReadConsoleInput情報が構造にありません。MENU_EVENT_RECORD

これらはすべて 1 つのスニペットでの私の試みです。ここでは、コンソールにメッセージが殺到する必要がありますが、ReadConsoleInput からのメッセージのみが表示されますが、これらには有用な情報は含まれていません。ユーザーが最初または 2 番目に追加されたメニュー項目をクリックしても、278 (0x116) WM_INITMENU と 287 (0x11F) WM_MENUSELECT の 2 つのコードしか表示されませんが、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