Panoramica degli hook
Un hook è un meccanismo in cui un'applicazione può intercettare eventi, ad esempio messaggi, azioni del mouse e sequenze di tasti. Una funzione che intercetta un particolare tipo di evento è nota come routine hook . Una routine hook può agire su ogni evento ricevuto e quindi modificare o eliminare l'evento.
Ecco alcuni esempi di utilizzo per i hooks:
- Monitorare i messaggi a scopo di debug
- Fornire supporto per la registrazione e la riproduzione di macro
- Fornire supporto per il tasto di aiuto (F1)
- Simulare l'input tramite mouse e tastiera
- Implementare un'applicazione di training basata su computer
Nota
Gli hook tendono a rallentare il sistema perché aumentano la quantità di elaborazione che il sistema deve eseguire per ogni messaggio. È consigliabile installare un hook solo quando necessario e rimuoverlo il prima possibile.
Questa sezione illustra quanto segue:
Catene di gancio
Il sistema supporta molti tipi diversi di hook; ogni tipo fornisce l'accesso a un aspetto diverso del meccanismo di gestione dei messaggi. Ad esempio, un'applicazione può usare l'hook WH_MOUSE per monitorare il traffico dei messaggi del mouse.
Il sistema mantiene una catena separata di ganci per ogni tipo di gancio. Un catena di hook è un elenco di puntatori a funzioni di callback speciali definite dall'applicazione denominate procedure hook. Quando si verifica un messaggio associato a un particolare tipo di hook, il sistema passa il messaggio a ogni routine hook a cui si fa riferimento nella catena di hook, uno dopo l'altro. L'azione che può essere eseguita da una procedura hook dipende dal tipo di hook coinvolto. Le procedure di aggancio per alcuni tipi di hook possono solo monitorare i messaggi; altri possono modificare i messaggi o interrompere il loro avanzamento lungo la catena, impedendo loro di raggiungere la procedura di aggancio successiva o la finestra di destinazione.
Procedure hook
Per sfruttare un particolare tipo di hook, lo sviluppatore fornisce una procedura hook e usa la funzionesetWindowsHookExper installarla nella catena associata all'hook. Una routine hook deve avere la sintassi seguente:
LRESULT CALLBACK HookProc(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
// process event
...
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
HookProc è un segnaposto per un nome definito dall'applicazione.
Il parametro nCode è un codice hook usato dalla routine hook per determinare l'azione da eseguire. Il valore del codice hook dipende dal tipo di hook; ogni tipo ha un proprio set di caratteristiche di codici hook. I valori dei parametri wParam e lParam dipendono dal codice hook, ma in genere contengono informazioni su un messaggio inviato o pubblicato.
La funzione SetWindowsHookEx installa sempre una routine hook all'inizio di una catena di hook. Quando si verifica un evento monitorato da un particolare tipo di hook, il sistema chiama la routine all'inizio della catena di hook associata all'hook. Ogni procedura hook nella catena determina se passare l'evento alla procedura successiva. Una routine hook passa un evento alla routine successiva chiamando la funzione CallNextHookEx.
Si noti che le procedure hook per alcuni tipi di hook possono monitorare solo i messaggi. il sistema passa messaggi a ogni routine hook, indipendentemente dal fatto che una determinata routine chiami CallNextHookEx.
Un gancio globale monitora i messaggi per tutti i thread nello stesso desktop del thread chiamante. Un hook specifico del thread monitora i messaggi solo per un singolo thread. È possibile chiamare una procedura hook globale nel contesto di qualsiasi applicazione nello stesso desktop del thread chiamante, quindi la procedura deve trovarsi in un modulo DLL separato. Una procedura hook specifica del thread viene chiamata solo nel contesto del thread associato. Se un'applicazione installa una procedura hook per uno dei propri thread, la procedura hook può trovarsi nello stesso modulo del resto del codice dell'applicazione o in una DLL. Se l'applicazione installa una procedura hook per un thread di un'applicazione diversa, la procedura deve trovarsi in una DLL. Per informazioni, vedere librerie Dynamic-Link.
Nota
È consigliabile usare hook globali solo a scopo di debug; in caso contrario, è consigliabile evitarli. Gli hook globali danneggiano le prestazioni del sistema e causano conflitti con altre applicazioni che implementano lo stesso tipo di hook globale.
Tipi di ganci
Ogni tipo di hook consente a un'applicazione di monitorare un aspetto diverso del meccanismo di gestione dei messaggi del sistema. Le sezioni seguenti descrivono gli hook disponibili.
- WH_CALLWNDPROC e WH_CALLWNDPROCRET
- WH_CBT
- WH_DEBUG
- WH_FOREGROUNDIDLE
- WH_GETMESSAGE
- WH_JOURNALPLAYBACK
- WH_JOURNALRECORD
- WH_KEYBOARD_LL
- WH_KEYBOARD
- WH_MOUSE_LL
- WH_MOUSE
- WH_MSGFILTER e WH_SYSMSGFILTER
- WH_SHELL
WH_CALLWNDPROC e WH_CALLWNDPROCRET
Gli hook WH_CALLWNDPROC e WH_CALLWNDPROCRET consentono di monitorare i messaggi inviati alle procedure della finestra. Il sistema chiama una routine hook WH_CALLWNDPROC prima di passare il messaggio alla routine della finestra ricevente e chiama la routine hook WH_CALLWNDPROCRET dopo che la routine finestra ha elaborato il messaggio.
L'hook WH_CALLWNDPROCRET passa un puntatore a una struttura CWPRETSTRUCT alla procedura hook. La struttura contiene il valore restituito dalla routine della finestra che ha elaborato il messaggio, nonché i parametri del messaggio associati al messaggio. La sottoclasse della finestra non funziona per i messaggi impostati tra processi.
Per ulteriori informazioni, vedere le funzioni di callback CallWndProc e CallWndRetProc.
WH_CBT
Il sistema chiama una procedura hook WH_CBT prima di attivare, creare, distruggere, minimizzare, massimizzare, spostare o ridimensionare una finestra; prima di completare un comando di sistema; prima di rimuovere un evento del mouse o della tastiera nella coda dei messaggi di sistema; prima di impostare il focus di input; o prima di sincronizzare con la coda dei messaggi di sistema. Il valore restituito dalla routine hook determina se il sistema consente o impedisce una di queste operazioni. L'hook WH_CBT è destinato principalmente alle applicazioni CBT (Computer-Based Training).
Per ulteriori informazioni, consultare la funzione di callback CBTProc.
Per informazioni, vedere WinEvents.
WH_DEBUG
Il sistema chiama una procedura hook WH_DEBUG prima di chiamare le procedure hook associate con qualsiasi altro hook nel sistema. È possibile usare questo hook per determinare se consentire al sistema di chiamare procedure di hook associate ad altri tipi di hook.
Per ulteriori informazioni, vedere la funzione di callback DebugProc.
WH_FOREGROUNDIDLE
L'hook WH_FOREGROUNDIDLE consente di eseguire attività con priorità bassa durante i periodi in cui il thread in primo piano è inattivo. Il sistema chiama una procedura hook WH_FOREGROUNDIDLE quando il thread in primo piano dell'applicazione sta per diventare inattivo.
Per ulteriori informazioni, vedere la funzione di callback ForegroundIdleProc.
WH_GETMESSAGE
L'hook WH_GETMESSAGE consente a un'applicazione di monitorare i messaggi che stanno per essere restituiti dalla funzione GetMessage o PeekMessage. È possibile usare l'hook WH_GETMESSAGE per monitorare l'input del mouse e della tastiera e altri messaggi pubblicati nella coda dei messaggi.
Per altre informazioni, vedere la funzione di callback GetMsgProc.
WH_JOURNALPLAYBACK
Avvertimento
Le API hook del journaling non sono supportate a partire da Windows 11 e verranno rimosse in una versione futura. Per questo motivo, è consigliabile chiamare invece l'API SendInput TextInput.
L'hook WH_JOURNALPLAYBACK consente a un'applicazione di inserire messaggi nella coda dei messaggi di sistema. È possibile usare questo hook per riprodurre una serie di eventi del mouse e della tastiera registrati in precedenza usando WH_JOURNALRECORD. L'input normale del mouse e della tastiera è disabilitato purché sia installato un hook WH_JOURNALPLAYBACK. Un hook WH_JOURNALPLAYBACK è un hook globale, che non può essere usato come hook specifico del thread.
L'hook WH_JOURNALPLAYBACK restituisce un valore di timeout. Questo valore indica al sistema quanti millisecondi attendere prima di processare il messaggio corrente dall'hook di riproduzione. Ciò consente all'hook di controllare la tempistica degli eventi riprodotti.
Per ulteriori informazioni, vedere la funzione di callback JournalPlaybackProc.
WH_JOURNALRECORD
Avvertimento
A partire da Windows 11, gli hook di journaling API non sono supportati e verranno rimossi in una versione futura. Per questo motivo, è consigliabile chiamare invece l'API SendInput TextInput.
L'hook WH_JOURNALRECORD consente di monitorare e registrare gli eventi di input. In genere, si usa questo hook per registrare una sequenza di eventi del mouse e della tastiera da riprodurre in un secondo momento usando WH_JOURNALPLAYBACK. L'hook WH_JOURNALRECORD è un hook globale, che non può essere usato come hook specifico del thread.
Per ulteriori informazioni, consultare la funzione di callback JournalRecordProc.
WH_KEYBOARD_LL
L'hook WH_KEYBOARD_LL consente di monitorare gli eventi di input della tastiera che stanno per essere inseriti nella coda di input di un thread.
Per ulteriori informazioni, vedere la funzione di callback LowLevelKeyboardProc.
WH_KEYBOARD
L'hook WH_KEYBOARD consente a un'applicazione di monitorare il traffico dei messaggi per i messaggi WM_KEYDOWN e WM_KEYUP che sta per essere restituiti dalla funzioneGetMessageo PeekMessage. È possibile usare l'hook WH_KEYBOARD per monitorare l'input della tastiera inviato a una coda di messaggi.
Per ulteriori informazioni, vedere la funzione di callback KeyboardProc.
WH_MOUSE_LL
L'hook WH_MOUSE_LL consente di monitorare gli eventi di input del mouse che stanno per essere pubblicati in una coda di input del thread.
Per ulteriori informazioni, vedere la funzione di callback LowLevelMouseProc.
WH_MOUSE
L'hook WH_MOUSE consente di monitorare i messaggi del mouse da restituire dalla funzione GetMessage o PeekMessage. È possibile usare l'hook WH_MOUSE per monitorare l'input del mouse inserito in una coda di messaggi.
Per ulteriori informazioni, vedere la funzione di callback MouseProc.
WH_MSGFILTER e WH_SYSMSGFILTER
Gli hook WH_MSGFILTER e WH_SYSMSGFILTER consentono di monitorare i messaggi da elaborare tramite un menu, una barra di scorrimento, una finestra di messaggio o una finestra di dialogo e per rilevare quando una finestra diversa sta per essere attivata in seguito alla pressione della combinazione di tasti ALT+TAB o ALT+ESC. L'hook WH_MSGFILTER può monitorare solo i messaggi passati a un menu, una barra di scorrimento, una finestra di messaggio o una finestra di dialogo creata dall'applicazione che ha installato la procedura hook. L'hook WH_SYSMSGFILTER monitora tali messaggi per tutte le applicazioni.
Gli hook WH_MSGFILTER e WH_SYSMSGFILTER consentono di eseguire il filtro dei messaggi durante i cicli modali equivalenti al filtro eseguito nel ciclo di messaggi principale. Ad esempio, un'applicazione esamina spesso un nuovo messaggio nel ciclo main tra il tempo in cui recupera il messaggio dalla coda e il momento in cui invia il messaggio, eseguendo un'elaborazione speciale in base alle esigenze. Tuttavia, durante un ciclo modale, il sistema recupera e invia messaggi senza consentire a un'applicazione di filtrare i messaggi nel ciclo di messaggi principale. Se un'applicazione installa un hook di tipo WH_MSGFILTER o WH_SYSMSGFILTER, il sistema chiama la procedura durante il ciclo modale.
Un'applicazione può chiamare direttamente l'hook WH_MSGFILTER chiamando la funzione CallMsgFilter. Usando questa funzione, l'applicazione può usare lo stesso codice per filtrare i messaggi durante i cicli modali usati nel ciclo di messaggi principale. A tale scopo, incapsulare le operazioni di filtro in una routine hook WH_MSGFILTER e chiamare CallMsgFilter tra le chiamate alle funzioni GetMessage e DispatchMessage.
while (GetMessage(&msg, (HWND) NULL, 0, 0))
{
if (!CallMsgFilter(&qmsg, 0))
DispatchMessage(&qmsg);
}
L'ultimo argomento di CallMsgFilter viene semplicemente passato alla routine hook; è possibile immettere qualsiasi valore. La routine hook, definendo una costante, ad esempio MSGF_MAINLOOP, può usare questo valore per determinare la posizione da cui è stata chiamata la routine.
Per altre informazioni, vedere le MessageProc e SysMsgProc funzioni di callback.
WH_SHELL
Un'applicazione shell può usare l'hook WH_SHELL per ricevere notifiche importanti. Il sistema chiama una procedura hook WH_SHELL quando l'applicazione shell sta per essere attivata e quando una finestra di primo livello viene creata o distrutta.
Si noti che le applicazioni shell personalizzate non ricevono messaggi WH_SHELL. Pertanto, qualsiasi applicazione che si registra come shell predefinita deve chiamare la funzione SystemParametersInfo prima che essa o qualsiasi altra applicazione possa ricevere messaggi WH_SHELL. Questa funzione deve essere chiamata con SPI_SETMINIMIZEDMETRICS e una struttura MINIMIZEDMETRICS. Impostare il membro iArrange di questa struttura su ARW_HIDE.
Per altre informazioni, vedere la funzione di callback ShellProc .