Interception arret windows

Soyez le premier à donner votre avis sur cette source.

Vue 5 346 fois - Téléchargée 1 395 fois


Description

Installer un programme résident en Trayicon ce n'est pas compliqué quand on sait. Être sûr qu'il n'empêchera pas Windows de se fermer c'est une autre histoire. Elle m'est arrivée. Aussi j'ai écrit un programme complet qui peut servir de base a ceux qui comme moi n'aime pas faire chauffer les neurones.

Source / Exemple :


// L'élément de base du programme tient dans les deux fonctions
// WM_QueryEndSession et WM_EndSession.
// Bien sûr il faut les replacer dans le contexte du programme.
// Aussi le plus simple est de charger le zip qui contient tous les fichiers
// tester sous delphi5 mais qui n'utilise aucun objet extérieur à Delphi
// Un exe est compris dans le zip pour tester le programme.

unit uPrg;

interface

uses
  Windows,
  ShellAPI,
  Messages,
  SysUtils,
  Classes,
  Controls,
  Forms,
  StdCtrls,
  Menus,
  Buttons,
  Dialogs;

const
  // dcResid © D.C V1.0.0.0
  Titre = '%s © D.C V%s';
  Wm_CallBackMessage = wm_user + 1;
  ProgName = 'dcResid';
  ICONON = 1;
  ICONOFF = 2;

type
  TfrmPrg = class(TForm)
    PopMenu: TPopupMenu;
    popAbout: TMenuItem;
    popOuvrir: TMenuItem;
    popExit: TMenuItem;
    N1: TMenuItem;
    N2: TMenuItem;
    Label1: TLabel;
    sbApropos: TSpeedButton;
    Label2: TLabel;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure popAboutClick(Sender: TObject);
    procedure popOuvrirClick(Sender: TObject);
    procedure popExitClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure sbAproposClick(Sender: TObject);
  private
    { Déclarations privées }
    hIconOn : THandle;
    hIconOff : THandle;
    nid : TNotifyIconData;
    OnlyHide : Boolean;
    bOkWnd : Boolean;
    procedure WMQueryEndSession(var Msg : TWMQueryEndSession); message WM_QueryEndSession;
    procedure WMEndSession(var Msg : TWMEndSession); message WM_EndSession;
    procedure WMCallBackMessage(Var msg : TMessage); message WM_CallBackMessage;

  public
    { Déclarations publiques }
    procedure RefreshTitre;
    procedure ChangeIcon(Etat : Boolean);
    procedure User (var msg: TMessage); message wm_User;
  end;

var
  frmPrg: TfrmPrg;

implementation

uses
  About,
  u_Global;

{$R *.DFM}

procedure TfrmPrg.User(var msg: TMessage);
Begin
  Application.Restore;
End;

procedure TfrmPrg.WMQueryEndSession(var Msg : TWMQueryEndSession);
begin
  // On signale a Windows qu'on accepte la fermeture des programmes
  if MessageDlg('Windows désire se fermer, acceptez-vous ?',
                 mtConfirmation,
                 [mbYes,mbNo], 0) = mrNo then
     Msg.Result := 0
       else
     Msg.Result := 1 ;
  bOkWnd := (Msg.Result = 1)
end;

procedure TfrmPrg.WMEndSession(var Msg : TWMEndSession);
begin
  // maintenant, avec notre accord, il faut libérer
  if bOkWnd then popExitClick(Self);
end;

// si c'est un clique droit de la souris, alors on montre le popup menu
procedure ShowPopupMenu(f : TForm; p : TPopupMenu);
var
  pt : TPoint;
begin
  GetCursorPos(pt);
  SetForegroundWindow(f.handle);
  p.Popup(pt.x, pt.y);
end;

// Si c'est un double click alors on montre l'application Tray Icon
procedure ShowApplication(f : TForm);
begin
  f.visible:=true;
end;

procedure TfrmPrg.WMCallBackMessage(var msg : TMessage);
begin
  case msg.lParam of
    Wm_RButtonDown : ShowPopupMenu(self, PopMenu);
    Wm_LButtonDblClk : ShowApplication(self);
    Wm_LButtonDown : ;
    Wm_MouseMove : ;
  end;
end;

procedure TfrmPrg.popAboutClick(Sender: TObject);
begin
  AboutBox.ShowModal;
end;

procedure TfrmPrg.popOuvrirClick(Sender: TObject);
begin
  ShowApplication(self);
  ChangeIcon(True);
end;

procedure TfrmPrg.popExitClick(Sender: TObject);
begin
  // pour décharger le Tray Icon alors on supprime sa référence
  // puis on positionne la variable OnlyHide à false pour libérer la
  // mémoire associée à la fiche lors de la fermeture de la fiche
  Shell_NotifyIcon(NIM_DELETE,@nid);
  OnlyHide := False;
  Close;
end;

procedure TfrmPrg.FormCreate(Sender: TObject);
begin
  // Extraction des icones
  hIconOn := ExtractIcon(Handle, 'dcResid.exe',ICONON);
  hIconOff := ExtractIcon(Handle, 'dcResid.exe',ICONOFF);

  // Lorsqu'on demande de fermer la fenêtre du Tray Icon, celle-ci est
  // simplement cachée
  OnlyHide := True;

  // Lecture des infos programme
  ProgrammeInfo;
  RefreshTitre;

  // on initialise la structure TNotifyIconData
  with nid do begin
    cbSize:=sizeof(nid);                       // taille de la structure
    wnd:=handle;                               // fenêtre du Tray Icon
    uID:=1;
    uCallBackMessage:=wm_CallBackMessage;      // message envoyé par le système
    hIcon:=hIconOn;                            // l'îcône du Tray Icon
    szTip:=ProgName;                           // Message d'aide
    uFlags:=nif_message or nif_Icon or nif_tip;// Indique que notre Tray Icon
                                               // reçoit un message,
                                               // a une icône et un conseil
  end;
  // enregistre le Tray Icon
  Shell_NotifyIcon(NIM_ADD, @nid);

  // cache l'application
  ShowWindow(Application.Handle, SW_HIDE);
end;

procedure TfrmPrg.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  // Si le tray Icon doit uniquement être caché, alors on cache la fenêtre
  // sans libérer sa mémoire
  if OnlyHide then
    begin
      Action := caNone;
      Visible := false;
      ChangeIcon(False);
    end;
end;

procedure TfrmPrg.ChangeIcon(Etat : Boolean);
begin
  If Etat then
    nid.hIcon := hIconOn
    else
    nid.hIcon := hIconOff;
  Shell_NotifyIcon(NIM_MODIFY, @nid);
end;

procedure TfrmPrg.RefreshTitre;
begin
  frmPrg.caption := Format(Titre,[pInfo.InternalName, pInfo.FileVersion]);
end;

procedure TfrmPrg.sbAproposClick(Sender: TObject);
begin
  AboutBox.ShowModal;
end;

end.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
12
Date d'inscription
mardi 21 janvier 2003
Statut
Membre
Dernière intervention
11 novembre 2010

bonsoir , super, c'est bien ce que je pensais mais en fait je me demandais comment le programme recevais le message de windows et j'ai lu un autre article sur le sujet qui l'a expliqué. Et ton programe en fait est plus complet et décrit aussi ce qu'il convient de faire pour que le programme se ferme correctement selon son comportement.
Merci en tout cas pour ta réponse, j'ai vais mettre cela en musique dans mon programme et je vous feraiun petit retour pour vous dire ce que j'en pense
Merci encore.
Nakos91
Messages postés
17
Date d'inscription
mardi 6 avril 2004
Statut
Membre
Dernière intervention
4 novembre 2018

Bonjour NAKOS91.
Quand WINDOWS se ferme il envoi a tous les programmes ouverts 2 requêtes:
D'abord 'WMQueryEndSession' qui vous permet de décider de l'avenir de votre programme.
Suivi de 'WMEndSession' qui vous permet d'agir sur votre programme.
C'est ce que démontre ce programme et dont la trame a l'air de répondre à votre souhait.
Messages postés
12
Date d'inscription
mardi 21 janvier 2003
Statut
Membre
Dernière intervention
11 novembre 2010

Bonsoir
je suis à la recherche d'un exemple pour comprendre comment mon programme peut savoir si Windows se ferme ou que la session se ferme afin de fermer mon programme correctement. j'ai du mal à comprendre si ton programme correspond à ce que je recherche. j'ai un programme resodent qui lance un batch toute les 10 secondes et quand je ferme la session ou windows cela provoque une erreur sur le CMD en cours du batch.Je souhaite donc pouvoir arrêter mon programme proprement par la détection de la fermature de windows.

Merci de votre aide
Nakos91
Messages postés
17
Date d'inscription
mardi 6 avril 2004
Statut
Membre
Dernière intervention
4 novembre 2018

Bonjour,
Si tu n'utilise pas WMQueryEndSession n'importe quelle application demandant la fermeture de Windows fermera ton application. Moi, je n'y tiens pas.
Si tu ne ferme pas ta pop sur WMEndSession je doute que Windows se ferme.
Tu peux faire des essais. Y a pas de risques!
Messages postés
9
Date d'inscription
dimanche 13 janvier 2008
Statut
Membre
Dernière intervention
6 octobre 2014

Bonjour,
Es qu’il est indispensable d’utiliser les deux fonctions WM_QueryEndSession et WM_EndSession.
Afficher les 10 commentaires

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.