|
PRÉSENTATION :
Création, modification, menu, clicks... tout sur l'icône dans le systray !
NOTES :
Voici un programme exemple simple montrant la mise en oeuvre d'une icône dans le systray ( barre des tâches )
Ce programme affiche une petite flèche dans le systray donnant la direction de la souris ( c'est parfaitement inutile, mais c'est pour l'exemple ).
Un menu est affiché sur le bouton gauche et un autre sur le bouton droit, de plus le double-clique est utilisé pour remettre l'application au premier plan.
Toutes les méthodes sont décrites dans les commentaires du source, en particulier l'utilisation simultanée du click et du double-click.
CODE :
Unit Unit1;
Interface
Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Menus;
Const
// Définition d'un message personnalisé.
// Ce message est envoyé par Windows sur demande quand un évènement
// lié à la souris intervient.
WM_MONICONE = WM_USER +1;
Type
TForm1 = Class(TForm)
TimerMiseAJour: TTimer;
PopUpGauche: TPopupMenu;
ActiverSuiviItem: TMenuItem;
PopUpDroit: TPopupMenu;
QuitterItem: TMenuItem;
TimerRetardMessage: TTimer;
RestaurerItem: TMenuItem;
ReduireItem: TMenuItem;
Procedure FormCreate(Sender: TObject);
Procedure FormDestroy(Sender: TObject);
Procedure TimerMiseAJourTimer(Sender: TObject);
Procedure ActiverSuiviItemClick(Sender: TObject);
Procedure QuitterItemClick(Sender: TObject);
Procedure TimerRetardMessageTimer(Sender: TObject);
Procedure RestaurerItemClick(Sender: TObject);
Procedure ReduireItemClick(Sender: TObject);
Private
{ Déclarations privées }
// Ce tableau regroupe est Handles des icones extraites du fichier
LesIcones :Array[0..5]Of HICON;
// Numero dans le tableau ci-dessus de l'icone actuellement affichée
IconeEnCours :Integer;
// Mémorisation du dernier message reçu par l'icone
// ( voir son utilité dans MessageIcone() )
DernierMSG :TMsg;
// Définition d'une méthode de réponse au message personnalisé créé
Procedure MessageIcone(Var Msg: TMsg);Message WM_MONICONE;
// Procédure d'ajout de l'icone, est appelée au début de l'application
Procedure AjouteIcone;
// Procédure de mise à jour de l'icone
Procedure ModifieIcone;
// Procédure de suppression de l'icone, est appelée à la fermeture
Procedure SupprimeIcone;
Public
{ Déclarations publiques }
End;
Var
Form1: TForm1;
Implementation
Uses ShellApi;
{$R *.dfm}
// Ajout d'un fichier de ressource contenant les icones affichées dans la barre des taches
// Les icones étant définies par un numéro de 0 à n dans le fichier exe en fonction
// de leur ordre alphabétique ( leur nom dans le .RES ).
// le mieux est de définir des noms d'icones en Zxxxx afin que l'icone de l'exe soit celle
// contenu dans les options de projet.
{$R icones.res}
// Au démarrage de l'application
Procedure TForm1.FormCreate(Sender: TObject);
Var i:Integer;
Begin
// On extrait les icones du fichier .EXE de l'application
For i:=0 To 5 Do LesIcones[i]:=ExtractIcon(Application.Handle,PChar(Application.exename),i);
// L'icone est ajoutée dans la barre des taches
IconeEnCours:=0;
AjouteIcone;
End;
// A la fin de l'application
Procedure TForm1.FormDestroy(Sender: TObject);
Var i:Integer;
Begin
// L'icone est supprimée de la barre des taches
SupprimeIcone;
// Et les handles des icones sont libérés
For i:=0 To 5 Do If LesIcones[i]>1 Then DestroyIcon(LesIcones[i]);
End;
// Procédure d'ajout d'une icone dans la barre des taches
Procedure TForm1.AjouteIcone;
Var Info:TNotifyIconData;
Begin
// If faut tout d'abord remplir la structure Info
// avec ce que l'on veut faire
// cbSize doit contenir la taille de la structure
Info.cbSize := SizeOf(Info);
// Wnd doit contenir le Handle de la fenêtre qui recevra les messages de
// notification d'évènement de la souris
Info.Wnd := Handle;
// uID Numéro d'icone, c'est utile si plusieurs icones sont affichées en
// simultannées dans la barre des taches. Car c'est ce numéro qui permettra
// ensuite de modifier celle que l'on veut.
Info.uID := 1;
// szTip contient le texte de l'info bulle affiché au dessus de l'icone
Info.szTip := 'Exemple d''icones par Nono40';
// hIcon contient le handle de l'icone qui doit être affichée
Info.hIcon := LesIcones[IconeEnCours];
// uCallBackMessage contient le message qui sera retourné à la fenêtre
// donnée par Wnd quand un évènement de souris apparait sur l'icone
Info.uCallbackMessage := WM_MONICONE;
// uFlags doit contenir le liste des champs utilisés dans la structure
// parmis les champs szTip,hIcon et uCallBackMessage
Info.uFlags := NIF_TIP Or NIF_ICON Or NIF_MESSAGE;
// Appel de la fonction API ajoutant l'icone
Shell_NotifyIcon(NIM_ADD,@Info);
End;
Procedure TForm1.ModifieIcone;
Var Info:TNotifyIconData;
Begin
// If faut tout d'abord remplir la structure Info
// avec ce que l'on veut faire
// ( voir la procédure ci-dessus pour les détails )
Info.cbSize := SizeOf(Info);
Info.Wnd := Handle;
Info.uID := 1;
Info.uFlags := NIF_TIP Or NIF_ICON Or NIF_MESSAGE;
Info.szTip := 'Exemple d''icones par Nono40';
Info.hIcon := LesIcones[IconeEnCours];
Info.uCallbackMessage := WM_MONICONE;
Shell_NotifyIcon(NIM_MODIFY,@Info);
End;
Procedure TForm1.SupprimeIcone;
Var Info:TNotifyIconData;
Begin
// Dans le cas de la suppression d'une icone, seuls les champs ci-dessous
// sont nécessaires
Info.cbSize := SizeOf(Info);
Info.Wnd := Handle;
Info.uID := 1;
Shell_NotifyIcon(NIM_DELETE,@Info);
End;
// Procédure liée au timer chargée de changer l'icone si besoin
Procedure TForm1.TimerMiseAJourTimer(Sender: TObject);
Var X :Integer;
Y :Integer;
NouvelleIcone :Integer;
Begin
// En premier lieu, on détermine l'icone qui doit être affichée
If ActiverSuiviItem.Checked
Then Begin
// Si le suivi de la souris est actif, il faut calculer l'angle
// antre le bas de l'écran et la ligne joignant la souris au coin bas-droit
// de l'écran. ArcTan(Y/X) retourne l'angle en Radian, la nouvelle icone
// n'est ensuite qu'une régle de trois pour obtenir une valeur entre 1 et 5
// ( car c'est le nombre d'icones différentes )
X := Screen.Width +30 -Mouse.CursorPos.X;
Y := Screen.Height +30 -Mouse.CursorPos.Y;
NouvelleIcone:=Round(Arctan(Y/X)/(PI/2)*5)+1;
// Il faut quand même vérifier que le résultat est cohérent
// ce n'est pas forcément utile, mais bon enfin c'est là...
If NouvelleIcone<1 Then NouvelleIcone:=1;
If NouvelleIcone>5 Then NouvelleIcone:=5;
End
Else Begin
// Si le suivi de la souris n'est pas activé
// c'est l'icone de base qui est affichée
NouvelleIcone:=0;
End;
// Dans le cas ou l'icone doit être changée, ben alors elle est changée...
If NouvelleIcone<>IconeEnCours
Then Begin
IconeEnCours:=NouvelleIcone;
ModifieIcone;
End;
End;
// Procédures du menu du bouton GAUCHE
Procedure TForm1.ActiverSuiviItemClick(Sender: TObject);
Begin
// Inversion du suivi de la souris...
ActiverSuiviItem.Checked := Not ActiverSuiviItem.Checked;
End;
// Procédures du menu du bouton DROIT
Procedure TForm1.QuitterItemClick(Sender: TObject);
Begin
// Quitter l'application
Close;
End;
Procedure TForm1.RestaurerItemClick(Sender: TObject);
Begin
// Restaurer l'application
Application.Restore;
End;
Procedure TForm1.ReduireItemClick(Sender: TObject);
Begin
// Réduire l'application
Application.Minimize;
End;
// Procédure de réponse à notre message personnalisé
// A chaque évènement de la souris, cette procédure sera appelée
// Windows retourne dans le champ wParam du message le message original
// de l'icone.
// Ainsi, MSG.Message contient WM_MONICONE
// et MSG.wParam contient WM_LBUTTONDOWN ou WM_LBUTTONUO ou ...
// Il est donc facile de faire le tri
Procedure TForm1.MessageIcone(Var MSG:TMSG);
Begin
// Click du bouton gauche
If MSG.wParam=WM_LBUTTONDOWN
Then Begin
// Attention, si le double click doit être géré, il ne faut pas exécuter
// tout de suite l'action liè à ce message. Surtout si un menu est affiché
// sur le click gauche. Dans ce cas le double-click ne se produit pas car
// le deuxième click n'est plus lié à l'icone mais au menu.
// Le message est enregistré, pour être tester plus tard si aucun autre
// click et/ou double-clique n'est reçu
DernierMSG := MSG;
// C'est le timer qui exécutera le message en cas de besoin
TimerRetardMessage.Enabled:=True;
End;
If MSG.wParam=WM_RBUTTONUP
Then Begin
// Dans le cas du bouton droit, le double-clique n'est pas géré
// le menu liè au bouton droit peut donc être affiché de suite.
// Il est préférable dans ce cas d'utiliser WM_RBUTTONUP plutôt
// que WM_RBUTTONDOWN
PopUpDroit .Popup(Mouse.CursorPos.X,Mouse.CursorPos.Y);
End;
If MSG.wParam=WM_LBUTTONDBLCLK
Then Begin
// Un double-clique est détecté, alors il faut annuler le timer avant
// qu'il n'arrive à terme. Ainsi le l'action liée au click simple
// n'est pas exécutée
TimerRetardMessage.Enabled:=False;
// Le double-click ici restaure l'application
// et elle est mise au premier plan
Application.Restore;
Application.BringToFront
End;
End;
// Procédure lié au timer de retard sur le click-gauche
Procedure TForm1.TimerRetardMessageTimer(Sender: TObject);
Begin
// Il faut vérifier que le message en attente est bien un click-gauche
If DernierMSG.wParam=WM_LBUTTONDOWN
Then Begin
// Dans ce cas le menu lié au click gauche est affiché
PopUpGauche.Popup(Mouse.CursorPos.X,Mouse.CursorPos.Y);
End;
// Le timer est ensuite annulé pour ne pas répéter le message...
TimerRetardMessage.Enabled := False;
End;
End.
|
| |