Tout sur l'utilisation d'une icone dans le sys-tray

Soyez le premier à donner votre avis sur cette source.

Vue 6 756 fois - Téléchargée 609 fois

Description

Voici un petit programme de demonstration de l'utilisation d'une icone dans le sys-tray. Il est largement commenté afin d'être facile à comprendre ( du moins je l'espère... )

Il regroupe les points suivants :
- Ajout d'une icone
- Modification de l'icone
- Suppression de l'icone
- Ajout d'une action sur le clique gauche, ignorée dans le cas d'un double-clique
- Ajout d'une action sur le clique droit
- Ajout d'une action sur le double-clique

L'application présente juste une icone qui indique la direction de la souris. Ce n'est pas utile, mais c'est pour l'exemple...

Si vous pensez que j'ai oublié quelque chose en rapport aux icones dans le systray, merci de me laisser un commentaire... Je me ferais un plaisir de compléter.

Source / Exemple :


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.

Conclusion :


Remarque : La source déposée juste avant celle-ci traite en partie du même sujet, mais je pense que les deux sont complémentaire, de plus ça fait deux soirées que je travaille dessus... Je l'ai donc posée quand même, mais si vous pensez qu'elle est en trop...

Cette source et quelques autres sur : http://nono40.developpez.com

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

cs_Nono40
Messages postés
962
Date d'inscription
mercredi 3 avril 2002
Statut
Membre
Dernière intervention
12 septembre 2006
1
Oh là là oui... la prochaine fois je choisirais mieux mon sujet..

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.