2011-09-18 3 views
11

Ho provato alcune cose con ganci, e non capisco il motivo per cui i ganci devono essere utilizzati con una coda di messaggiPerché deve SetWindowsHookEx essere utilizzato con una coda di messaggi di Windows

hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0); 
MSG msg; 
while(GetMessage(&msg, NULL, 0, 0) > 0) 
{ 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
} 
UnhookWindowsHookEx(hook); 

Perché non fa qualcosa come questo lavoro?

hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0); 
cin >> aKey; 
UnhookWindowsHookEx(hook); 

Utilizzo di thread di boost e una barriera non funziona. Perché l'attesa tra il gancio e lo sgancio non può essere fatta in un altro modo?

EDIT:

ho fatto un errore quando ho creato questo esempio, creo un gancio WH_KEYBOARD_LL, non WH_KEYBOARD, (io non credo che fa una grande differenza)

anche il ciclo non esegue attende solo la funzione GetMessage.

Il ciclo viene eseguito solo quando si invia il messaggio di uscita PostThreadMessage(id, WM_QUIT, 2323, NULL);, quindi non capisco cosa fa dopo l'attesa, c'è qualche elaborazione interna?

RELATIVA:

C++ SetWindowsHookEx WH_KEYBOARD_LL Correct Setup

How can I set up a CBT hook on a Win32 console window?

risposta

26

I ganci di basso livello, WH_KEYBOARD_LL e WH_MOUSE_LL sono diversi da tutti gli altri ganci. Non richiedono l'inserimento di una DLL nel processo di destinazione. Invece, Windows chiama direttamente il callback del gancio, all'interno del tuo processo. Per farlo funzionare, è richiesto un ciclo di messaggi. Non c'è nessun altro meccanismo per Windows per rendere i callback sul thread principale, il callback può verificarsi solo quando hai chiamato Get/PeekMessage() in modo che Windows abbia il controllo.

Un hook globale come WH_KEYBOARD è molto diverso. Richiede una DLL e il callback si verifica all'interno del processo che elabora il messaggio della tastiera. Hai bisogno di una sorta di comunicazione tra processi per far sì che il tuo programma sia consapevole di questo. Le pipe nominate sono la scelta abituale. Che altrimenti richiede ovviamente che questo processo iniettato pompi un ciclo di messaggi. Non riceverebbe altrimenti i messaggi della tastiera.

Favorire un hook di livello basso, sono molto più facile da ottenere.Ma pompa o non funzionerà. E fai attenzione ai timeout, se non sei abbastanza reattivo, Windows bloccherà il tuo hook senza preavviso.

Understanding the low-level mouse and keyboard hook (win32)

+0

Quindi, se ho capito bene, Windows può chiamare il mio callback solo in una chiamata Get/PeekMessage()? – Ha11owed

+2

Lo capisci correttamente. Non c'è altro modo per iniettare chiamate in sicurezza in un thread, deve essere inattivo. Questo è il motivo per cui esistono loop di messaggi. –

+0

@HansPassant per chiarire, stai suggerendo che per gli hook globali come WH_KEYBOARD named pipe possono essere usati per "passare" le informazioni al mio programma e quel programma non ha bisogno di un message pump? – dave

4

di Windows Ganci agganciare il ciclo di messaggi di Windows: http://msdn.microsoft.com/en-us/library/ms644959#wh_keyboardhook

Il gancio WH_KEYBOARD consente a un'applicazione per il monitoraggio sul traffico per WM_KEYDOWN e WM_KEYUP messaggi che devono essere restituiti dallo Funzione GetMessage o PeekMessage. È possibile utilizzare il gancio WH_KEYBOARD per monitorare l'input della tastiera inviato a una coda di messaggi.

Le applicazioni della console non pompano i messaggi autonomamente - il processo della console lo fa. Quindi non funzionerà a meno che il processo non abbia un ciclo di messaggi.

Vedi:

How can I set up a CBT hook on a Win32 console window?

C++ SetWindowsHookEx WH_KEYBOARD_LL Correct Setup

+0

Grazie per il link, sono andato attraverso tutti loro, ma io ancora non capiscono cosa GetMessage non accanto in attesa. Nel mio caso (applicazione console) l'unica volta che viene eseguita quando invio il messaggio di chiusura alla discussione. – Ha11owed

+0

Inoltre, poiché GetMessage è in attesa, non significa che la console non sta pompando alcun messaggio fino al mio messaggio di uscita? – Ha11owed

+0

Vedere la risposta di Han - Windows richiamerà il thread solo quando sa che è inattivo. E se il thread è bloccato in GetMesasge() Windows sa che non sta facendo nulla – shf301