Réalisation d'un écran de veille avec Delphi
Date de publication : 23/09/2004
Par
Bruno Guérangé (nono40.developpez.com)
Cet article présente la méthode pour la réalisation d'un écran de veille simple avec Delphi.
I. Principe
I-A. Ecran de veille, simple exécutable
I-B. Affichage normal de l'écran de veille
I-C. Configuration de l'écran de veille
I-D. Prévisualisation de l'écran de veille
I-E. Modification du mot de passe
I-F. Signaler au système qu'il est en veille
I-G. Application mono-instance, quoi-que...
II. Réalisation
II-A. Données globales
II-B. Fenêtre de visualisation de l'écran de veille
II-C. Modification du source du projet
II-D. Ajout d'une fenêtre de configuration
II-E. Gestion du mot de passe
III. Conclusion
I. Principe
I-A. Ecran de veille, simple exécutable
Un écran de veille pour Windows est en fait un simple exécutable dont l'extension .EXE est renommée en .SCR.
Bien sur afin que celui-ci fonctionne comme un écran de veille il doit répondre aux demandes de windows passées en paramètres lors de son exécution.
Le détail de ces paramètres est donné dans les paragraphes suivants.
Windows passe en premier paramètre le type d'action que l'écran de veille doit réaliser, comme la visualisation, configuration, etc.
Le deuxième paramètre est optionnel et dépend du premier.
I-B. Affichage normal de l'écran de veille
Pour afficher l'écran de veille Windows lance l'application en lui passant -S, /S ou S en premier paramètre.
Le second paramètre est vide dans ce cas.
Sur la commande S il faut afficher l'écran de veille normalement, le mieux est de le faire dans une fenêtre sans bord ( bsNone ), en avant-plan ( fsStayOnTop ) et en plein écran ( wsMaximized ).
C'est à l'écran de veille de gérer la sortie quand on bouge la souris, on appuie sur une touche, etc... De même c'est à l'application de vérifier que l'écran
de veille est éventuellement protégé par un mot de passe et de demander celui-ci pour se fermer.
Si l'écran de veille est protégé par mot de passe, la clef HKEY_CURRENT_USER\\Control Panel\Desktop doit contenir une valeur ScreenSaveUsePassword non nulle.
I-C. Configuration de l'écran de veille
Pour afficher la fenêtre de configuration de l'écran de veille, Windows lance l'application avec le paramètre -C, /C ou C.
Le second paramètre est vide dans ce cas.
Sur la commande C il faut afficher la fenêtre de configuration de l'écran de veille. Les valeurs de paramétrage de l'écran de veille peuvent simplement être stockées dans un fichier INI ou dans la base de registre.
Vous pouvez prendre la methode que vous préférez. La fenêtre doit lire les infos de configuration, les afficher, et les sauvegarder si l'utilisateur valide les modifications.
Il n'y a pas de spécification particulière sur la fenêtre de configuration.
I-D. Prévisualisation de l'écran de veille
Pour prévisualiser l'écran de veille Windows lance l'application en lui passant -P, /P ou P en premier paramètre.
Le second paramètre est le Handle de la fenêtre dans laquelle doit s'afficher l'écran de veille.
 |
Attention, la prévisualisation est l'affichage dans le petit moniteur de la fenêtre des propriétés d'affichage du bureau. Le bouton "tester" de cette même fenêtre ne fait que lancer l'écran de veille normalement avec la commande S.
|
Si la fenêtre utilisée par la commande S est définie comme ci-dessus, alors il suffit d'assigner le ParentHandle de cette fenêtre avec la valeur reçue dans le deuxième paramètre.
Il ne faut pas gérer le mot de passe dans ce cas, ni la sortie par les mouvements de souris ou les évènement clavier. Windows se chargera de fermer l'écran de veille en envoyant un message WM_CLOSE à l'application. Rien ne doit donc empêcher sa fermeture en mode prévisualisation.
I-E. Modification du mot de passe
Pour modifier le mot de passe de l'écran de veille Windows lance l'application en lui passant -A, /A ou A en premier paramètre.
Le second paramètre est le Handle de la fenêtre pouvant servir de parent à la boite de dialogue de saisie du mot de passe.
Vous pouvez gérer vous-même les fenêtres de saisie de mot de passe, mais le mieux est d'utiliser celles de Windows.
Pour appeler la fenêtre de modification du mot de passe de l'écran de veille il faut utiliser la fonction PwdChangePasswordA de la librairie MPR.DLL.
Pour appeler la fenêtre de vérification du mot de passe ( pour sortir de l'écran de veille ) il faut utiliser la fonction VerifyScreenSavePwd de la librairie PASSWORD.CPL.
L'appel de ces deux fonctions sera détaillé un peu plus loin.
I-F. Signaler au système qu'il est en veille
L'écran de veille, quand il est en mode normal, ( commande S ) doit signaler au système qu'il est en veille. Pour cela
il faut utiliser la fonction SystemParametersInfo avec le paramètre SPI_SCREENSAVERRUNNING.
Au délà du fait que le système sait qu'il est en mode veille, ceci simplifie beaucoup la gestion des accès externes. En effet
en mode veille Alt-TAB, Ctrl-ESC, etc sont désactivés. Il n'y donc plus aucune gestion à faire pour bloquer le basculement de tâche quand l'écran de veille est lancé.
I-G. Application mono-instance, quoi-que...
Mais bien sur... Il y a une exception à la règle. Dans le cas de la modification du mot de passe, Windows ne ferme pas l'instance en cours de prévisualisation. Donc pour la modification du mot de passe il faut pouvoir lancer une deuxième instance de l'application.
Ceci peut ce faire facilement dans le source du projet comme nous allons le voir plus loin.
II. Réalisation
Pour présenter la réalisation des principes proposés précédemment nous allons réaliser un simple écran de veille ou une petite image rebondi sur les bords de l'écran.
C'est bien sur simpliste, mais permet de ne garder dans le code que les principes de base d'un écran de veille.
Cet écran de veille aura un seul paramètre de configuration : la vitesse de déplacement de l'image.
II-A. Données globales
Ajouter une unité au projet afin d'y stocker les variables globales et les procédures de lecture/écriture des paramètres.
Le mode de stockage sera ici un fichier INI situé là où est l'exécutable. C'est la méthode la plus simple dans ce cas.
Le source de cette unité est le suivant :
unit Declare;
interface
Type TssMode = ( ssAffiche , ssConfig , ssMotDePasse , ssPrevisu );
Var
ssMode : TssMode = ssAffiche;
Param1 : String;
Param2 : String;
DecX : Integer = 3;
DecY : Integer = 3;
optVitesse : Integer = 100;
Procedure LitIni;
Procedure EcritIni;
implementation
Uses IniFiles,SysUtils;
Procedure LitIni;
Var Ini:TInifile;
Begin
Ini:=TIniFile.Create(ExtractFilePath(ParamStr(0))+'CONFIG.INI');
Try
optVitesse := Ini.ReadInteger('ECRAN','Vitesse',optVitesse);
Finally
Ini.Free;
End;
End;
Procedure EcritIni;
Var Ini:TInifile;
Begin
Ini:=TIniFile.Create(ExtractFilePath(ParamStr(0))+'CONFIG.INI');
Try
Ini.WriteInteger('ECRAN','Vitesse',optVitesse);
Finally
Ini.Free;
End;
End;
end.
|
II-B. Fenêtre de visualisation de l'écran de veille
Ajouter une fenêtre à votre projet servant d'affichage de l'écran de veille. Sur celle-ci définissez les propriétés suivantes :
- BorderStyle : bsNone ( obligatoire )
- FormStyle : fsStayOnTop ( obligatoire )
- WindowState : wsMaximized ( obligatoire )
- Color : clBlack
Dans cette fenêtre placez en haut à gauche un TImage dont la propriété AutoSize est à True. Chargez une image de petite taille ( car elle doit rebondir aussi dans la petite fenêtre de prévisualisation ).
Placer aussi un TTimer sur la fiche pour gérer le déplacement de l'image.
Dans le code de création de la fiche, il faut lire le fichier INI et utiliser les valeurs qu'il contient.
procedure TFenEcran.FormCreate(Sender: TObject);
begin
LitIni;
Timer.Interval := optVitesse;
cursor:=crNone;
end;
|
A l'affichage de la fenêtre, on masque l'application dans la barre des tâches et on signale au système que l'écran de veille est actif.
La fonction SystemParametersInfo attend quatre paramètres :
- uiAction : Identificateur du paramètre à modifier, ici SPI_SCREENSAVERRUNNING
- uiParam : Valeur du paramètre : 1 si l'écran de veille est actif, 0 sinon
- pvParam : Pointeur vers un entier ( inutilisé dans ce cas )
- fWinIni : Mettre 1 pour modifier le fichier WinIni, dans notre cas il faut mettre 0
procedure TFenEcran.FormShow(Sender: TObject);
Var i:Integer;
begin
ShowWindow(Application.Handle,SW_HIDE);
SystemParametersInfo(SPI_SCREENSAVERRUNNING,1,@i,0);
end;
|
Le code du timer est le suivant ( c'est simpliste, je sais... )
procedure TFenEcran.TimerTimer(Sender: TObject);
begin
Image.Left := Image.Left + DecX;
Image.Top := Image.Top + DecY;
If (Image.Left + Image.Width)>=ClientWidth Then DecX := -3;
If (Image.Top + Image.Height)>=ClientHeight Then DecY := -3;
If Image.Left <= 0 Then DecX := 3;
If Image.Top <= 0 Then DecY := 3;
end;
|
L'écran de veille doit gérer les causes de sa fermeture, ici nous allons simplement gérer le click de la souris. Mais d'autres évènements peuvent facilement être ajoutés.
procedure TFenEcran.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Close;
end;
|
Lors de la fermeture de la fiche il faut dire aussi au système que l'on sort de l'écran de veille :
procedure TFenEcran.FormClose(Sender: TObject; var Action: TCloseAction);
Var i:Integer;
begin
SystemParametersInfo(SPI_SCREENSAVERRUNNING,0,@i,0);
end;
|
II-C. Modification du source du projet
La gestion des paramètres sera effectuée dans le source du projet. C'est de loin la méthode la plus simple pour gérer le nombre d'instances et la création de différentes fenêtres suivant les commandes.
A ce stade le code du projet est le suivant :
program Project1;
uses
Windows,
Forms,
SysUtils,
Declare in 'Declare.pas',
UEcran in 'UEcran.pas' ;
begin
Param1 := Copy(UpperCase(ParamStr(1)),1,2);
Param2 := UpperCase(ParamStr(2));
If (Length(Param1)>0)And Not (Param1[1] In ['A'..'Z']) Then
Param1 := Copy(Param1,2,1);
If Param1='P' Then ssMode := ssPrevisu;
If Param1='C' Then ssMode := ssConfig;
If Param1='S' Then ssMode := ssAffiche;
If Param1='A' Then ssMode := ssMotDePasse;
SetLastError(NO_ERROR);
CreateMutex (nil, False, 'MONSCREENSAVER');
if GetLastError = ERROR_ALREADY_EXISTS Then Exit;
Case ssMode Of
ssAffiche,ssPrevisu:
Begin
Application.Initialize;
Application.CreateForm(TFenEcran, FenEcran);
if ssMode=ssPrevisu Then
FenEcran.ParentWindow := StrToInt(Param2);
Application.Run;
End;
End;
end.
|
On notera l'utilisation de la directive $E afin de modifier l'extension du fichier exécutable en .SCR. Ceci est important afin que Windows le reconnaise en tant que tel.
Le début du code ne fait que lire et stocker les paramètres passés au programme.
Ensuite, la vérification de la mono-instance de l'application est effectuée.
Enfin l'écran de veille est affiché.
Vous noterez que la différence entre l'affichage normal et la prévisualisation est minime. Dans le cas de la prévisualisation
une simple affectation de ParentWindow permet à la fenêtre de l'écran de veille de se loger dans le petit moniteur. C'est pour cela
que dans le code de l'écran de veille on utilise ClientWidth/ClientHeight au lieu de Screen.Width et Screen.Height.
La fenêtre prenant d'elle-même les dimensions de la fenêtre parente ( Merci Delphi ).
A ce stade, l'écran de veille est fonctionnel. Compilez le projet, puis effectuez un clic droit dans l'explorateur afin d'installer l'écran de veille. Cette methode permet de le tester sans avoir à le copier dans le répertoire de base de Windows.
L'écran de veille doit alors apparaître en prévisualisation :
Le bouton "Aperçu" permet de le voir en plein écran, comme en veille normale.
II-D. Ajout d'une fenêtre de configuration
L'ajout d'une fenêtre de configuration est très simple.
Ajoutez une nouvelle fenêtre au projet et donnez lui l'aspect suivant :
Ajouter le code suivant dans le OnShow :
procedure TFenConfig.FormShow(Sender: TObject);
begin
LitIni;
seTimer.Value := optVitesse;
ShowWindow(Application.Handle,SW_HIDE);
end;
|
Et le code suivant sur les boutons :
procedure TFenConfig.btnAnnulerClick(Sender: TObject);
begin
Close;
end;
procedure TFenConfig.btnOKClick(Sender: TObject);
begin
optVitesse := seTimer.Value;
EcritIni;
Close;
end;
|
Il ne reste plus qu'a modifier le source du projet pour appeler la fenêtre de configuration quand Windows le demande :
Case ssMode Of
ssAffiche,ssPrevisu:
Begin
Application.Initialize;
Application.CreateForm(TFenEcran, FenEcran);
if ssMode=ssPrevisu Then
FenEcran.ParentWindow := StrToInt(Param2);
Application.Run;
End;
ssConfig:
Begin
Application.CreateForm(TFenConfig,FenConfig);
Application.Initialize;
Application.Run;
End;
End;
|
Et voila, quand vous cliquez sur le bouton "Paramètres" dans les propriétés d'affichage, votre fenêtre de configuration s'affiche.
II-E. Gestion du mot de passe
Pour ajouter la gestion du mot de passe il faut ajouter deux parties dans le code :
- Répondre à la commande A de modification du mot de passe.
- Tester le mot de passe dans l'écran de veille.
Pour modifier le mot de passe, comme énoncé plus haut nous allons utiliser les procédures de Windows. Il faut noter aussi que la demande de modification du mot de passe peut être demandée même si l'écran de veille est déjà en prévisualisation.
Il faut donc gérer la modification du mot de passe avant la gestion du nombre d'instances. Le source du projet devient :
Case ssMode Of
ssMotDePasse:Begin
MdpLib := LoadLibrary('MPR.DLL');
If MdpLib <> 0 Then
Begin
MdpFunc := GetProcAddress(MdpLib,'PwdChangePasswordA');
If Assigned(MdpFunc) Then
MdpFunc('SCRSAVE',StrToInt(Param2),0,0);
FreeLibrary(MdpLib);
End;
Exit;
End;
End;
SetLastError(NO_ERROR);
CreateMutex (nil, False, 'MONSCREENSAVER');
if GetLastError = ERROR_ALREADY_EXISTS Then Exit;
...
|
Pour gérer le mot de passe, nous allons simplement utiliser l'évènement OnCloseQuery de la fiche de visualisation :
procedure TFenEcran.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
Var Reg:TRegistry;
MdpFunc : function (Parent : THandle) : Boolean; stdcall;
MdpLib : THandle;
begin
CanClose := True;
If ssMode=ssAffiche Then
Try
Reg := TRegistry.Create;
Try
Reg.RootKey := HKEY_CURRENT_USER;
If Reg.OpenKey('Control Panel\Desktop',False) Then
If Reg.ReadInteger('ScreenSaveUsePassword') <> 0 Then
Begin
MdpLib := LoadLibrary('PASSWORD.CPL');
If MdpLib <> 0 Then
Begin
MdpFunc := GetProcAddress(MdpLib,'VerifyScreenSavePwd');
CanClose := MdpFunc(Handle);
FreeLibrary(MdpLib);
End;
End;
Finally
Reg.Free;
End;
Except
CanClose:=True;
End;
end;
|
A noter que par défaut ( erreur de lecture BDR etc... ) il ne faut pas gérer le mot de passe, sous peine d'avoir à rebooter votre PC.
Notez également que dans le cas de la prévisualisation il ne faut pas demander le mot de passe, car l'écran de veille doit se fermer dés que Windows le demande ( fermeture de la fenêtre des propriétés d'affichage ).
 |
Sous Windows XP la clef n'existe pas. La gestion du mot de passe est effectuée par Windows directement en affichant la fenêtre d'ouverture de session.
|
III. Conclusion
La gestion d'un écran de veille n'est donc pas si compliquée que ça, libre à vous maintenant de créer des écrans plus compliqués.
Ici l'écran de prévisualisation est le même que l'écran final, mais ce n'est pas obligatoirement le cas.


Copyright © 2004 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.
Cette page est déposée.