2011-01-27 12 views
6

Microsoft non consiglia DirectInput per l'input da tastiera e mouse. Come tale, ho scritto una classe manager di input che usa SetWindowsHookEx per collegarsi a WndProc e GetMsg. Credo che i ganci siano impostati in modo appropriato, anche se sembrano essere la causa di vari problemi.Perché gli hook di Windows non riceveranno determinati messaggi?

Né i miei hook WndProc né GetMsg ricevono alcun messaggio ricevuto dal WndProc effettivo. Il mio gestore di input non riceve mai i messaggi WM_INPUT, WM_ BUTTON, WM_MOUSEWHEEL e WM_KEY * di cui ha bisogno.

Cosa dà?

intestazione parziale:

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

fonte parziale:

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

non includere il codice per il gestore di messaggio come si compone di 149 linee, la maggior parte dei quali sono gli interruttori per la tipi di messaggio. I valori dei messaggi ricevuti nel WndProc non sono uguali a quelli dei miei callback.

+0

La finestra di destinazione è all'interno della stessa procedura? –

+0

Sì, sì, lo è. Tutto è in un singolo binario. –

risposta

4

Sono in ritardo per la festa qui, ma ho passato così tante ore a capire lo stesso problema, e spero che qualcun altro lo troverà utile.

La mia conclusione empirica è che DispatchMessage non attiva gli hook WH_CALLWNDPROC. In altre parole, i messaggi che sono inviati nella coda dei messaggi del thread e passano attraverso il loop dei messaggi (GetMessage -> DispatchMessage) non verranno rilevati da WH_CALLWNDPROC. Raggiunge solo i messaggi inviati direttamente alla procedura di finestra con SendMessage ecc .. E quando si guarda la documentazione, che è un pò quello che dice:

Un'applicazione definita o una funzione di callback libreria definita utilizzato con il Funzione SetWindowsHookEx. Il sistema chiama questa funzione prima di chiamare la procedura della finestra per elaborare un messaggio inviato alla discussione.

E ovviamente il contrario è vero per WH_GETMESSAGE hook. Cattura i messaggi inviati ma non i messaggi inviati. Per ottenere tutti i messaggi che sia necessario utilizzare entrambi i ganci, o utilizzare sottoclasse di agganciare la procedura di finestra direttamente:

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

Inoltre, il motivo gancio GetMessage del PO non funzionava è probabilmente perché lParameter dovrebbe essere colato a MSG* e non CWPSTRUCT*.

+0

Eventualmente restituito a questo problema e provato di nuovo. In effetti, sembra che il 'CWPSTRUCT *' sia stato il problema. –

6

Non riesco ad aggiungere un commento sotto la vostra domanda originale, che è dove io preferirei mettere questo ma:

Da quello che sembra che si sta cercando di fare, non sarebbe un WH_KEYBOARD e WH_MOUSE gancio essere più appropriato?

+0

Hai bisogno di 50 rappresentanti per poter commentare le domande di altre persone. Questo commento in realtà fornisce una risposta ragionevolmente buona, e ti porterà a costruire un rappresentante. –

+0

Sì, sarebbe il caso, ma avrei bisogno di usare le versioni LL. Inoltre, ho bisogno di catturare gli eventi modificati in modalità finestra per rilasciare i pulsanti se l'utente lascia la finestra. Questo può essere un lavoro valido, ma continuo a non capire perché non sto ricevendo i messaggi. La documentazione non sembra suggerire * qualcosa * su quei due ganci che non ricevono messaggi di input. –

+0

In realtà, anche quegli hook non mi faranno del bene, dato che non hanno alcuna forma di identificazione della finestra verso cui sono indirizzati, che è parte integrante del mio gestore di input ... –

0

Una volta ho avuto un problema simile. Non sono abbastanza sicuro di quello che è stato (penso che sia stato consumato da qualche parte in PreTranslateMessage ma non sono sicuro) ma so come ho individuato:

Ho creato uno di quei messaggi di fuga e ho eseguito il debug con MFC. Se ricordo correttamente, sono tornato da qualche parte nel BOOLEAN sbagliato. Tuttavia, questo approccio potrebbe darti l'indizio reale.