C++Builder logo
System-wide hook System-wide hook

1. What is a hook? Qu'est-ce qu'un hook?
A hook is a mechanism we can use to monitor windows messages before they reach the target window. This allows us to intercept messages and perform a certain task before they are treated by the window.
For a global hook  the code must be placed in a DLL. For an application hook, it is not required.
To install a hook, we use SetWindowsHookEx(), specifying the type of the hook and a callback procedure. To release the hook, we call UnhookWindowsHookEx(), specifying the hook handle of the early created hook. SetWindowsHookEx() add the hook to a chain. The hook procedure can call the next hook in the chain or not. It depends on our needs.
Un hook est un système qui permet d'intercepter les messages que Windows envoie aux fenêtres avant qu'ils ne soient traiter par la fenêtre.
Le code du hook doit être placé dans une DLL si le hook est global. Ceci n'est pas nécessaire si le hook ne concerne qu'une application.
Pour installer un hook, on appelle la fonction de l'API SetWindowsHookEx() en spécifiant un type de hook et une procédure de callback. Pour supprimer un hook, on appelle la fonction UnhookWindowsHookEx() en lui donnant en paramètre le handle du hook créé précédemment. SetWindowsHookEx() ajoute le hook à une chaîne. La procédure peut permettre ou non l'appel du hook suivant dans la chaîne.
2. Types of hook Types de hook
WH_CALLWNDPROC Allows you to monitor messages sent by Windows with SendMessage(). The WH_CALLWNDPROC hook procedure is called before the message is sent to the target window.

Permet de monitorer les messages envoyés par Windows au moyen de SendMessage(). La procédure de hook est appelée avant que le message ne soit envoyé à la fenêtre.

WH_CALLWNDPROCRET Allows you to monitor messages send by windows with SendMessage(). The WH_CALLWNDPROCRET hook procedure is called after the message is sent to the target window.

Permet de monitorer les messages envoyés par windows au moyen de SendMessage(). La procédure de hook est appelée après que le message ne soit envoyé à la fenêtre.

WH_CBT The hook is called before a system command is completed like creating, destroying, sizing, moving ... a window.

Le hook est appelé avant qu'une commande système ne soit effectuée, comme par exemple créer, détruire, redimensionner ou bouger une fenêtre.

WH_DEBUG The hook procedure is called before any other type of hook.

La procédure de hook est lancée avant tout autre type de hook.

WH_FOREGROUNDIDLE The hook procedure is called when the foreground thread is idle.

La procédure de hook est appelée lorsque le thread est en mode idle.

WM_GETMESSAGE This type of hook allows you to monitor messages about to be returned by PeekMessage() or GetMessage() and posted to the message queue.

Ce type permet de monitorer les messages sur le point d'être renvoyer par PeekMessage() et GetMessage() et envoyés dans la 'message queue'.

WH_JOURNALPLAYBACK With this hook, you can insert messages in the message queue.

Ce type de hook permet d'insérer des messages dans la 'message queue'.

WH_JOURNALRECORD It allows you to record a sequence of messages, like mouse or keyboard messages, and send them later using WH_JOURNALPLAYBACK.

Permet d'enregistrer une séquence de messages comme par exemple ceux envoyés par la souris ou le clavier et de les envoyer plus tard en utilisant WH_JOURNALPLAYBACK.

WH_KEYBOARD Enables you to intercept keyboard messages.

Permet d'intercepter les messages du clavier.

WH_MOUSE Enables you to intercept mouse messages.

Permet d'intercepter les messages de la souris.

WH_MSGFILTER This type of hook is used to monitor messages sent to a menu, scrollbar, dialogbox. It can only be used by the application who installed the hook.

Ce type de hook est utilisé pour monitorer les messages envoyés par les menus, les scrollbars ou les boîtes de dialogue. Il ne peut être utilisé que par l'application qui a installé le hook.

WH_SYSMSGFILTER Same as above but for all applications.

Même chose que le type ci-dessus mais pour l'ensemble des applications.

WM_SHELL Called when the shell is about to be activated and when a top-level window is created or destroyed.

Ce hook est apelé lorsque le shell est sur le point d'être activé et lorsqu'une fenêtre 'top-level' est créée ou détruite.

3. Example : Installing a mouse hook Exemple : Installation d'un hook sur la souris 
As an example, we will try to install a mouse hook wich will launch the screensaver everytime the mouse is in the upper right edge of the screen. Whenever the mouse is moved, the hook procedure is called. This one does the following : it gets the mouse position with GetCursorPos(), check if the mouse is in a predetermined rectangle, corresponding to the upper right edge and if it is the case, launch the screen saver. Then  it calls the next hook in the chain using CallNextHookEx(). Comme exemple de hook, nous allons installer un hook sur la souris qui lancera l'économiseur d'écran lorsque la souris sera dans le coin droit supérieur de l'écran. Chaque fois que la souris bouge la procédure de hook est appelée. Celle-ci effectue les tâches suivantes : obtenir la position de la souris avec la fonction GetCursorPos(), tester si la souris se trouve dans un rectangle prédéterminé, correspondant au coin supérieur droit de l'écran, lancer le screensaver et ensuite appeler le hook suivant dans la chaîne de hook CallNextHookEx().
First, create a new application with two buttons on the form and a label. The first button  is used to install the hook, the second to release the hook.
The real functions which install and remove the hook are in the DLL, so the only thing the button function do is calling a function in the DLL.
Place the code below in the OnClick event of each button :
D'abord, créons une nouvelle application et plaçons deux boutons sur la forme et un label. Le premier bouton sert à installer le hook, le second à le supprimer.
Comme les véritables fonctions qui installent et suppriment le hook se trouve dans la DLL, l'appui sur un bouton ne fait qu'appeler une fonction contenue dans la DLL.
Placez le code suivant dans l'événement OnClick de chaque bouton :

In Unit1.h :

// place this before the class declaration 
typedef  bool (__stdcall *MOUSEHOOKFCT)(); 

private// User declarations 
  HINSTANCE DllHandle; 


In Unit1.cpp : 

void __fastcall TForm1::Button1Click(TObject *Sender) 

  DllHandle=LoadLibrary("MouseHook.dll"); 
  MOUSEHOOKFCT InstHook=reinterpret_cast<MOUSEHOOKFCT> 
        (GetProcAddress(DllHandle,"_InstallMouseHook")); 
  if(!InstHook()) 
  { 
    Label1->Caption="Unable to install mouse hook!"
  } 
  else Label1->Caption="Mouse hook installed!"

//--------------------------------------------------------------------------- 
void __fastcall TForm1::Button2Click(TObject *Sender) 

  MOUSEHOOKFCT RemHook=reinterpret_cast<MOUSEHOOKFCT> 
        (GetProcAddress(DllHandle,"_RemoveMouseHook")); 
  if(!RemHook()) 
  { 
    Label1->Caption="Unable to remove mouse hook!"
  } 
  else Label1->Caption="Mouse hook removed!"
  FreeLibrary(DllHandle); 



Now, we have to create the DLL containing the hook procedure and the functions to install and remove the hook. Click on the File menu, choose New... and DLL. Then click OK. The canvas of our DLL is automatically created by Builder.
We want to export two functions : InstallMouseHook() which will be called by the install hook button and a RemoveMouseHook() which will be called by the remove hook button. After the two exported functions, we have the declaration of the hook procedure and some global variables.
The DllEntrypoint() allows us to know when the DLL is mapped in or out the application address space.
InstallMouseHook() install the hook, calling SetWindowsHookEx().
RemoveMouseHook() remove the hook using UnhookWindowsHookEx().
MouseProc() is the callback hook procedure. It's the procedure called by Windows whenever the mouse moves. First we create a rectangle and get the position of the mouse. We check if the mouse is in the rectangle and if true, we launch the screensaver using SendMessage(). And finally, we call the next hook in the chain using CallNextHookEx().
Nous devons maintenant créer la DLL qui va contenir le code du hook et les fonctions appelées par les deux boutons de notre forme pour installer et désinstaller le hook. Cliquez sur le menu Fichier. Choisissez Nouveau... puis DLL. Builder crée alors le canevas de notre DLL.
Nous voulons exporter deux fonctions : InstallMouseHook() et RemoveMouseHook() qui sont les deux fonctions appelées par les boutons du formulaire. Après la déclarations des deux fonctions exportées, nous trouvons la déclaration de la fonction de callback utilisée par le hook et appelée chaque fois que la souris bouge.
DllEntryPoint() est appelée chaque fois que la DLL est mappée dans la zône d'adresse de notre application.
InstallMouseHook() installe le hook en utilisant la fonction SetWindowsHookEx().
RemoveMouseHook() supprime le hook en utilisant UnhookWindowsHookEx().
MouseProc() est la fonction de callback proprement dite et est appelée par Windows lorsque la souris bouge. Dans cette fonction, on crée d'abord un rectangle correspondant au coin supérieur droit de l'écran, ensuite on obtient la position de la souris et on teste pour savoir si la souris se trouve dans le rectangle. Si c'est le cas, on lance le screensaver au moyen de SendMessage(). pour terminer, on appelle le hook suivant dans la chaîne avec CallNextHookEx().

#include <vcl.h> 
#include <windows.h> 
#pragma hdrstop 
// Exported functions 
extern "C" __declspec(dllexport)bool InstallMouseHook(); 
extern "C" __declspec(dllexport)bool RemoveMouseHook(); 

// Callback Procedure Declaration 
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam); 

// Global variables 
HHOOK HookHandle; 
HINSTANCE DllInstance; 
bool IsInRect=false

//--------------------------------------------------------------------------- 
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) 

  DllInstance=hinst; 
  return 1; 

//--------------------------------------------------------------------------- 
bool InstallMouseHook() 

  HookHandle=SetWindowsHookEx(WH_MOUSE, 
      reinterpret_cast<HOOKPROC>(MouseProc),DllInstance,0); 
  if (HookHandle==NULL)return false
  else return true

//--------------------------------------------------------------------------- 
bool RemoveMouseHook() 

  if(UnhookWindowsHookEx(HookHandle)==0) 
  { 
    return false
  } 
  else return true

//--------------------------------------------------------------------------- 
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) 

  if (code<0) 
  { 
    return CallNextHookEx(HookHandle,code,wParam,lParam); 
  } 
  //Define a rectangle 
  POINT MousePos; 
  RECT UpperRightCorner=Rect(Screen->Width-2,0,Screen->Width,2); 
  //Get the mouse position 
  GetCursorPos(&MousePos); 
  //Check if the mouse is in the rectangle 
  if((PtInRect(&UpperRightCorner,MousePos))&&(IsInRect==false)) 
  { 
    //if the mouse is in the rectangle, launch the screensaver 
    IsInRect=true
    SendMessage(GetDesktopWindow(),WM_SYSCOMMAND,SC_SCREENSAVE,0);
  } 
  else IsInRect=false
  //Call the next hook in the chain 
  return CallNextHookEx(HookHandle,code,wParam,lParam); 
}

 
All you have to do now is to build the application and the DLL. 
Run the application and click on the button1, this will install the hook. Put the mouse in the upper right edge of the screen . This will launch the screensaver. A click on the second button will uninstall the hook.
Il ne vous reste plus qu'à compiler l'application et la DLL. Ensuite, lancez l'application et cliquez sur le bouton 1 pour installer le hook . Placez la souris dans le coin supérieur droit, cela devrait lancer le screensaver. Si vous voulez désinstaller le hook, cliquez sur le deuxième bouton.

            Download : BCB4 source code (5.97 kb)