まず一番基本的なプロセス内でのフックであるローカルフックからやってみる。
基本的な処理フローはこんな感じ。
- SetWindowsHookExでフックプロシージャを登録
- フックプロシージャでフック処理
CallNextHookExで次のフックへ引き継ぎ - nhookWindowsHookExでフック解除
コードは以下のような感じ。
HHOOK hMyHook; /* CallNextHookExの第一引数にはフックのインスタンスを渡す NULLを渡してしまうと前のフックに戻ることができなくなってしまう。どこかのフックで誤作動してしまうかもしれない。 */ LRESULT CALLBACK MyHookProc(int nCode, WPARAM wParam, LPARAM lParam){ // nCodeがマイナスの場合は何もしないですぐに返す。そういう決まり。 if(nCode < 0){ return CallNextHookEx(hMyHook, nCode, wParam, lParam); } // any hook return CallNextHookEx(hMyHook, nCode, wParam, lParam); } bool BeginHook(){ hMyHook = SetWindowsHookEx( WH_KEYBOARD, // フックタイプ (HOOKPROC)MyHookProc, // フックプロシージャのアドレス NULL, // ローカルフックではNULL。システムフックではDLLのハンドル。 GetCurrentThreadId()); // フックされるスレッド if(hMyHook == NULL){ return false; } return true; } void EndHook(){ if(UnhookWindowsHookEx(hMyHook) == 0){ MessageBoxA(NULL, "Failed to delete hook!", "Error", MB_OK); } } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // ウィンドウの生成など BeginHook(); while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } EndHook(); return (int) msg.wParam; }
BeginHook()でフック開始。EndHook()でフック終了。その間のキーボードフックは設定したMyHookProc関数で処理している。SetWindowsHookExで設定しているWH_KEYBOARDとプロシージャを変えればマウスフックなども簡単そうだ。
参考
http://www.kab-studio.biz/Programing/Codian/DLL_Hook_SClass/07.html
http://www.kumei.ne.jp/c_lang/sdk2/sdk_160.htm