2011-01-27 3 views
6

DirectInputはキーボードとマウスの入力にはお勧めしません。そのため、SetWindowsHookExを使用してWndProcとGetMsgにフックする入力マネージャクラスを作成しました。フックはさまざまな問題の原因に見えますが、適切に設定されていると思います。Windowsが特定のメッセージを受信しないのはなぜですか?

私のWndProcまたはGetMsgフックは、実際のWndProcが受信しているメッセージのいずれも受信しません。私の入力マネージャーは、WM_INPUT、WM_ ボタン、WM_MOUSEWHEEL、およびWM_KEY *メッセージを受け取ることはありません。

何がありますか?

部分ヘッダ:

namespace InputManager 
{ 
    class CInputManager 
    { 
     HWND m_Window; 
     HHOOK m_WndProcHook; 
     HHOOK m_GetMessageHook; 
     static LRESULT CALLBACK WindowsProcedureHookProcedure(int Code, WPARAM WParameter, LPARAM LParameter); 
     static LRESULT CALLBACK GetMessageHookProcedure(int Code, WPARAM WParameter, LPARAM LParameter); 
     static LRESULT CALLBACK MessageHandler(HWND Window, UINT Message, WPARAM wParameter, LPARAM lParameter); 
    }; 
} 

部分源:それがためのスイッチであるほとんどが149本のラインで構成されたように、私はメッセージハンドラのコードを含んでいない

namespace InputManager 
{ 
    bool CInputManager::Initialize(HWND Window) 
    { 
     m_Window = Window; 

     // Hook into the sent messages of the target window to intercept input messages. 
     m_WndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, &(WindowsProcedureHookProcedure), NULL, GetCurrentThreadId()); 
     // Hook into the posted messages of the target window to intercept input messages. 
     m_GetMessageHook = SetWindowsHookEx(WH_GETMESSAGE, &(GetMessageHookProcedure), NULL, GetCurrentThreadId()); 

     // Register mouse device for raw input. 
     RAWINPUTDEVICE RawInputDevice; 
     RawInputDevice.usUsagePage = HID_USAGE_PAGE_GENERIC; 
     RawInputDevice.usUsage = HID_USAGE_GENERIC_MOUSE; 
     RawInputDevice.dwFlags = RIDEV_INPUTSINK; 
     RawInputDevice.hwndTarget = m_Window; 
     return RegisterRawInputDevices(&(RawInputDevice), 1, sizeof(RawInputDevice)); 
    } 

    void CInputManager::Shutdown() 
    { 
     // Unhook from the posted messages of the target window. 
     UnhookWindowsHookEx(m_GetMessageHook); 
     // Unhook from the sent messages of the target window. 
     UnhookWindowsHookEx(m_WndProcHook); 
    } 

    LRESULT CALLBACK CInputManager::WindowsProcedureHookProcedure(int nCode, WPARAM wParameter, LPARAM lParameter) 
    { 
     if(nCode == HC_ACTION) 
     { 
      // Forward to message handler. 
      CWPSTRUCT* Message = reinterpret_cast<CWPSTRUCT*>(lParameter); 
      MessageHandler(Message->hwnd, Message->message, Message->wParam, Message->lParam); 
     } 
     return CallNextHookEx(NULL, nCode, wParameter, lParameter); 
    } 

    LRESULT CALLBACK CInputManager::GetMessageHookProcedure(int nCode, WPARAM wParameter, LPARAM lParameter) 
    { 
     if(nCode == HC_ACTION) 
     { 
      // Forward to message handler. 
      CWPSTRUCT* Message = reinterpret_cast<CWPSTRUCT*>(lParameter); 
      MessageHandler(Message->hwnd, Message->message, Message->wParam, Message->lParam); 
     } 
     return CallNextHookEx(NULL, nCode, wParameter, lParameter); 
    } 
} 

メッセージタイプ。 WndProcで受け取ったメッセージの値は、コールバックのメッセージの値と同じではありません。

+0

ターゲットウィンドウは同じプロセス内にありますか? –

+0

はい、はいです。すべてが1つのバイナリに収められています。 –

答えて

4

私はここでパーティーにかなり遅れましたが、同じ問題を考え出すのに何時間も費やしました。うまくいけば、誰かがこれを役に立つと思うでしょう。

DispatchMessageがWH_CALLWNDPROCフックを起動しないという経験的結論です。つまり、というメッセージは、スレッドのメッセージキューにと投稿され、メッセージループ(GetMessage - > DispatchMessage)を通過すると、WH_CALLWNDPROCによって捕捉されません。それだけで..メッセージはSendMessage関数などでウィンドウプロシージャに直接を送っキャッチし、あなたがドキュメントを見ると、それはそれは言うちょっとです:

、アプリケーション定義またはライブラリ定義のコールバック関数を使用しますSetWindowsHookEx関数。メッセージは、をスレッドに送信するために、ウィンドウプロシージャを呼び出す前にこの関数を呼び出します。

もちろん、WH_GETMESSAGEフックでは逆です。投稿されたメッセージを捕捉しますが、送信されたメッセージは捕捉しませlParameterMSG*にキャストしなければならないので

WNDPROC realProc; 
LRESULT CALLBACK hookProc(HWND h, UINT msg, WPARAM wp, LPARAM lp) 
{ 
    return CallWindowProc(realProc, h, msg, wp, lp); 
} 
... 
realProc = (WNDPROC)SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)hookProc); 

はまた、OPの値getMessageフックが働いていなかった理由は、おそらくです:あなたは、両方のフックを使用する必要があり、または直接ウィンドウプロシージャをフックするためにサブクラス化を使用するか、すべてのメッセージを取得するにはCWPSTRUCT*ではありません。

+0

最終的にこの問題に戻って再試行しました。実際、「CWPSTRUCT *」が問題だったようです。 –

6

私はこれが、置くことを好むだろう場所で、あなたの元の質問の下にコメントを追加するように見えることはできません。考えないWH_KEYBOARDとWH_MOUSE、あなたがやろうとしているようにそれが見えるものから

をフックはより適切でしょうか?

+0

他の人の質問にコメントするには、50人の担当者が必要です。このコメントは実際には合理的に良い答えとなり、あなたの方法を担当者に伝えます。 –

+0

そうですが、LLバージョンを使用する必要があります。さらに、ユーザーがウィンドウを離れるとボタンを解放するために、ウィンドウモードで変更されたイベントをキャプチャする必要があります。これは有効な回避策かもしれませんが、私はまだメッセージを受け取っていない理由を理解できません。ドキュメンテーションは、入力メッセージを受け取っていない2つのフックに関する*何も*示唆していないようです。 –

+0

実際には、それらのフックでさえ、私の入力マネージャに不可欠な、どのウィンドウをターゲットにしているかを特定することができないので、私に何の役にも立たないでしょう... –

0

私はかつて同様の問題を抱えていました。 (PreTranslateMessageのどこかで消費されたが、私はshureではないと思う)しかし、私はそれを見つけた方法を知っている:

私はそれらのメッセージを自分自身で作成し、MFCを通してその方法をデバッグした。もし私が正しく記憶していれば、私はちょうど間違ったブーリアンのどこかに戻った。しかし、このアプローチはあなたに実際の手がかりを与えるかもしれません。

関連する問題