Developpez.com - Delphi
X

Choisissez d'abord la catégorieensuite la rubrique :

Nono40.developpez.com
Le petit coin du web de Nono40
SOURCES TESTS DELPHI WIN32 AUTOMATISMES DELPHI .NET QUICK-REPORT
Retour à l'accueil
27 - UTILISATION D'UNE ICONE DANS LE SYSTRAY

PRÉSENTATION : Création, modification, menu, clicks... tout sur l'icône dans le systray !
ZIP : Téléchargez le zip APERÇUS :

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.

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2003 Bruno Guérangé. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Responsables bénévoles de la rubrique Delphi : Gilles Vasseur - Alcatîz -