Почему хуки Windows не получают определенные сообщения? - PullRequest
6 голосов
/ 27 января 2011

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, не совпадают со значениями в моих обратных вызовах.

Ответы [ 3 ]

6 голосов
/ 28 января 2011

Кажется, я не могу добавить комментарий к вашему первоначальному вопросу, куда я бы предпочел поставить это, но:

Из того, что вы пытаетесь сделать, не будет WH_KEYBOARDХук WH_MOUSE будет более подходящим?

4 голосов
/ 19 июня 2011

Я опаздываю на вечеринку здесь, но я потратил так много часов, чтобы понять ту же проблему, и, надеюсь, кто-то найдет это полезным.

Мой эмпирический вывод заключается в том, что 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);

Кроме того, причина, по которой хук GetMessage OP не работал, вероятно, в том, что lParameter должен быть приведен к MSG*, а не CWPSTRUCT*.

0 голосов
/ 25 марта 2011

У меня когда-то была похожая проблема.Я не совсем уверен, что это было (я думаю, что оно использовалось где-то в PreTranslateMessage, но я не уверен), но я знаю, как я его заметил:

Я создал одно из этих исчезающих сообщений сам и отладил егоMFC.Если я правильно помню, я просто возвратил куда-то не тот БУЛ.Однако этот подход может дать вам реальную подсказку.

...