Vue d’ensemble des hooks

Un hook est un mécanisme par lequel une application peut intercepter des événements, tels que des messages, des actions de souris et des frappes. Une fonction qui intercepte un type particulier d’événement est appelée procédure de hook. Une procédure de hook peut agir sur chaque événement qu’elle reçoit, puis modifier ou ignorer l’événement.

Voici quelques exemples d’utilisations pour les crochets :

  • Surveiller les messages à des fins de débogage
  • Assurer la prise en charge de l’enregistrement et de la lecture des macros
  • Fournir une prise en charge d’une clé d’aide (F1)
  • Simuler l’entrée de la souris et du clavier
  • Implémenter une application de formation basée sur ordinateur (CBT)

Notes

Les crochets ont tendance à ralentir le système, car ils augmentent la quantité de traitement que le système doit effectuer pour chaque message. Vous devez installer un crochet uniquement si nécessaire et le supprimer dès que possible.

 

Cette section décrit les éléments suivants :

Chaînes de crochets

Le système prend en charge de nombreux types de crochets différents ; chaque type fournit l’accès à un aspect différent de son mécanisme de gestion des messages. Par exemple, une application peut utiliser le crochet WH_MOUSE pour surveiller le trafic de messages pour les messages de souris.

Le système gère une chaîne de crochet distincte pour chaque type de crochet. Une chaîne de hook est une liste de pointeurs vers des fonctions de rappel spéciales définies par l’application appelées procédures de hook. Lorsqu’un message associé à un type particulier de hook se produit, le système transmet le message à chaque procédure de crochet référencée dans la chaîne de crochet, l’une après l’autre. L’action qu’une procédure de crochet peut effectuer dépend du type de crochet impliqué. Les procédures de hook pour certains types de hooks ne peuvent surveiller que les messages ; d’autres peuvent modifier les messages ou arrêter leur progression dans la chaîne, ce qui les empêche d’atteindre la procédure de hook suivante ou la fenêtre de destination.

Procédures de hook

Pour tirer parti d’un type particulier de hook, le développeur fournit une procédure de hook et utilise la fonction SetWindowsHookEx pour l’installer dans la chaîne associée au crochet. Une procédure de hook doit avoir la syntaxe suivante :

LRESULT CALLBACK HookProc(
  int nCode, 
  WPARAM wParam, 
  LPARAM lParam
)
{
   // process event
   ...

   return CallNextHookEx(NULL, nCode, wParam, lParam);
}

HookProc est un espace réservé pour un nom défini par l’application.

Le paramètre nCode est un code de hook que la procédure de hook utilise pour déterminer l’action à effectuer. La valeur du code de hook dépend du type du hook ; chaque type a son propre ensemble caractéristique de codes de crochet. Les valeurs des paramètres wParam et lParam dépendent du code de hook, mais elles contiennent généralement des informations sur un message qui a été envoyé ou publié.

La fonction SetWindowsHookEx installe toujours une procédure de crochet au début d’une chaîne de crochet. Lorsqu’un événement qui est surveillé par un type particulier de hook se produit, le système appelle la procédure au début de la chaîne de crochet associée au crochet. Chaque procédure de hook dans la chaîne détermine s’il faut passer l’événement à la procédure suivante. Une procédure de hook transmet un événement à la procédure suivante en appelant la fonction CallNextHookEx .

Notez que les procédures de hook pour certains types de hooks ne peuvent surveiller que les messages. le système transmet des messages à chaque procédure de hook, qu’une procédure particulière appelle Ou non CallNextHookEx.

Un hook global surveille les messages pour tous les threads dans le même bureau que le thread appelant. Un hook spécifique au thread surveille uniquement les messages d’un thread individuel. Une procédure de hook global peut être appelée dans le contexte de n’importe quelle application dans le même bureau que le thread appelant, de sorte que la procédure doit se trouver dans un module DLL distinct. Une procédure de hook spécifique au thread est appelée uniquement dans le contexte du thread associé. Si une application installe une procédure de hook pour l’un de ses propres threads, la procédure de hook peut se trouver dans le même module que le reste du code de l’application ou dans une DLL. Si l’application installe une procédure de hook pour un thread d’une autre application, la procédure doit se trouver dans une DLL. Pour plus d’informations, consultez Bibliothèques de liens dynamiques.

Notes

Vous devez utiliser des hooks globaux uniquement à des fins de débogage ; sinon, vous devriez les éviter. Les hooks globaux nuisent aux performances du système et provoquent des conflits avec d’autres applications qui implémentent le même type de hook global.

 

Types de crochets

Chaque type de hook permet à une application de surveiller un aspect différent du mécanisme de gestion des messages du système. Les sections suivantes décrivent les hooks disponibles.

WH_CALLWNDPROC et WH_CALLWNDPROCRET

Les crochets WH_CALLWNDPROC et WH_CALLWNDPROCRET vous permettent de surveiller les messages envoyés aux procédures de fenêtre. Le système appelle une procédure de hook WH_CALLWNDPROC avant de passer le message à la procédure de fenêtre de réception, puis appelle la procédure de hook WH_CALLWNDPROCRET une fois que la procédure de fenêtre a traité le message.

Le crochet WH_CALLWNDPROCRET transmet un pointeur vers une structure CWPRETSTRUCT vers la procédure de hook. La structure contient la valeur de retour de la procédure de fenêtre qui a traité le message, ainsi que les paramètres de message associés au message. La sous-classification de la fenêtre ne fonctionne pas pour les messages définis entre les processus.

Pour plus d’informations, consultez les fonctions de rappel CallWndProc et CallWndRetProc .

WH_CBT

Le système appelle une procédure de crochet WH_CBT avant d’activer, de créer, de détruire, de réduire, d’optimiser, de déplacer ou de dimensionner une fenêtre ; avant d’effectuer une commande système ; avant de supprimer un événement de souris ou de clavier de la file d’attente de messages système ; avant de définir le focus d’entrée ; ou avant la synchronisation avec la file d’attente de messages système. La valeur renvoyée par la procédure de crochet détermine si le système autorise ou empêche l’une de ces opérations. Le crochet WH_CBT est principalement destiné aux applications d’entraînement par ordinateur (CBT).

Pour plus d’informations, consultez la fonction de rappel CBTProc .

Pour plus d’informations, consultez WinEvents.

WH_DEBUG

Le système appelle une procédure de hook WH_DEBUG avant d’appeler les procédures de hook associées à tout autre hook dans le système. Vous pouvez utiliser ce crochet pour déterminer s’il faut autoriser le système à appeler des procédures de hook associées à d’autres types de crochets.

Pour plus d’informations, consultez la fonction de rappel DebugProc .

WH_FOREGROUNDIDLE

Le crochet WH_FOREGROUNDIDLE vous permet d’effectuer des tâches de faible priorité pendant les moments où son thread de premier plan est inactif. Le système appelle une procédure de crochet WH_FOREGROUNDIDLE lorsque le thread de premier plan de l’application est sur le point de devenir inactif.

Pour plus d’informations, consultez la fonction de rappel ForegroundIdleProc .

WH_GETMESSAGE

Le crochet WH_GETMESSAGE permet à une application de surveiller les messages sur le point d’être retournés par la fonction GetMessage ou PeekMessage . Vous pouvez utiliser le crochet WH_GETMESSAGE pour surveiller les entrées de souris et de clavier et d’autres messages publiés dans la file d’attente des messages.

Pour plus d’informations, consultez la fonction de rappel GetMsgProc .

WH_JOURNALPLAYBACK

Avertissement

Les API de crochets de journalisation ne sont pas prises en charge à partir de Windows 11 et seront supprimées dans une version ultérieure. Pour cette raison, nous vous recommandons vivement d’appeler l’API SendInput TextInput à la place.

Le crochet WH_JOURNALPLAYBACK permet à une application d’insérer des messages dans la file d’attente des messages système. Vous pouvez utiliser ce crochet pour lire une série d’événements de souris et de clavier enregistrés précédemment à l’aide de WH_JOURNALRECORD. L’entrée régulière de la souris et du clavier est désactivée tant qu’un crochet WH_JOURNALPLAYBACK est installé. Un crochet WH_JOURNALPLAYBACK est un hook global. Il ne peut pas être utilisé comme un hook spécifique au thread.

Le crochet WH_JOURNALPLAYBACK retourne une valeur de délai d’attente. Cette valeur indique au système combien de millisecondes il faut attendre avant de traiter le message actuel à partir du crochet de lecture. Cela permet au crochet de contrôler le minutage des événements qu’il lit.

Pour plus d’informations, consultez la fonction de rappel JournalPlaybackProc .

WH_JOURNALRECORD

Avertissement

Les API de crochets de journalisation ne sont pas prises en charge à partir de Windows 11 et seront supprimées dans une version ultérieure. Pour cette raison, nous vous recommandons vivement d’appeler l’API SendInput TextInput à la place.

Le crochet WH_JOURNALRECORD vous permet de surveiller et d’enregistrer les événements d’entrée. En règle générale, vous utilisez ce crochet pour enregistrer une séquence d’événements de souris et de clavier à lire ultérieurement à l’aide de WH_JOURNALPLAYBACK. Le crochet WH_JOURNALRECORD est un crochet global. Il ne peut pas être utilisé comme un crochet spécifique au thread.

Pour plus d’informations, consultez la fonction de rappel JournalRecordProc .

WH_KEYBOARD_LL

Le crochet WH_KEYBOARD_LL vous permet de surveiller les événements d’entrée du clavier sur le point d’être publiés dans une file d’attente d’entrée de thread.

Pour plus d’informations, consultez la fonction de rappel LowLevelKeyboardProc .

WH_KEYBOARD

Le crochet WH_KEYBOARD permet à une application de surveiller le trafic de messages pour WM_KEYDOWN et WM_KEYUP messages sur le point d’être retournés par la fonction GetMessage ou PeekMessage . Vous pouvez utiliser le crochet WH_KEYBOARD pour surveiller les entrées au clavier publiées dans une file d’attente de messages.

Pour plus d’informations, consultez la fonction de rappel KeyboardProc .

WH_MOUSE_LL

Le crochet WH_MOUSE_LL vous permet de surveiller les événements d’entrée de souris sur le point d’être publiés dans une file d’attente d’entrée de thread.

Pour plus d’informations, consultez la fonction de rappel LowLevelMouseProc .

WH_MOUSE

Le crochet WH_MOUSE vous permet de surveiller les messages de souris sur le point d’être retournés par la fonction GetMessage ou PeekMessage . Vous pouvez utiliser le crochet WH_MOUSE pour surveiller les entrées de souris publiées dans une file d’attente de messages.

Pour plus d’informations, consultez la fonction de rappel MouseProc .

WH_MSGFILTER et WH_SYSMSGFILTER

Les WH_MSGFILTER et les crochets WH_SYSMSGFILTER vous permettent de surveiller les messages sur le point d’être traités par un menu, une barre de défilement, une boîte de message ou une boîte de dialogue, et de détecter quand une autre fenêtre est sur le point d’être activée à la suite d’un appui de l’utilisateur sur la combinaison de touches ALT+TAB ou ALT+ÉCHAP. Le crochet WH_MSGFILTER peut uniquement surveiller les messages transmis à un menu, à une barre de défilement, à une boîte de message ou à une boîte de dialogue créée par l’application qui a installé la procédure de hook. Le crochet WH_SYSMSGFILTER surveille ces messages pour toutes les applications.

Les crochets WH_MSGFILTER et WH_SYSMSGFILTER vous permettent d’effectuer un filtrage des messages pendant les boucles modales qui équivaut au filtrage effectué dans la boucle de message main. Par exemple, une application examine souvent un nouveau message dans la boucle main entre le moment où elle récupère le message de la file d’attente et le moment où elle le distribue, en effectuant un traitement spécial le cas échéant. Toutefois, lors d’une boucle modale, le système récupère et distribue des messages sans permettre à une application de filtrer les messages dans sa boucle de message main. Si une application installe une procédure de hook WH_MSGFILTER ou WH_SYSMSGFILTER , le système appelle la procédure pendant la boucle modale.

Une application peut appeler le hook WH_MSGFILTER directement en appelant la fonction CallMsgFilter . En utilisant cette fonction, l’application peut utiliser le même code pour filtrer les messages pendant les boucles modales qu’elle utilise dans la boucle de message main. Pour ce faire, encapsulez les opérations de filtrage dans une procédure de hook WH_MSGFILTER et appelez CallMsgFilter entre les appels aux fonctions GetMessage et DispatchMessage .

while (GetMessage(&msg, (HWND) NULL, 0, 0)) 
{ 
    if (!CallMsgFilter(&qmsg, 0)) 
        DispatchMessage(&qmsg); 
} 

Le dernier argument de CallMsgFilter est simplement passé à la procédure hook ; vous pouvez entrer n’importe quelle valeur. La procédure de hook, en définissant une constante telle que MSGF_MAINLOOP, peut utiliser cette valeur pour déterminer d’où elle a été appelée.

Pour plus d’informations, consultez les fonctions de rappel MessageProc et SysMsgProc .

WH_SHELL

Une application shell peut utiliser le crochet WH_SHELL pour recevoir des notifications importantes. Le système appelle une procédure de hook WH_SHELL lorsque l’application shell est sur le point d’être activée et lorsqu’une fenêtre de niveau supérieur est créée ou détruite.

Notez que les applications d’interpréteur de commandes personnalisées ne reçoivent pas de messages WH_SHELL . Par conséquent, toute application qui s’inscrit comme interpréteur de commandes par défaut doit appeler la fonction SystemParametersInfo avant qu’elle (ou toute autre application) puisse recevoir WH_SHELL messages. Cette fonction doit être appelée avec SPI_SETMINIMIZEDMETRICS et une structure MINIMIZEDMETRICS . Définissez le membre iArrange de cette structure sur ARW_HIDE.

Pour plus d’informations, consultez la fonction de rappel ShellProc .