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.
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.
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é...
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:
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: