Le gestionnaire de messages Windows permet aux applications d'accéder à des flux de messages contrôlés.
Le mécanisme dit de crochet (HOOK) de c4. Il existe de nombreux types de hooks, chacun étant utilisé pour capturer un type ou une plage spécifique de messages. Tels que : les messages du clavier, les messages de la souris, etc. Nous prenons ici uniquement l'utilisation des crochets de clavier comme exemple pour expliquer comment écrire des programmes DLL sous DELPHI et comment installer et utiliser les fonctions de crochet de clavier dans vos propres programmes. Nous discutons également de la façon de partager des données lorsque différents programmes utilisent le même fichier DLL. .
1. Instructions pour écrire les fonctions de filtre à crochet
Étant donné que la fonction de filtre de crochet doit être dans un module indépendant, cela signifie que nous devons d'abord générer un framework DLL, puis y ajouter le code de fonction de crochet et d'autres codes de fonction associés. Ici, nous prenons l'écriture de la fonction de filtre de crochet du clavier comme exemple pour illustrer. Les étapes spécifiques sont les suivantes :
1. Générez d'abord un panier DLL 2
2. Écrivez votre propre fonction de filtre de crochet de clavier
La fonction de filtre de hook doit être une fonction de rappel et sa fonction a la forme suivante :
fonctionKeyHookPRoc(
iCode : Entier ;
wParam : WPARAM ;
lParam:LPARAM ): LRESULT; stdcall ;export;
Ajoutez votre propre fonction de traitement des hooks de clavier au framework DLL généré pour gérer les messages du clavier.
Le code est le suivant :…
if(iCode>=0) alors commencez
Résultat :=0 ; //Valeur de retour d'initialisation
//Ajoutez votre propre code ici
fin sinon
commencer
Résultat :=CallNextHook(hOldKeyHook,iCode,wParam,lParam);
//hOldKeyHook est la fonction de filtre de clavier d'origine enregistrée ?
fin;
3. Installez la fonction de filtre de crochet de clavier
Pour installer un hook, la fonction de filtre _fd doit appeler la fonction SetWindowsHookEx (la fonction d'installation du hook SetWindowsHook pour Windows 3.0 est désormais obsolète). Le prototype de cette fonction est le suivant :
HHOOK SetWindowsHookEx(
int idHook, // Installé ?_b3 sous-type
HOOKPROC lpfn, //Hook filter??f numéro d'adresse
HINSTANCE hMod, //Gestion de la tâche
DWord dwThreadId // Le but du hook
);
Il convient de noter que : ?_a8 doit souvent appeler la fonction MakeProcInstance pour obtenir l'adresse d'entrée du préambule d'une fonction de sortie, puis utiliser cette adresse comme deuxième paramètre lpfn de SetWindowsHookEx. Cependant, puisque Delphi fournit un « rappel intelligent », MakeProcInstance peut être omis et le nom de la fonction de filtre de hook peut être directement utilisé comme adresse d'entrée.
De cette manière, lorsque la fonction _c3GetMessage ou PeekMessage de l'application lit des messages de la file d'attente de messages ou a des messages clés (WM_KEYDOWN ou WM_KEYUP) à traiter, le système appellera la fonction de filtre de hook KeyHookProc pour traiter les messages du clavier.
4. Désinstallez la fonction de filtre à crochet.
Lorsque la fonction hook n'est plus nécessaire, UnHookWindowsHookProc doit être appelé pour désinstaller le hook installé afin de libérer les ressources système.
La liste complète des programmes est la suivante ?_ba
Crochet de clé de bibliothèque ;
utilise Windows ;
constBUFFER_SIZE=16*1024 ;
const HOOK_MEM_FILENAME='SAMPLE KEY_HOOK_MEM_FILE';
const HOOK_MUTEX_NAME = 'SAMPLE KEY_HOOK_MUTEX_NAME';
taper
TShared=enregistrement
Clés : tableau[0..BUFFER_SIZE] de Char ;
KeyCount : entier ;
fin;
PShared=^TSPartagé ;
var
MemFile, HookMutex : THandle ;
hOldKeyHook : HHook ;
ProcSaveExit : pointeur ;
Partagé : Partagé ;
//Fonction de filtre de crochet de clavier
fonction KeyHookProc(iCode : Integer ; wParam : WPARAM ; lParam : LPARAM) :LRESULT
; appel standard ;
const KeyPressMask = 8 000 000 $ ;
commencer
si iCode < 0 alors
Résultat := CallNextHookEx(hOldKeyHook, iCode, wParam, lParam)
sinon commencer
if ((lParam et KeyPressMask)= 0) then // touche enfoncée
commencer
Partagé^.Keys[Shared^.KeyCount]:=Char(wParam et $00ff);
Inc(Partagé^.KeyCount);
si Partagé^.KeyCount>=BUFFER_SIZE-1 alors Partagé^.KeyCount:=0 ;
fin;
iCode :=-1 ;
Résultat := CallNextHookEx(hOldKeyHook, iCode, wParam, lParam);
fin;
fin;
//Définit la fonction de filtre de crochet
fonction EnableKeyHook : BOOL exportation ;
commencer
Partagé^.KeyCount:=0; //Initialiser le pointeur du clavier
si hOldKeyHook=0 alors commencez
hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD,
KeyHookProc,
Par exemple,
0);
fin;
Résultat := (hOldKeyHook <> 0);
fin;
//Annuler la fonction de filtre de crochet
fonction DisableKeyHook : BOOL ; exportation ;
commencer
si hOldKeyHook<> 0 alors
commencer
UnHookWindowsHookEx(hOldKeyHook); // Décrocher le crochet du clavier
hOldKeyHook:= 0;
Partagé^.KeyCount:=0;
fin;
Résultat := (hOldKeyHook = 0);
fin;
//Obtenir le nombre de frappes dans le tampon du clavier
fonction GetKeyCount :Exportation entière ;
commencer
Résultat :=Partagé^.KeyCount ;
fin;
//Récupère les touches du tampon clavier
function GetKey(index:Integer) : Char export;
commencer
Résultat :=Partagé^.Keys[index] ;
fin;
//Effacer le tampon du clavier
procédure ClearKeyString ; exportation ;
commencer
Partagé^.KeyCount:=0;
fin;
// Processus de traitement de sortie de la DLL
procédure KeyHookExit loin ;
commencer
si hOldKeyHook <> 0 alors DisableKeyHook ;
UnMapViewOfFile(Shared); // Libère le fichier image mémoire
CloseHandle(MemFile); // Ferme le fichier image
ExitProc := ProcSaveExit;
fin;
exports // définit la fonction de sortie
ActiverKeyHook,
Désactiver KeyHook,
GetKeyCount,
ClearKeyString,
GetKey ;
commencer
//Partie d'initialisation de la DLL
HookMutex:=CreateMutex(nil,True,HOOK_MUTEX_NAME);
// Partagez la mémoire en créant un fichier image mémoire
MemFile:=OpenFileMapping(FILE_MAP_WRITE,False,
HOOK_MEM_FILENAME);
si MemFile=0 alors
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
SizeOf(TShared),HOOK_MEM_FILENAME);
Partagé :=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
ReleaseMutex(HookMutex);
CloseHandle(HookMutex);
ProcSaveExit := ExitProc; // Enregistre le ExitProc de la DLL
ExitProc := @KeyHookExit; // Définit le nouveau ExitProc de la DLL
fin.
//Fin du code source
2. Utilisez la fonction de filtre de crochet de clavier préparée dans votre propre programme.
Une fois la fonction hook compilée, elle est en fait très simple à utiliser : appelez d'abord SetWindowsHookEx pour installer votre propre fonction de filtre hook, et en même temps enregistrez l'adresse d'origine de la fonction de filtre hook. À ce stade, la fonction hook entre en jeu et gérera les messages du clavier en fonction de vos besoins. Lorsque l'exécution du programme est terminée ou qu'il n'est plus nécessaire de surveiller les messages du clavier, appelez la fonction UnHookWindowsHookProc pour désinstaller la fonction de hook installée et restaurer l'adresse de la fonction de filtre de hook d'origine.
Voici un exemple d'utilisation de la fonction hook compilée ci-dessus :
unité Unité1 ;
interface
utilise
Windows, messages, SysUtils, classes, graphiques, contrôles, formulaires, boîtes de dialogue,
StdCtrls, ExtCtrls ;
taper
TForm1 = classe(TForm)
Mémo1 : TMémo ;
Panneau 1 : TPanel ;
bSetHook : TButton ;
bCancelHook : TButton ;
bReadKeys : TButton ;
bClearKeys : TButton ;
Panneau 2 : TPanel ;
procédure bSetHookClick(Expéditeur : TObject);
procédure bCancelHookClick(Expéditeur : TObject);
procédure bReadKeysClick(Expéditeur : TObject);
procédure bClearKeysClick(Expéditeur : TObject);
fin;
var Form1 : TForm1 ;
mise en œuvre
{$R *.DFM}
fonction EnableKeyHook : BOOL ; externe 'KEYHOOK.DLL' ;
fonction DisableKeyHook : BOOL ; externe 'KEYHOOK.DLL' ;
fonction GetKeyCount : Entier ; externe 'KEYHOOK.DLL' ;
function GetKey(idx:Integer) : Char ; externe 'KEYHOOK.DLL';
procédure ClearKeyString ; externe 'KEYHOOK.DLL' ;
procédure TForm1.bSetHookClick(Sender: TObject); // Définir le crochet du clavier 7ó
commencer
ActiverKeyHook ;
bSetHook.Enabled :=False;
bCancelHook.Enabled:=True;
bReadKeys.Enabled :=True;
bClearKeys.Enabled :=True;
Panel2.Caption:='Le crochet du clavier a été défini';
fin;
procédure TForm1.bCancelHookClick(Sender: TObject); // Désinstaller le hook du clavier
commencer
DésactiverKeyHook ;
bSetHook.Enabled :=True;
bCancelHook.Enabled:=False;
bReadKeys.Enabled :=False;
bClearKeys.Enabled :=False;
Panel2.Caption:='Le crochet du clavier n'est pas défini';
fin;
procédure TForm1.bReadKeysClick(Sender: TObject); // Récupère l'historique des frappes au clavier
var i:Entier;
commencer
Memo1.Lines.Clear; // Afficher l'historique des frappes dans Memo1
pour i:=0 à GetKeyCount-1 faire
Mémo1.Text :=Mémo1.Text+GetKey(i);
fin;
procédure TForm1.bClearKeysClick(Sender: TObject); // Effacer l'historique des frappes
commencer
Mémo1.Clear ;
ClearKeyString ;
fin;
fin.
//Fin du code source
3. Implémentation de la mémoire partagée dans les DLL sous Windows95
Dans le fichier DLL où se trouve la fonction de hook ci-dessus, la mémoire partagée doit être utilisée, c'est-à-dire que tous les enregistrements de frappe sont stockés dans le même segment de données. Pourquoi faisons-nous cela ? En effet, la méthode d'appel des DLL de Windows95 est différente de celle de Windows3.X. Lorsque chaque thread se connecte à une bibliothèque de liens dynamiques, il transmet un nouveau handle d'instance (c'est-à-dire le handle du segment de données DLL) à la bibliothèque de liens dynamiques. Cela permet aux différentes instances de la DLL de ne pas interférer les unes avec les autres, mais cela entraîne certaines difficultés lorsque toutes les instances de la DLL partagent un ensemble de variables. Afin de résoudre ce problème, nous le résolvons ici en créant un fichier mappé en mémoire. Autrement dit, en utilisant OpenFileMapping, CreateFileMapping et Windows
MapViewOfFile trois fonctions à réaliser. Comment l'utiliser :
…
MemFile est un type THandle, Shared est un type pointeur et HOOK_MEM_FILENAME est une chaîne constante.
…
MemFile:=OpenFileMapping(FILE_MAP_WRITE,False,
HOOK_MEM_FILENAME); //Ouvrir le fichier mappé en mémoire
if MemFile=0 then //Si l'ouverture échoue ?_c2 Créer un fichier mappé en mémoire
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
SizeOf(TShared),HOOK_MEM_FILENAME);
//Mapper les fichiers vers des variables
Partagé :=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
Jusqu'à présent, vous savez déjà à quel point il est facile de compiler des fonctions hook dans Delphi. Enfin, je dois rappeler à tout le monde : bien que la fonction hook soit relativement puissante, si elle est mal utilisée, elle affectera sérieusement l'efficacité du système, alors essayez d'éviter d'utiliser des hooks système. Des précautions particulières doivent être prises lorsqu'il doit être utilisé, afin que cela affecte le moins possible le fonctionnement du système.
[Fin du texte intégral]