Systray

 

De plus en plus de programmes se placent dans la barre de tâches à droite (c'est le systray) lorsque l'utilisateur passe ceux-ci sous forme d'icône:

 

Pour cela, il suffit d'utiliser la fonction Shell_NotifyIcon qui va envoyer un message à la barre de tâches pour lui indiquer ce que vous voulez faire de votre programme lorsque celui-ci est icônisé.

BOOL Shell_NotifyIcon(
DWORD dwMessage,
PNOTIFYICONDATA lpdata
);

Les paramètres sont:

dwMessage : Message à envoyer à la barre de tâches qui peut-être le suivant:

Valeur Description
NIM_ADD Demande l'ajout d'une icône dans la barre. lpdata doit avoir impérativement le handle de la window ainsi que identificateur de l'icône renseignés. Ces valeurs seront utilisées pour les prochains appels à Shell_NotifyIcon()
NIM_DELETE Effacer l'icône de la barre. Là aussi, il faudra renseigner le handle de la window ainsi que identificateur de l'icône.
NIM_MODIFY Modifier l'icône. Là aussi, il faudra renseigner le handle de la window ainsi que identificateur de l'icône. Cela peut permettre une animation.
NIM_SETFOCUS (à partir de la version 5) : rendre le focus à la barre de tâches. Utile pour réactiver la barre.
NIM_SETVERSION

Permet de spécifier la version de système et donc la version de la fonction à utiliser (Attention pour la compatibilité descendante éventuelle).

La version compatible tous systèmes est 0 (pour Windows 95), mais il manque alors des fonctions. Reste à voir si ces fonctions vous sont indispensables...

La version compatible à partir de Windows 2000 est NOTIFYICON_VERSION

Pour déterminer le type de système, il faudra alors utiliser la fonction GetVer

 

Bon voilà un petit problème : On parle ici de version avec NIM_SETVERSION. En effet, cette fonction a évolué entre Windows 95 et Windows 2000...

Donc soit on se fiche des nouveautés et on veut que le programme soit portable. Dans ce cas, on passera 0 dans ce numéro de version (c'est la valeur par défaut).

Soit on veut utiliser ces nouveautés, mais il faut aussi pouvoir le faire fonctionner dans les systèmes antérieurs. Dans ce cas, il faut d'abord connaître la version de cette DLL. Cette fonction est déclarée dans la DLL Shell32. Pour connaître la version, utilisez la fonction DllGetVersion().


Maintenant que vous avez le numéro de version, vous pouvez définir la version correctement dans NIM_SETVERSION.

La version 5.0 correspond à Windows 2000 et la 6.0 correspond à XP. Vous pourrez utiliser NOTIFYICON_VERSION. Sinon il faut mettre 0

 

Une autre solution consiste à essayer la version NOTIFYICON_VERSION avec dwMessage à NIM_SETVERSION. La fonction retournera false si elle est incompatible ou non supportée.

 

lpdata Pointeur sur une structure de type NOTIFYICONDATA. Le contenu de cette structure va dépendre de dwMessage.

 

Le second problème : il faut tout gérer à la main. Un double clique ne va donc pas réouvrir votre fenêtre. Heureusement, comme vous le verrez par la suite dans la défintion de la structure, votre fenêtre pourra récupérer les évènements qui vont se produire sur son icône grâce au membre uCallbackMessage de la structure.

 

Structure NOTIFYICONDATA:

typedef struct _NOTIFYICONDATA {
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
TCHAR szTip[64];
DWORD dwState;
DWORD dwStateMask;
TCHAR szInfo[256];
union {
UINT uTimeout;
UINT uVersion;
};
TCHAR szInfoTitle[64];
DWORD dwInfoFlags;
GUID guidItem;
} NOTIFYICONDATA, *PNOTIFYICONDATA;

Les membres sont:

cbSize : Taille de la structure (Utilisez sizeof())

hWnd : Handle de la fenêtre qui va recevoir les informations de la barre de tâches (Cette information est liée avec uID).
uID : Handle de l'icône. Liée à hWnd. Il est donc tout à fait possible d'avoir plusieurs icônes pour la même fenêtre. S'il n'y a qu'une icône, peut importe la valeur, mais si il y en a plusieurs, ne mettez pas n'importe quoi. Car ce sera le seul moyen de connaître l'icône selectionnée.
uFlags : Indique les champs de la structure qui sont valides pour l'opération en cours et donc que ces champs doivent être pris en compte. Ce flag peut donc prendre les valeurs suivantes:

Valeurs Membres ou champs valide
NIF_ICON Le handle de l'icône hIcon
NIF_MESSAGE uCallbackMessage est valide
NIF_TIP szTip
NIF_STATE dwState et dwStateMask
NIF_INFO szInfo, uTimeout, szInfoTitle et dwInfoFlags
NIF_GUID Réservé

 

uCallbackMessage : Message à retourner à votre fenêtre lorsqu'un évènement se produit sur l'icône dans la barre de tâche. Il s'agit d'un message standard qui sera traité dans la procédure de gestion des messages de la fenêtre. wParam contient alors l'id de l'icône, et lParam contient l'évènement (WM_MOUSEMOVE, WM_LBUTTONDOWN, ...). Pour définir la valeur de ce message, vous pourrez utilier WM_APP. Par exemple #define WM_TRAY_ICONE WM_APP

hIcon : Handle de l'icône à afficher, modifier ou supprimer.

Image non trouvée ! Windows 95, Windows 98, et Microsoft Windows NT 4.0 utilisent des icônes à 4 bits par pixel (BPP). Windows Me et Windows 2000 utilisent des icônes correspondant à l'affichage. Windows XP peut aller jusqu'à 32 BPP. Normalement, Windows est capable de convertir l'icône au bon format, mais je ne l'ai pas essayé sur toutes les versions, avec tous les formats possibles...


szTip : Pointeur sur une chaîne de caractères (max. 64 car., à partir de la version 5.0, max. 128 car.) terminée par NULL. Ce message correspondant au message affiché dans le tooltip.

dwState : A partir de la version 5, état de l'icône:

NIS_HIDDEN : l'icône est caché
NIS_SHAREDICON : l'icône est partagé

dwStateMask : Masque pour dwState, et donc uniquement à partir de la version 5.
szInfo : A partir de la Version 5, chaîne de caractères contenant des informations pour le tooltip (balloon ToolTip) (Max. 255 car.). Pour effacer cette zone par la suite, il faut aller en modification en précisant NIF_INFO dans uFlag et szOnfo à NULL.
uTimeout : Durée minimum et maximum du time out pour balloon ToolTip (Le maximum est alors passé dans uVersion)
uVersion : Dans le cas d'un positionnement de version (NIM_SETVERSION), version de Shell_NotifyIcon à utiliser. Sinon TimeOut.
szInfoTitle : A partir de la Version 5: Titre du balloon ToolTip (Terminé par NULL, max. car.: 63)
dwInfoFlags : Lié à szInfoTitle, pour ajouter une icône si la chaîne de titre est renseignée:

Valeur Description
NIIF_ERROR Icone d'erreur
NIIF_INFO Icone d'information
NIIF_NONE Pas d'icone
NIIF_USER A partir de XP service Pack 2, Utilise l'icône identifié dans hIcon
NIIF_WARNING Warning ou attention !
NIIF_ICON_MASK Version 6.0. Reservé.
NIIF_NOSOUND Pas de son !

guidItem : Version 6.0 et réservé...

Image non trouvée ! Pour pouvoir utiliser les membres supportés à partir de la version 5.0, il faut ajouter ceci:

#define _WIN32_IE 0x0500
#define _WIN32_IE 0x0600

Pour initialiser la taille de la structure, il faut utiliser DllGetVersion() pour connaître la version de la dll. Version 5.0 et supérieure, vous préciserez nid.cbSize = sizeof(NOTIFYICONDATA);

Pour une taille avant la 6.0, il faut utiliser NOTIFYICONDATA_V2_SIZE

nid.cbSize = NOTIFYICONDATA_V2_SIZE;

Et enfin avant la version 5.0, NOTIFYICONDATA_V1_SIZE constant.

nid.cbSize = NOTIFYICONDATA_V1_SIZE;

 

Remarques:

  • Si vous ne voulez plus avoir l'icône dans la barre de tâche mais uniquement dans le Systray, il vous faudra gérer le cas de la fenêtre que l'on transforme en icône par le bouton minimum. Pour cela, il faut intercepter le message WM_SYSCOMMAND et traiter SC_MINIMIZE comme ceci:

    if (wParam == SC_MINIMIZE)
    {

    ShowWindow (hwnd, SW_HIDE); // On cache la fenêtre, on ne la tranforme pas en icône !
    return 0; // De plus, il ne faut pas que la procédure par défaut traite ce cas !!!

    }
    break;// Tous les autres cas doivent être traités par la procédure par défaut.

  • De même, si le programme doit être lancé au démarrage et que vous ne voulez pas avoir la fenêtre ouverte, mais l'avoir directement dans le systray, ne pas oublier de faire ShowWindow (hwnd, SW_HIDE); dans WinMain () pour cacher la fenêtre à la place d'un classique ShowWindow (hwnd, nCmdShow);.
  • La fonction IsIconic retournera toujours vrai à partir du moment où vous avez créé une icône en SysTray, Windows considérant que votre fenêtre est sous forme d'icône , et ceci même si votre fenêtre est ouverte sur le bureau !

 

Voici un exemple très simple:

Image non trouvée !Il manque la partie gestion des versions du shell ou encore l'appelle à la fonction SetForegroundWindow(HWND hWnd) permettant de forcer la fenêtre à être au premier plan...


Voici le même avec la gestion de SYS_COMMANDE\SC_MINIMIZE et du foreground:

Image non trouvée !