La bibliothèque graphique de C++Builder se charge de la gestion des messages de fenêtres Windows. Cependant il peut arriver d'avoir besoin de gérer l'interception d'un message personnalisé. J'ai rencontré le cas pour recevoir un message de la barre des tâches de Windows. Celle-ci émet des messages définis par l'utilisateur.
On commence donc par en définir un:
#define WM_TASKBAR (WM_APP+1)
Ensuite on enregistre ce message auprès de la barre des tâches:
NOTIFYICONDATA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hIcon = Application->Icon->Handle;
nid.hWnd = Handle;
strcpy(nid.szTip, "Mon Application");
nid.uCallbackMessage = WM_TASKBAR;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uID = MON_ICON;
// etc...
::Shell_NotifyIcon(NIM_ADD, &nid);
A partir d'ici la barre des tâches émettra, selon les circonstances, les messages WM_TASKBAR vers notre application. Nous abordons maintenant la question cruciale: comment recevoir ce message dans une application C++Builder ? On commence par déclarer un gestionnaire de message:
protected:
void __fastcall OnTaskbar(TMessage &Message);
Le gestionnaire doit obligatoirement être declaré dans la section protected de la classe de fenêtre. Le mot clef __fastcall doit être présent. Même si le message n'est qu'un simple nombre (voir sa déclaration ci-dessus), le mécanisme de routage des message de C++Builder va enrober ce nombre dans une instance de TMessage. Donc notre gestionnaire est déclaré recevant un objet de ce type.
Voici maintenant la recette magique qui branche notre gestionnaire avec le message.
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_TASKBAR, TMessage, OnTaskbar)
END_MESSAGE_MAP(TForm)
Cette déclaration réside elle aussi dans la section protected. Nous employons donc 3 macros. Dans la macro du milieu on trouve successivement l'identifiant du message, le type de l'objet qui l'enrobe et le nom du gestionnaire. Dans la dernière macro, on trouve le nom de la classe de base de la classe de la fenêtre principale de l'application. Et voilà, le tour est joué!