2011-01-27 72 views
6

Microsoft不建議將DirectInput用於鍵盤和鼠標輸入。因此,我寫了一個使用SetWindowsHookEx掛接到WndProc和GetMsg的輸入管理器類。我相信鉤子是適當設置的,儘管它們看起來是各種問題的原因。爲什麼Windows掛鉤不會收到某些消息?

我的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中接收到的消息值與回調中的消息值不同。

+0

目標窗口是否在同一個進程內? – 2011-01-27 17:51:24

+0

是的,是的。一切都在一個單一的二進制。 – 2011-01-27 17:54:31

回答

4

我在這裏參加派對的時間已經很晚了,但我花了很多時間弄清楚同樣的問題,希望別人會覺得這很有用。

我的實證結論是,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*

6

我不能似乎你原來的問題是,我寧願把這個但在添加註釋:

從它看起來像你正在嘗試做的,就不是一個WH_KEYBOARD和WH_MOUSE勾得更合適?

+0

您需要50位代表才能評論其他人的問題。這個評論實際上是一個相當好的答案,並會幫助你建立代表。 – 2011-01-27 22:44:26

0

我曾經有過類似的問題。我不太清楚它是什麼(我認爲它被PreTranslateMessage中的某處消耗,但我不舒服),但我知道我是如何發現它的:

我自己創建了一個消失的消息,並通過MFC進行了調試。如果我記得正確的話,我只是回到了錯誤的BOOLEAN的地方。但是,這種方法可能會給你實際的線索。

相關問題