Panoramica dei hook
Un hook è un meccanismo per 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 procedura di hook. Una routine hook può agire su ogni evento ricevuto e quindi modificare o eliminare l'evento.
Nell'esempio seguente vengono usati per gli hook:
- Monitorare i messaggi per scopi di debug
- Fornire supporto per la registrazione e la riproduzione di macro
- Fornire supporto per una chiave della Guida (F1)
- Simulare l'input del mouse e della tastiera
- Implementare un'applicazione CBT (Computer-Based Training)
Nota
Gli hook tendono a rallentare il sistema perché aumentano la quantità di elaborazione che il sistema deve eseguire per ogni messaggio. È necessario 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 ganci; ogni tipo fornisce l'accesso a un aspetto diverso del meccanismo di gestione dei messaggi. Ad esempio, un'applicazione può usare l'WH_MOUSE hook per monitorare il traffico dei messaggi per i messaggi del mouse.
Il sistema gestisce una catena di gancio separata per ogni tipo di gancio. Una catena di hook è un elenco di puntatori a funzioni di callback speciali definite dall'applicazione denominate procedure di hook. Quando si verifica un messaggio associato a un particolare tipo di hook, il sistema passa il messaggio a ogni routine di hook a cui fa riferimento la catena di hook, una dopo l'altra. L'azione che può richiedere una procedura di hook dipende dal tipo di gancio coinvolto. Le procedure di hook per alcuni tipi di hook possono monitorare solo i messaggi; altri possono modificare i messaggi o arrestare lo stato di avanzamento attraverso la catena, impedendo loro di raggiungere la procedura di hook successiva o la finestra di destinazione.
Procedure di hook
Per sfruttare un particolare tipo di hook, lo sviluppatore fornisce una procedura di hook e usa la funzione SetWindowsHookEx per installarla nella catena associata all'hook. Una procedura di 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 di hook dipende dal tipo di gancio; ogni tipo ha un proprio set di caratteristiche di codici di hook. I valori dei parametri wParam e lParam dipendono dal codice di hook, ma in genere contengono informazioni su un messaggio inviato o pubblicato.
La funzione SetWindowsHookEx installa sempre una procedura di hook all'inizio di una catena di hook. Quando si verifica un evento monitorato da un particolare tipo di hook, il sistema chiama la procedura all'inizio della catena di hook associata al gancio. Ogni routine di hook nella catena determina se passare l'evento alla procedura successiva. Una routine di hook passa un evento alla procedura successiva chiamando la funzione CallNextHookEx .
Si noti che le procedure di hook per alcuni tipi di hook possono monitorare solo i messaggi. il sistema passa i messaggi a ogni routine di hook, indipendentemente dal fatto che una determinata routine chiami CallNextHookEx.
Un hook 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. Una procedura di hook globale può essere chiamata nel contesto di qualsiasi applicazione nello stesso desktop del thread chiamante, quindi la procedura deve essere in un modulo DLL separato. Una routine di hook specifica del thread viene chiamata solo nel contesto del thread associato. Se un'applicazione installa una routine di hook per uno dei propri thread, la procedura di hook può trovarsi nello stesso modulo del resto del codice dell'applicazione o in una DLL. Se l'applicazione installa una procedura di hook per un thread di un'applicazione diversa, la procedura deve trovarsi in una DLL. Per informazioni, vedere Librerie di collegamento dinamico.
Nota
È consigliabile usare i hook globali solo per scopi di debug; in caso contrario, è consigliabile evitarli. Gli hook globali fanno male alle prestazioni del sistema e causano conflitti con altre applicazioni che implementano lo stesso tipo di hook globale.
Tipi di hook
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
I WH_CALLWNDPROC e i WH_CALLWNDPROCRET hook consentono di monitorare i messaggi inviati alle procedure della finestra. Il sistema chiama una procedura di hook WH_CALLWNDPROC prima di passare il messaggio alla procedura di ricezione della finestra e chiama la procedura di collegamento WH_CALLWNDPROCRET dopo l'elaborazione della procedura di finestra.
Il WH_CALLWNDPROCRET hook passa un puntatore a una struttura CWPRETSTRUCT alla procedura di 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 altre informazioni, vedere le funzioni callWndProc e CallWndRetProc .
WH_CBT
Il sistema chiama una procedura di collegamento WH_CBT prima di attivare, creare, distruggere, ridurre al minimo, massimizzare, spostare o ridimensionare una finestra; prima di completare un comando di sistema; prima di rimuovere un evento del mouse o della tastiera dalla coda dei messaggi di sistema; prima di impostare lo stato attivo di input; o prima di sincronizzare con la coda dei messaggi di sistema. Il valore restituito dalla procedura di hook determina se il sistema consente o impedisce una di queste operazioni. Il WH_CBT hook è destinato principalmente alle applicazioni CBT (Computer-Based Training).
Per altre informazioni, vedere la funzione di callback CBTProc .
Per informazioni, vedere WinEvents.
WH_DEBUG
Il sistema chiama una procedura di hook WH_DEBUG prima di chiamare le procedure di hook associate a qualsiasi altro hook nel sistema. È possibile usare questo hook per determinare se consentire al sistema di chiamare le procedure di hook associate ad altri tipi di hook.
Per altre informazioni, vedere la funzione di callback DebugProc .
WH_FOREGROUNDIDLE
L'WH_FOREGROUNDIDLE hook consente di eseguire attività con priorità bassa durante i tempi in cui il thread in primo piano è inattiva. Il sistema chiama una procedura di collegamento WH_FOREGROUNDIDLE quando il thread in primo piano dell'applicazione sta per diventare inattiva.
Per altre informazioni, vedere la funzione callback ForegroundIdleProc .
WH_GETMESSAGE
Il WH_GETMESSAGE hook consente a un'applicazione di monitorare i messaggi da restituire dalla funzione GetMessage o PeekMessage . È possibile usare il WH_GETMESSAGE hook 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
Avviso
Le API di journaling Hooks non sono supportate a partire da Windows 11 e verranno rimosse in una versione futura. A causa di questo, è consigliabile chiamare invece l'API SendInput TextInput .
L'WH_JOURNALPLAYBACK hook 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 WH_JOURNALPLAYBACK hook. Un hook WH_JOURNALPLAYBACK è un hook globale, che non può essere usato come un hook specifico del thread.
Il WH_JOURNALPLAYBACK hook restituisce un valore di timeout. Questo valore indica al sistema quanti millisecondi attendere prima di elaborare il messaggio corrente dall'hook di riproduzione. In questo modo l'hook consente di controllare la tempistica degli eventi riprodotti.
Per altre informazioni, vedere la funzione callbackProc JournalPlaybackProc .
WH_JOURNALRECORD
Avviso
Le API di journaling Hooks non sono supportate a partire da Windows 11 e verranno rimosse in una versione futura. A causa di questo, è consigliabile chiamare invece l'API SendInput TextInput .
Il WH_JOURNALRECORD hook 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 un hook specifico del thread.
Per altre informazioni, vedere la funzione callback JournalRecordProc .
WH_KEYBOARD_LL
L'WH_KEYBOARD_LL hook consente di monitorare gli eventi di input della tastiera da pubblicare in una coda di input del thread.
Per altre informazioni, vedere la funzione callback LowLevelKeyboardProc .
WH_KEYBOARD
L'hook WH_KEYBOARD consente a un'applicazione di monitorare il traffico dei messaggi per WM_KEYDOWN e WM_KEYUP messaggi da restituire dalla funzione GetMessage o PeekMessage . È possibile usare l'WH_KEYBOARD hook per monitorare l'input della tastiera pubblicato in una coda di messaggi.
Per altre informazioni, vedere la funzione callback KeyboardProc .
WH_MOUSE_LL
L'WH_MOUSE_LL hook consente di monitorare gli eventi di input del mouse da pubblicare in una coda di input del thread.
Per altre informazioni, vedere la funzione callback LowLevelMouseProc .
WH_MOUSE
L'WH_MOUSE hook consente di monitorare i messaggi del mouse da restituire dalla funzione GetMessage o PeekMessage. È possibile usare l'WH_MOUSE hook per monitorare l'input del mouse pubblicato in una coda di messaggi.
Per altre informazioni, vedere la funzione callback MouseProc .
WH_MSGFILTER e WH_SYSMSGFILTER
I WH_MSGFILTER e i WH_SYSMSGFILTER hook 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 ALT+TAB o ALT+ESC. Il WH_MSGFILTER hook 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 di hook. L'WH_SYSMSGFILTER hook monitora tali messaggi per tutte le applicazioni.
I WH_MSGFILTER e WH_SYSMSGFILTER hook 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 principale tra il tempo in cui recupera il messaggio dalla coda e l'ora 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 una WH_MSGFILTER o WH_SYSMSGFILTER routine hook, il sistema chiama la procedura durante il ciclo modale.
Un'applicazione può chiamare direttamente l'WH_MSGFILTER hook 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 di 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 procedura di hook; è possibile immettere qualsiasi valore. La procedura di hook, definendo una costante come MSGF_MAINLOOP, può usare questo valore per determinare da dove è stata chiamata la procedura.
Per altre informazioni, vedere le funzioni di callback MessageProc e SysMsgProc .
WH_SHELL
Un'applicazione shell può usare l'hook WH_SHELL per ricevere notifiche importanti. Il sistema chiama una procedura di hook WH_SHELL quando l'applicazione shell sta per essere attivata e quando viene creata o eliminata una finestra di primo livello.
Si noti che le applicazioni della shell personalizzate non ricevono messaggi di WH_SHELL . Pertanto, qualsiasi applicazione che registra se stessa come shell predefinita deve chiamare la funzione SystemParametersInfo prima che sia (o qualsiasi altra applicazione) possa ricevere WH_SHELL messaggi. 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 .