SetWindowsHookEx(グローバルフック)でメッセージをすりかえることは可能でしょうか?

このQ&Aのポイント
  • SetWindowsHookExでグローバルフックしてメッセージをすりかえることはできるのか疑問です。
  • WH_CALLWNDPROCで受け取ったメッセージを書き換えるだけでは無理です。
  • WH_CALLWNDPROCのCallWndProcではメッセージを変更できるのか疑問です。
回答を見る
  • ベストアンサー

SetWindowsHookEx(グローバルフック)の質問

SetWindowsHookExでグローバルフックして メッセージをすりかえる事って可能でしょうか? 例えばWM_KEYDOWNが送られてきたら、それを無視して WM_CLOSEとかえるといった具合に。 試しにWH_CALLWNDPROCで受け取ったメッセージを 書き換えるだけでは無理でした(WindowsXp SP2) MSDNのWH_CALLWNDPROCRETの関数CallWndRetProcの説明で 「このフックプロシージャは、メッセージを調べることはできますが、変更することはできません。」 となっていました。 ということはWH_CALLWNDPROCのCallWndProcでは変更できるのかな?と思った次第です。 何か情報があれば宜しくお願いします。 (2000では不可だけど98だとできるとか?)

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>WH_GETMESSAGEがP「ポストしたメッセージ」 >WH_CALLWNDPROCがS「送出するメッセージ」 >WH_CALLWNDPROCRETがR「送出したメッセージの戻り値」 というか、対象のウィンドウプロシージャにおいて、 P:PostMessageで受け取ったメッセージ S:SendMessageで受け取ったメッセージ R:SendMessageの受け取ったときのプロシージャの戻り値 と考えたほうがわかりやすいかと。 #RがSendMessageのみなのは、呼び出し元がPostMessageのときは終了を待たないため。 >>Sendで送られるメッセージもすり替えはたい場合はウィンドウのサブクラス化でしょう。 >>ただし、DLLを対象のプロセスに突っ込む荒業が必要ですが。 >サブクラス化はdllも同じプロセスに属す必要があるんですね。 >この方法についてどこか参考になるサイト、あるいは書籍ってありますか? ここらへんかな? http://www.microsoft.com/japan/info/press/JPN_ViewMsPress.asp?Book_id=39&list_id=2 http://ruffnex.oc.to/kenji/text/api_hook/

sha-girl
質問者

お礼

ご回答ありがとうございます。 「Advanced Windows」は手元にあったりしますが、 これを機会によく目を通してみようと思います。 URLも大変参考になりました。

その他の回答 (1)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

用途が違いますね。 >例えばWM_KEYDOWNが送られてきたら、それを無視して 特に、WM_KEYDOWNのようにPostされるものはWH_GETMESSAGEで無視することは可能です。 ちなみにWH_CALLWNDPROCでは取得すらできません。 Sendで送られるメッセージもすり替えはたい場合はウィンドウのサブクラス化でしょう。 ただし、DLLを対象のプロセスに突っ込む荒業が必要ですが。

sha-girl
質問者

お礼

いつもご回答くださり有難うございます。 >ちなみにWH_CALLWNDPROCでは取得すらできません。 すみません。取得出来ませんね。理解不足でした。 ところでspy++でいう WH_GETMESSAGEがP「ポストしたメッセージ」 WH_CALLWNDPROCがS「送出するメッセージ」 WH_CALLWNDPROCRETがR「送出したメッセージの戻り値」 にあたるということになるのでしょうか? >Sendで送られるメッセージもすり替えはたい場合はウィンドウのサブクラス化でしょう。 >ただし、DLLを対象のプロセスに突っ込む荒業が必要ですが。 サブクラス化はdllも同じプロセスに属す必要があるんですね。 この方法についてどこか参考になるサイト、あるいは書籍ってありますか?

関連するQ&A

  • キーボードフックについて

    SetWindowsHookEx()で、WH_KEYBOARDを指定したときのフックプロシージャのwParam値は仮想キーコードとありますが、このフックプロシージャ内で、打った文字が英語の大文字か小文字であるかを区別して取得する方法はありますでしょうか?

  • マウスホイールをフックしたい

    かなり突っ込んだ質問かもしれませんが Win32API系の質問です。 マウスホイールをフックするコードを書いています。 フックはDLLが必要なグローバルフックではなく スレッドローカルなフックです。 具体的には 1.SetWindowsHookEx APIでWH_MOUSEタイプをフック 2.MouseProcフックプロシジャーでWM_MOUSEWHELLメッセージはフックできている。 ここまでは良いのですが ホイールの回転方向がわかりません。 MouseProcフックプロシジャーのlParamを MOUSEHOOKSTRUCT構造体へキャストしても dwExtraInfo追加情報には何も入っておらず (オールゼロでした。) 行き詰っています。 試しにフック後に PeekMessageも試みましたがダメでした。 諸事情でグローバルフックは使いたくなくて スレッドローカルなフックで解決したいのですが 良い方法は無いでしょうか? 試しにフックタイプを WH_CALLWNDPROC WH_GETMESSAGE とこれらも試してみましたがNGでした。 なお、WH_JOURNALRECORDフックは ユーザの操作でキャンセルされてしまうので あまり使いたくありません。 経験者の方、アドバイス頂けると助かります。 宜しく御願いします。

  • グローバルフック

    http://www.microsoft.com/japan/developer/library/jpwinpf/_win32_setwindowshookex.htm に フックタイプがスレッドとグローバルの両方をサポートしている場合、最初にスレッドフックが呼び出され、次にグローバルフックが呼び出されます。 と書いてありますが、WH_GETMESSAGEでフックしてWM_USERを発生させてみてもMessageProcは1回しか実行されていないようでした。 MessageProcが2回実行されるという解釈は間違っていますか?

  • キィーボードをフックしません、何故ですか???

    パソコンを現在人間が実際に操作中であるか否かを判定しながら進めるアプリを作っています 簡易的にキィーボードを操作していれば操作中と判断します(マウス操作も含めますが話を簡単にするため今はキィーだけとします) グローバルフックでKEY_DOWNをフックする為に以下のDLL(主要部分のみ)を作りました キィーが押されるとMW_KEYDOWN_DLLというメッセージをアプリに送ります EXPORT LRESULT CALLBACK HookProc( int nCode, WPARAM wParam, LPARAM lParam) { if(nCode == HC_ACTION) { CWPSTRUCT *pcwp = (CWPSTRUCT *)lParam; if(pcwp->message == WM_KEYDOWN) { SendMessage(g_hWnd, WM_KEYDOWN_DLL, pcwp->wParam, pcwp->lParam); ←(1) } } return (CallNextHookEx(g_hHook, nCode, wParam, lParam)); } MW_KEYDOWN_DLLメッセージを受けたアプリは操作中フラグを立てます(主要部分のみ) LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_KEYDOWN_DLL: ここで操作中フラグを立てます ←(2)  このフラグは一定時間後にタイマーが倒します break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return (0L); } 実行してみると(1)に来ません、当然(2)のフラグは立ちません WM_KEYDOWNの代わりにWM_CREATE、WM_CLOSEだときちんとフックします WM_CHAR、MW_KEYUPなどのキィーボード系のメッセージだとフックしません なぜでしょうか??? 多分きわめて初歩的な知識の欠如によるものでしょうが分かりません 宜しくご指導願います

  • グローバルフック?にならない(SetWindowsHookEx:WH_CALLWNDPROC)

    とあるアプリケーションがアクティブウィンドウである場合、 とあるキーを抑制するアプリを作っているのですが、 とあるキーを抑制するのは低レベルキーフック用のDLLを用意して実現しました。 とあるアプリケーションがアクティブウィンドウである場合は、 500msのタイマで監視していたのですが、かっこわるいので ウィンドウイベントをフックしてWM_ACTIVATEあたりを拾って 拾ったときのウィンドウハンドルがとあるアプリケーションのウィンドウか否かで 判断しようかなんて思ったのです。 で、本題です。 SetWindowsHookEx(WH_CALLWNDPROC, &HookProc, g_hInst, NULL); と、実行しているのですが、自分のウィンドウと、IMEとか、 合計3~4種のウィンドウのイベントしか拾えません。 電卓を起動しても電卓のイベントが何も拾えなかったり。 デバッグだからだめなのかと思い、ログファイルに吐かせた結果 こういった状況です。 ロギングしたイベントは特にマスクせずに、コールバックが呼ばれ、 HC_ACTIONであった場合に全て書き出してみました。 そこで質問です。 SetWindowsHookEx(WH_CALLWNDPROC~ では、デスクトップ上の全てのウィンドウのイベントを覗き見できる 訳ではないのでしょうか? それとも、やり方がわるいのでしょうか? 宜しくお願いします。 #SetWindowsHookExの取り扱いについてはMSDN上で確認できる #部分についてはわかっているつもりです。

  • WM_INITDIALOGのフック

    どこにも載っていないため質問させていただきます。 次のようなコードを書いたとき、ダイアログの出現の検知ができるWM_INITDIALOGを検知できないのはなぜでしょうか。 hHookForDialog = SetWindowsHookEx(WH_CALLWNDPROCRET, CallWndRetProcForDialog, hDll, 0); LRESULT CALLBACK CallWndRetProcForDialog(int nCode, WPARAM wp, LPARAM lp) { if(nCode < 0) return CallNextHookEx(hHookForDialog, nCode, wp, lp); PCWPRETSTRUCT Wmes = (PCWPRETSTRUCT)lp; if(nCode == HC_ACTION) { if(Wmes->message == WM_INITDIALOG) { PostMessage(hWndToSendMessage, mesDialogCreated, (WPARAM)(Wmes->hwnd), NULL); } } return CallNextHookEx(hHookForDialog, nCode, wp, lp); } フック自体は成功しているようで、条件文を外すとメッセージはたくさん飛んできます。 けれども目的のWM_INITDIALOGは無いようです。 どうすればいいのかご教授お願いします。

  • VC++&グローバルフックについて質問です

    vc++2008,Windows Vistaの環境でプログラムを作成しています。 以下、aが押されたら、設定したhWndにWM_KEYDOWN,VK_LEFTのメッセージを送るプログラムのつもりで書きました。 http://www.shos.info/develop/cwin/tipswin.html#windows008 を参考にしています。 しかし、dllにしてWinMainで呼び出したのですが動作しません。 エラーも出ないのでなぜ動かないのかがわかりません。 このプログラムをちゃんと動かすにはどうしたらいいでしょうか。 どうかご指摘ください。よろしくお願いします。 //hook.h #ifdef HOOKAPI #else #define HOOKAPI extern "C" __declspec(dllimport) #endif HOOKAPI HINSTANCE _hInstance; HOOKAPI HHOOK _hHook; HOOKAPI HWND _hWnd; HOOKAPI BOOL Set(HWND hWnd); HOOKAPI void Reset(); //hook.cpp #include <windows.h> #define HOOKAPI extern "C" __declspec(dllexport) #include "hook.h" #pragma data_seg(".share") HHOOK _hHook = NULL; HWND _hWnd = NULL; HINSTANCE _hInstance; #pragma data_seg() #pragma comment(linker, "/section:.share,rws") LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) { /* ここでは 'A' が押されたら予め設定済みの _hWnd にメッセージを送る */ if (nCode >= 0 && nCode != HC_NOREMOVE && wParam == 'A') { PostMessage(_hWnd, WM_KEYDOWN, VK_LEFT, 0); CallNextHookEx(_hHook, nCode, wParam, lParam); return 1; } return CallNextHookEx(_hHook, nCode, wParam, lParam); } BOOL Set(HWND hWnd) { /* キーのフック */ _hHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)HookProc, _hInstance, 0); /* ここで hInstance は DLL のインスタンス ハンドル */ _hWnd = hWnd; return (_hHook != NULL); } void Reset() { if (_hHook != NULL) { UnhookWindowsHookEx(_hHook); _hHook = NULL; } }

  • APIのメッセージループの流れとTranslateMessage

    while(GetMessage(&msg, NULL, 0, 0) > 0){ TranslateMessage(&msg); DispatchMessage(&msg); } もしも「a」が押されたときは、 GetMessageで受け取って TranslateMessageでWM_CHARに変換され DispatchMessageでWM_CHARとしてのメッセージが送られる という流れになるはずです。 けど、実際には一度プロシージャにWM_KEYDOWNが送られます。 TranslateMessageが先にメッセージを変換してるので、WM_KEYDOWNが送られることはありえないと思うのですが、なぜでしょうか。 何か重大な思い違いをしているのでしょうか・・?

  • フック関数を使って情報流出防止

    例えばあるファイルやデータが送信される際に、どのファイルが送信されようとしているかを表示させ警告を出して、そこで通信を止めるプログラムを作ろうと思っています。これをうまく使えば、望まない情報流出を防ぐことが出来るものになります。 ですが、実際にプログラムにはどのように書いたらいいのかよくわかりません。vc++を使って開発しようとしているのですが、まだ使い初めでよく分かっていません。フック関数を使うことまでは分かったのですが、具体的にどのようにやったら良いのか分かりません。 http://ruffnex.oc.to/kenji/text/api_hook/ のサイトを参考にしています。SetWindowsHookExを使いopen関数をフックしたらどうか?という意見をもらったのですが、よく仕組みが分かっていません。データを送信するときは、いったん何かのファイルを開いて書き込んでから送信されるものなんでしょうか? この↑サイトのサンプルを参考にして作り上げることは可能でしょうか?また具体的にどのようにやったら出来るかお分かりの方いましたら教えて下さい。 まだプログラム初心者なもので、よく分かっていないことだらけで申し訳ありません。ちなみに開発環境はvc++2003、windowsXPです。

  • グローバルフック(SetWindowsHookEx)でのEM_REPLACESELの取得について

    はじめまして。 グローバルフック(SetWindowsHookEx)を使って別アプリ(exe)がEDITボックスに出力している 文字列を取得しようとしています。 SPY++で確認すると別アプリではEM_REPLACESELを用いていることがわかりました。 フックするDLLを以下のように作成しメッセージをフックすることはできました。 1. フックのセット   SetWindowsHookEx(WH_CALLWNDPROC, MyHookProc, hInst, dwThreadId);      // hInst はDllMainでアタッチ時に保存したもの      // dwThreadIdは別アプリのスレッドID(以下の方法で取得)      // HWND pWnd = ::FindWindow(NULL, 別アプリのフォームのキャプション) ;      // HWND pEdt = ::FindWindowEx(pWnd,0,"Edit",0);      // DWORD dwThreadId= ::GetWindowThreadProcessId(pEdt, NULL); 2. コールバック   LRESULT CALLBACK MyHookProc(int nCode, WPARAM wp, LPARAM lp)   {    if( EM_REPLACESELの判定 ){      メッセージの保存処理     }     return CallNextHookEx(hMyHook, nCode, wp, lp);   } 上記のコールバックの中で”EM_REPLACESELの判定”をどのようにしたら良いかわからずに困っています。 if分をはずしてファイルにダンプすると何かメッセージが取得できているのは確認できています。 他のサイトを見て、 MSG* pMSG = (MSG*)lp; として、pMSG->lParam を参照してもEM_REPLACESELになっているメッセージがありませんでした。 何か思いつくことがある方、根本的な間違いがあるという方、 アドバイアスをお願いします。

専門家に質問してみよう