1. Introduction▲
Ce tutoriel a pour objectif de montrer comment élaborer une application fonctionnant sous Windows qui permet à l'utilisateur d'un PC de masquer son écran temporairement en mettant en œuvre en quelque sorte un écran de confidentialité numérique.
Dans la solution proposée, la mise en place comme le retrait du masque se fait seulement par la combinaison de deux touches autres que celles réservées à Windows telles que le verrouillage de la session (Windows + L) qui, lui, demande ensuite la saisie du mot de passe (théoriquement assez long et complexe) pour la réouverture.
Quant aux pratiques telles qu'éteindre l'écran ou bien le rabattre si c'est un PC portable, elles sont à proscrire. Elles n'apportent qu'une très faible sécurité et si trop pratiquées peuvent s'avérer délétères pour le matériel.
Ce masquage numérique convient uniquement pour les absences de très courte durée de l'utilisateur face à son écran tout en demeurant non loin de celui-ci.
Même si quelques mesures de sécurisation sont mises en œuvre, il n'est en rien aussi sécurisé et comparable à un système grâce auquel l'utilisateur déverrouille sa session en présentant sa carte à puce sur un lecteur tout en n'ayant pas d'identifiant et de mot de passe à saisir.
2. L'application▲
Pour savoir si l'application est active, il est nécessaire d'avoir une icône qui viendra se loger dans la zone de notification.
Dans les paramètres de Windows, Il faudra d'ailleurs sélectionner l'icône de l'application parmi celles à afficher dans la barre des tâches au niveau de la zone de notification.
|
|
|
|
3. Les composants et leurs propriétés▲
Deux formes sont nécessaires.
|
La forme principale |
|
La forme masque de confidentialité |
|
Composants |
Propriétés |
|
TForm (forme principale) |
Caption : LazConf |
|
TTrayIcon |
Hint : Ecran de confidentialité |
|
TPopupMenu |
Items : → Name : Gestion |
|
TTimer |
Enable : True |
|
TForm (Forme masque de confidentialité) |
Caption : Ecran de confidentialité |
TrIco le composant TTrayIcon
se trouve dans l'onglet Additional de la palette de composants de Lazarus. Il est utilisé pour l'affichage de l'icône dans la zone de notification et montrer que l'application est active. De plus, quand l'utilisateur pointera avec la souris l'icône, « Écran de confidentialité » s'affichera dans une bulle d'information.
PopMen le composant TPopupMenu
dans l'onglet Standard de la palette de composants de Lazarus permet d'associer un menu contextuel à l'icône de l'application dans la zone de notification. Il s'affiche suite à un clic droit sur l'icône.
|
|
Lors de la conception, pour saisir les items du menu, il faut double-cliquer sur le composant TPopupMenu. Dans l'événement OnClick de chacun des items, vous pourrez saisir le code respectif pour mettre en œuvre l'écran de confidentialité et pour quitter l'application.
Quant à TtIdle le composant TTimer
, il est dans l'onglet System de la palette de composants de Lazarus. Il est utilisé pour verrouiller la session Windows de l'utilisateur après le temps qui sera déterminé dans le code de l'application.
4. Le code▲
Lors de la compilation et/ou l'utilisation de l'application, votre antivirus peut la bloquer. Si tel est le cas, il faut le paramétrer de sorte qu'il en autorise l'exécution.
4-1. Au niveau de l'unité main▲
Les clauses uses :
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, Menus, Windows, Messages, LCLType;Pour apporter un peu de sécurité en complexifiant la levée de l'écran de confidentialité, on s'appuie sur un hook clavier qui interceptera certaines touches « sensibles » utilisées au clavier lorsque l'écran de confidentialité sera actif. Il faut commencer par paramétrer le hook dans l'unité au niveau de type :
type
// Définition de ULONG_PTR pour compatibilité avec certaines versions ou plateformes
{$ifndef ULONG_PTR}
ULONG_PTR = PtrUInt;
{$endif}
// Structure utilisée pour intercepter les événements clavier via WH_KEYBOARD_LL
PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT;
TKBDLLHOOKSTRUCT = record
vkCode: DWORD; // Code virtuel de la touche pressée
scanCode: DWORD; // Code physique de la touche
flags: DWORD; // Informations diverses sur l'événement
time: DWORD; // Timestamp de l’événement
dwExtraInfo: ULONG_PTR; // Informations supplémentaires
end;Tout d'abord, déclarez les procédures qui servent à recevoir les messages système liés aux raccourcis clavier globaux, afficher l’écran de confidentialité et le cacher. Quant à la fonction GetIdleTime, elle permet d'obtenir le temps d'inactivité en millisecondes de l'utilisateur.
private
function GetIdleTime: DWORD;
procedure WMHotKey(var Msg: TMessage); message WM_HOTKEY;
procedure ShowPrivacyScreen;
procedure HidePrivacyScreen;
procedure CheckPrivacyWindow(Sender: TObject);
procedure CheckIdleAndLogoff(Sender: TObject);Des identifiants sont nécessaires pour différencier les raccourcis clavier. Déclarez-en les constantes sous public :
public
const
HOTKEY_ID_SHOW = 1;
HOTKEY_ID_HIDE = 2;
WH_KEYBOARD_LL = 13;
VK_TAB = 9;Afin de lier la forme principale F_Conf à la forme de l'écran de confidentialité F_Priv, inscrivez l'unité priv dans les clauses uses dans la partie implementation :
{$R *.lfm}
{ TF_Conf }
uses
priv;Sous ces clauses uses, il faut déclarer la structure utilisée par l'API (Application programming interface) Windows pour obtenir le temps de la dernière entrée utilisateur.
// Déclaration de la structure utilisée par l'API Windows pour obtenir le temps de la dernière entrée utilisateur
type
TLastInputInfo = record
cbSize: UINT; // Taille de la structure (doit être initialisée avant appel)
dwTime: DWORD; // Nombre de millisecondes depuis le démarrage du système où la dernière entrée utilisateur a eu lieu
end;Déclarez ensuite les variables :
var
HookHandle: HHOOK = 0;
IsPrivacyActive: Boolean = False;Puis il faut assurer la liaison avec les fonctions API de Windows suivantes.
- Pour avoir le moment de la dernière activité utilisateur :
// Liaison avec la fonction Windows API GetLastInputInfo (déclarée dans user32.dll)
// Obtention du moment de la dernière activité (clavier/souris) de l'utilisateur
function GetLastInputInfo(var plii: TLastInputInfo): BOOL; stdcall; external 'user32.dll';- Pour le verrouillage de la session Windows de l'utilisateur :
// Liaison avec la fonction Windows API LockWorkStation (déclarée dans user32.dll)
// Verrouillage de la session utilisateur en cours (affiche l'écran de verrouillage de Windows)
function LockWorkStation: BOOL; stdcall; external 'user32.dll';En sollicitant la fonction GetLastInputInfo vue précédemment, la fonction GetIdleTime permet d'obtenir le temps d'inactivité de l'utilisateur.
// Obtention du temps d'inactivité en millisecondes
function TF_Conf.GetIdleTime: DWORD;
var
lii: TLastInputInfo;
begin
lii.cbSize := SizeOf(TLastInputInfo); // Initialisation obligatoire de la taille
if GetLastInputInfo(lii) then
Result := GetTickCount - lii.dwTime
else
Result := 0;
end;Afin de sécuriser un peu l'application, la fonction LowLevelKeyboardProc permet d'intercepter les frappes de touches dites « sensibles » déterminées dans le code :
// Fonction hook clavier bas niveau pour intercepter les frappes de touches
function LowLevelKeyboardProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
KBDStruct: PKBDLLHOOKSTRUCT;
begin
if nCode = HC_ACTION then
begin
KBDStruct := PKBDLLHOOKSTRUCT(lParam);
// Interception seulement des appuis de touches
if (wParam = WM_KEYDOWN) or (wParam = WM_SYSKEYDOWN) then
// Si l'écran de confidentialité est actif, les touches sensibles choisies sont bloquées
begin
if IsPrivacyActive and (KBDStruct^.vkCode in [VK_TAB, VK_MENU, VK_CONTROL, VK_ESCAPE, VK_F4, VK_LWIN, VK_RWIN, VK_DELETE, VK_SHIFT, Ord('D'), Ord('M')]) then
begin
Exit(1); // Bloque l’événement clavier
end;
end;
end;
// Propagation de l’événement aux autres hooks si non bloqué
Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
end;La combinaison de touches Alt + Ctrl + Suppr ne peut ni être interceptée ni bloquée par l'application. Cette combinaison est gérée par le système d'exploitation à un niveau privilégié appelé kernel mode. Elle invoque le Secure Attention Sequence (SAS), que seul Windows peut intercepter. Microsoft empêche toute application non système de bloquer ou modifier ce comportement pour éviter les malwares qui tenteraient de cacher leur activité.
Lors de la création de F_Conf les raccourcis claviers que sont les combinaisons de touches AltGr + C pour afficher l'écran de confidentialité et AltGr + V pour le retirer sont enregistrés. C'est également par le biais de cette procédure que le hook clavier est installé.
procedure TF_Conf.FormCreate(Sender: TObject);
begin
// Enregistrement de AltGr + C pour cacher donc pour afficher l’écran de confidentialité
RegisterHotKey(Handle, HOTKEY_ID_SHOW, MOD_CONTROL or MOD_ALT, Ord('C')); // AltGr + C
// Enregistrement de AltGr + V pour voir donc pour cacher l’écran de confidentialité
RegisterHotKey(Handle, HOTKEY_ID_HIDE, MOD_CONTROL or MOD_ALT, Ord('V')); // AltGr + V
// Installation du hook clavier global
HookHandle := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, hInstance, 0);
// Initialisation du timer de vérification d'inactivité
Ttidle := TTimer.Create(Self);
Ttidle.Interval := 1000; // Vérifie toutes les 1 secondes
Ttidle.OnTimer := @CheckIdleAndLogoff;
Ttidle.Enabled := True;
end;Maintenant, il faut renseigner les procédures déclarées précédemment :
- La procédure de gestion des messages système liés aux raccourcis clavier enregistrés dans la procédure précédente :
procedure TF_Conf.WMHotKey(var Msg: TMessage); // Gestion des raccourcis clavier système reçus
begin
case Msg.WParam of
HOTKEY_ID_SHOW: ShowPrivacyScreen; // Si AltGr + C, Active l’écran de confidentialité
HOTKEY_ID_HIDE: HidePrivacyScreen; // Si AltGr + V, Désactive l’écran de confidentialité
end;
end;- La procédure pour afficher l'écran de confidentialité :
procedure TF_Conf.ShowPrivacyScreen; // Affichage de l'écran de confidentialité
begin
if not F_Priv.Visible then
begin
F_Priv.Show;
F_Priv.BringToFront;
IsPrivacyActive := True;
end;
end;- La procédure pour retirer l'écran de confidentialité :
procedure TF_Conf.HidePrivacyScreen; // Masquage de l'écran de confidentialité
begin
if F_Priv.Visible then
begin
F_Priv.Hide;
IsPrivacyActive := False;
end;
end;- La procédure de surveillance assure que l'écran de confidentialité remplit pleinement sa fonction tant qu'il est actif :
procedure TF_Conf.CheckPrivacyWindow(Sender: TObject); // Surveillance de l'écran de confidentialité
begin
// Restauration de la fenêtre de l'écran de confidentialité si réduite
if F_Priv.Visible and IsIconic(F_Priv.Handle) then
ShowWindow(F_Priv.Handle, SW_RESTORE);
// Forçage de la fenêtre de l'écran de confidentialité à rester au premier plan et en plein écran
if F_Priv.Visible then
SetWindowPos(F_Priv.Handle, HWND_TOPMOST, 0, 0, Screen.Width, Screen.Height, SWP_SHOWWINDOW);
end;-
La surveillance de l'écran de confidentialité est lancée au niveau du TTimer :
SélectionnezprocedureTF_Conf.TtIdleTimer(Sender: TObject);// Lancement de la surveillance de l'écran de confidentialitébeginCheckPrivacyWindow(Self);end; - En sollicitant la fonction LockWorkStation, la procédure CheckIdleAndLogoff verrouille la session Windows de l'utilisateur :
procedure TF_Conf.CheckIdleAndLogoff(Sender: TObject); // Verrouillage session après temps déterminé
const
TIMEOUT = 10 * 60 * 1000; // 10 minutes en millisecondes
begin
if IsPrivacyActive and (GetIdleTime >= TIMEOUT) then
begin
Ttidle.Enabled := False; // Stopper le timer pour éviter plusieurs appels
//ExitWindowsEx(EWX_LOGOFF, 0);
LockWorkStation;
end;
end;Grâce à la procédure suivante, l'utilisateur par un simple double clic sur l'icône de l'application dans la zone de notification peut activer l'écran de confidentialité.
procedure TF_Conf.TrIcoDblClick(Sender: TObject); // Affichage de l'écran de confidentialité sur double clic icône
begin
ShowPrivacyScreen; // Active l’écran de confidentialité
end;Un clic droit sur l’icône permet d'ouvrir le menu contextuel.
- Un clic sur Mettre l'écran lance l'écran de confidentialité :
procedure TF_Conf.EcranOnClick(Sender: TObject); // Affichage de l'écran de confidentialité par le menu contextuel
begin
ShowPrivacyScreen;
end;- Un clic sur Quitter ferme l'application :
procedure TF_Conf.EcranOffClick(Sender: TObject); // Fermeture de l'application par le menu contextuel
begin
if MessageDlg ('Ecran de confidentialité', 'Souhaitez-vous quitter l''application ?', mtConfirmation,[mbYes, mbNo],0) = mrYes then
Application.Terminate;
end;Avant la fermeture de l'application, un message de confirmation demande à l'utilisateur s'il le veut.
|
|
À la fermeture de l'application les raccourcis claviers sont libérés afin que les touches reprennent leurs fonctions initiales et le hook clavier est supprimé.
procedure TF_Conf.FormDestroy(Sender: TObject);
begin
// Libération des raccourcis clavier lors de la fermeture de l'application
UnregisterHotKey(Handle, HOTKEY_ID_SHOW);
UnregisterHotKey(Handle, HOTKEY_ID_HIDE);
// Suppression du hook clavier s’il est actif
if HookHandle <> 0 then
UnhookWindowsHookEx(HookHandle);
end;Maintenant, passons à la forme F_Priv et l'unité priv.
4-2. Au niveau de l'unité priv▲
Les clauses uses :
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Windows;Vous devez déclarer la procédure qui interdit la minimisation de l'écran de confidentialité.
private
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;La procédure est celle-ci :
procedure TF_Priv.WMSysCommand(var Msg: TWMSysCommand); // Empêche la minimisation
begin
if Msg.CmdType = SC_MINIMIZE then
Msg.Result := 1
else
inherited;
end;La création de l'écran de confidentialité :
procedure TF_Priv.FormCreate(Sender: TObject); // Configure la fenêtre en écran de confidentialité noir plein écran
begin
BorderStyle := bsNone; // Pas de bordure
FormStyle := fsStayOnTop; // Toujours au-dessus
WindowState := wsFullScreen; // Plein écran
Color := clBlack; // Couleur noir
Screen.Cursor := crNone; // Curseur invisible
end;L'écran de confidentialité à partir de F_Priv est noir, conçu sans bordure et occupe tout l'écran de l'ordinateur quand il est mis en œuvre. Le curseur n'est pas visible.
La procédure suivante interdit une tentative éventuelle de fermeture manuelle de l'écran de confidentialité.
procedure TF_Priv.FormCloseQuery(Sender: TObject; var CanClose: Boolean); // Empêche la fermeture manuelle
begin
CanClose := False;
end;4-3. Masquer la forme au démarrage de l'application▲
Au démarrage, il est nécessaire que la forme de l'application reste invisible pour l'utilisateur de l'ordinateur. Il faut alors l'inscrire au niveau du code source :
begin
RequireDerivedFormResource:=True;
Application.Scaled:=True;
{$PUSH}{$WARN 5044 OFF}
Application.MainFormOnTaskbar:=True;
{$POP}
Application.Initialize;
Application.CreateForm(TF_Conf, F_Conf);
Application.CreateForm(TF_Priv, F_Priv);
Application.ShowMainForm := False; // Ne montre pas le forme principale
Application.Run;
end.5. Pour le déploiement▲
Pour un peu plus de facilité de déploiement, il est préférable de déposer l'application sur C :.
Si l'administrateur doit installer l'application pour un utilisateur du PC, le raccourci de l'application doit être déposé ici :
- C:\Users\Nom de session de l'utilisateur\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Pour l'ensemble des utilisateurs du PC, l'administrateur dépose le raccourci de l'application ici :
- C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
Ainsi l'application est lancée au démarrage et de manière transparente pour l'utilisateur.
Pensez à faire apparaître l'icône de l'application dans la zone de notification.
6. Conclusion▲
Parvenu au terme de ce tutoriel, vous voilà prêt à proposer une solution simple d'utilisation afin que les utilisateurs préservent la confidentialité des données qu'ils traitent pendant le court instant durant lequel ils doivent ne plus être face à leur écran pour accomplir une tâche.
Pour activer l'écran de confidentialité : AltGr + C ou double-clic sur l'icône de l'application dans la zone de notification. C'est aussi possible de le faire en un clic droit sur l'icône et un clic sur Mettre l'écran dans le menu qui s'affiche.
Pour désactiver l'écran de confidentailité : AltGr + V.
Pour fermer l'application, clic droit sur l'icône et un clic sur Quitter dans le menu affiché.
L'application développée dans ce tutoriel peut être utile pour les utilisateurs de PC désirant que leur écran ne soit pas lisible lors de leurs absences de très faible durée devant leur écran. La mise en place de l'écran de confidentialité protège des regards indiscrets qui pourraient se porter sur un document qui resterait ouvert alors que l'utilisateur serait occupé à proximité à réaliser une tâche de très courte durée.
Même si cette application permet de masquer le contenu de l'écran et qu'après 10 minutes d'inactivité la session de l'utilisateur est verrouillée, elle n'apporte pas suffisamment de sécurité pour permettre à celui-ci de rester éloigné de son PC alors que sa session (normalement protégée par identifiant – mot de passe) est ouverte.
Cette application peut sûrement être améliorée, adaptée à des contextes particuliers, aussi je vous encourage et vous remercie de partager vos versions retouchées de celle-ci.
7. Remerciements▲
Je remercie Alcatîz pour sa relecture technique. Cette relecture nous permet de développer des applications dans le respect des bonnes pratiques notamment d'optimisation du code.
Je remercie ALT pour sa relecture orthographique. Quant à cette relecture, elle a l'avantage de proposer des tutoriels sans fautes, plus agréables à lire et à suivre.








