7

Microsoftは、キーボードおよびマウス入力にDirectInputを推奨していません。そのため、SetWindowsHookExを使用してWndProcとGetMsgにフックする入力マネージャークラスを作成しました。フックはいろいろな問題の原因になっているようですが、適切に設定されていると思います。

私のWndProcフックもGetMsgフックも、実際のWndProcが受信しているメッセージを受信しません。入力マネージャーは、必要なWM_INPUT、WM_ BUTTON、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);
    };
}

部分的なソース:

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);
    }
}

メッセージハンドラーのコードは149行で構成されており、そのほとんどがメッセージタイプのスイッチであるため、ここには含めません。WndProcで受信したメッセージ値は、私のコールバックのメッセージ値と同じではありません。

4

3 に答える 3

6

私はあなたの元の質問の下にコメントを追加することができないようですが、それは私がこれを置きたい場所ですが:

あなたがやろうとしているように見えることから、WH_KEYBOARDとWH_MOUSEフックはより適切ではないでしょうか?

于 2011-01-27T21:59:03.867 に答える
5

私はここでのパーティーにかなり遅れていますが、同じ問題を理解するのに非常に多くの時間を費やしました。他の誰かがこれが役立つことを願っています。

私の経験的な結論は、DispatchMessageはWH_CALLWNDPROCフックをトリガーしないということです。つまり、スレッドのメッセージキューに投稿され、メッセージループ(GetMessage-> DispatchMessage)を通過するメッセージは、WH_CALLWNDPROCによってキャッチされません。SendMessageなどを使用してウィンドウプロシージャに直接送信されたメッセージのみをキャッチします。ドキュメントを見ると、次のようになっています。

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

そしてもちろん、WH_GETMESSAGEフックの場合は逆になります。投稿されたメッセージはキャッチしますが、送信されたメッセージはキャッチしません。すべてのメッセージを取得するには、両方のフックを使用するか、サブクラス化を使用してウィンドウプロシージャを直接フックする必要があります。

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フックが機能しなかった理由は、おそらくlParameterにキャストする必要があり、にキャストする必要がMSG*ないためCWPSTRUCT*です。

于 2011-06-19T15:59:43.660 に答える
0

私はかつて同様の問題を抱えていました。私はそれが何であったかを完全に理解していません(私はそれがPreTranslateMessageのどこかで消費されたと思いますが、私はそれを理解していません)が、私はそれをどのように見つけたか知っています:

私はそれらの消えるメッセージの1つを自分で作成し、MFCを介してその方法をデバッグしました。正しく覚えていれば、間違ったBOOLEANをどこかに返しました。ただし、このアプローチは実際の手がかりを与える可能性があります。

于 2011-03-24T21:16:54.877 に答える