Bonjour à tous,
Dans le cadre de mon application, j'utilise un hook souris afin de détecter une activité (ou plutôt l'inactivité) du système. Le problème est, qu'une fois l'application lancée, la souris ne répond plus et je suis obligé de redémarrer le système.
C'est le premier hook que je code, je suppose qu'une fois le message intercepté par le hook, je ne le renvoie pas correctement pour qu'il soit traité normalement.
Voici le code de ma DLL inspirée par quelques bouts de codes trouvés sur le net. J'ai ajouté un hook clavier juste pour le test.
Voici le fichier d'entête de mon code source:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 #include <windows.h> #include <VCL.h> // Définition de la structure de la zone mémoire partagée typedef struct _TDonnees { HHOOK MouseHookHandle; // Handle du hook de la souris HHOOK KeybdHookHandle; // Handle du hook du clavier HWND hDestWindow; // Handle de la fenêtre à laquelle le hook du clavier doit les données // Mettez ici toutes les données que vous voulez partager } TDonnees; // Déclaration des variables globales de la DLL HANDLE MemPartagee; // Handle de la zone de mémoire partagée TDonnees * VueDonnees; // Pointeur vers la zone de mémoire HINSTANCE HInst; // Handle d'intance de la DLL // Déclaration des fonctions de la DLL extern "C" __stdcall void _export InitHook(HWND hDest); extern "C" __stdcall void _export EndHook(); LRESULT CALLBACK _export MouseProc(int nCode,WPARAM wParam,LPARAM lParam); LRESULT CALLBACK _export KeybdProc(int nCode,WPARAM wParam,LPARAM lParam); // fonction d'initialisation de la DLL int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) { HInst = hinst; switch (reason) { case DLL_PROCESS_ATTACH : // à la création de l'instance de la DLL // Attachement d'une zone de mémoire partagée (notez le cast) MemPartagee = CreateFileMapping((HANDLE)0xFFFFFFFF, // On map un espace mémoire NULL, // Pas d'informations de sécurité PAGE_READWRITE, // Partage en lecture/écriture 0, // Taille de la zone réservée sur 64 bits (32 bits de poid fort) sizeof(TDonnees), // 32 bits de poids faible "Tutoriel Hooks par gRRosminet"); // Nom de la zone réservée // Création d'une vue pour pouvoir accéder à la zone de mémoire partagée (notez le cast) VueDonnees = (TDonnees *)(MapViewOfFile((HANDLE)MemPartagee, // Zone sur laquelle créer la vue FILE_MAP_WRITE, // Mode d'accès en lecture/écriture 0, 0, // Offset de début de la vue sur 64 bits 0)); // Taille de la vue (0 = tout) break; case DLL_PROCESS_DETACH : // au détachement de la DLL // Destruction de la vue sur la zone de mémoire partagée UnmapViewOfFile((LPVOID)VueDonnees); // Détachement de la zone de mémoire partagée CloseHandle(MemPartagee); break; default : // DLL_THREAD_ATTACH, DLL_THREAD_DETACH break; } return 1; } void __stdcall _export InitHook(HWND hDest) // _export est spécifique à BCB { // Installation du hook sur la souris VueDonnees->MouseHookHandle = SetWindowsHookEx(WH_MOUSE, // Créer un hook sur la souris (HOOKPROC)MouseProc, // Utiliser la fonction MouseProc HInst, // Dans la DLL d'instance HInst 0); // Pour tous les threads // Installation du hook pour le clavier VueDonnees->MouseHookHandle = SetWindowsHookEx(WH_KEYBOARD, // Créer un hook sur le clavier (HOOKPROC)KeybdProc, // Utiliser la fonction KeybdProc HInst, // Dans la DLL d'instance HInst 0); // Pour tous les threads // Partage de la fenêtre destinatrice des données du clavier VueDonnees->hDestWindow = hDest; } void __stdcall _export EndHook() { // Supression des hooks UnhookWindowsHookEx(VueDonnees->MouseHookHandle); UnhookWindowsHookEx(VueDonnees->KeybdHookHandle); } #define WMAP_MOUSEHOOKMSG WM_APP + 2 LRESULT CALLBACK _export MouseProc(int nCode,WPARAM wParam,LPARAM lParam) { // On envoie un message WMAP_MOUSEHOOKMSG à chaque fois que // l'utilisateur presse sur la souris (bouton gauche) if(nCode < 0) return CallNextHookEx(VueDonnees->MouseHookHandle,nCode,wParam,lParam); else { if (wParam == WM_LBUTTONDOWN) { PostMessage(VueDonnees->hDestWindow, WMAP_MOUSEHOOKMSG, 0, 0); } } } #define WMAP_KEYBDHOOKMSG WM_APP + 1 LRESULT CALLBACK _export KeybdProc(int nCode,WPARAM wParam,LPARAM lParam) { // On envoie un message WMAP_KEYBDHOOKMSG à chaque fois que // l'utilisateur presse la touche ENTREE if(nCode < 0) return CallNextHookEx(VueDonnees->KeybdHookHandle,nCode,wParam,lParam); else { if (wParam == VK_RETURN) { PostMessage(VueDonnees->hDestWindow, WMAP_KEYBDHOOKMSG, 0, 0); } } }
et finalement le fichier source où se trouvent les fonctions appelées par les deux hooks (clavier et souris).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 #ifndef MainFormH #define MainFormH //--------------------------------------------------------------------------- #include "Windows.h" #include <string> #include <fstream> #include <iostream> #include <dbt.h> // used for the windows message function //-------------------------------------------------------------------------- typedef void (__stdcall *TInitFunc)(HWND); // déclarations des fonctions pour les hooks typedef void (__stdcall *TEndFunc)(); #define WMAP_MOUSEHOOKMSG WM_APP + 2 //used for the hook #define WMAP_KEYBDHOOKMSG WM_APP + 1 //used for the hook class TForm_Main : public TForm { private: // User declarations // Variables bool bHook; // Les hooks ont-ils été initialisés ? int nbEntree; // compteur de pressions pour le gestionnaire de messages int nbSouris // compteur de clics pour le gestionnaire de messages HINSTANCE hinstDLL; // instance de la DLL public: // Functions __fastcall TForm_Main(TComponent* Owner); __fastcall ~TForm_Main(); TInitFunc InitHooks; // fonction d'initialisation des hooks TEndFunc EndHooks; // fonction de suppression des hooks // fonction appelée par le message WMAP_MOUSEHOOKMSG (clic gauche) void __fastcall TForm_Main::MouseDetection(TWMNoParams &p); // fonction appelée par le message WMAP_KEYBDHOOKMSG (pression touche "entrée" void __fastcall TForm_Main::PressionEntree(TWMNoParams &p); BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(WMAP_KEYBDHOOKMSG, TWMNoParams, PressionEntree) VCL_MESSAGE_HANDLER(WMAP_MOUSEHOOKMSG, TWMNoParams, MouseDetection) END_MESSAGE_MAP(TForm) // Variables // Functions }; //--------------------------------------------------------------------------- extern PACKAGE TForm_Main *Form_Main; //--------------------------------------------------------------------------- #endif
La DLL est bien chargée, les fonctions MouseDetection et PressionEntree sont bien appelées, mais la souris ne marche plus du tout, comme si le hook ne renvoyait pas le message du clic. La fonction PressioEntree fonctionne bien mais ne renvoie pas non plus l'information (le programme détecte une pression, mais une entrée dans un objet TEdit ne fait pas de saut à la ligne par exemple)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 #include <vcl.h> #pragma hdrstop #include "MainForm.h" #include <mmsystem.h> //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm_Main *Form_Main; void __fastcall TForm_Main::PressionEntree(TWMNoParams &p) { nbEntree++; // On a reçu un message du hook : on incrémente et on affiche le compteur LHookKeyboard->Caption = "Pressions de ENTREE : " + IntToStr(nbEntree); } void __fastcall TForm_Main::MouseDetection(TWMNoParams &p) { nbSouris++; // On a reçu un message du hook : on incrémente et on affiche le compteur LHookSouris->Caption = "Pressions de Souris: " + IntToStr(nbSouris); } //--------------------------------------------------------------------------- __fastcall TForm_Main::TForm_Main(TComponent* Owner) : TForm(Owner) { // Hooks souris et clavier hinstDLL = LoadLibrary("HookDLL.dll"); // Chargement de la librairie if (!hinstDLL) // Erreur lors du chargement de la librairie ? { ErrorManagement("Erreur dans le chargement de la DLL"); Application->Terminate(); } else { // On récupère les adresses des fonctions InitHooks = (TInitFunc)GetProcAddress(hinstDLL, "InitHook"); EndHooks = (TEndFunc)GetProcAddress(hinstDLL, "EndHook"); } InitHooks(Form_Main->Handle); // On initialise les hooks nbEntree = 0; nbSouris = 0; } __fastcall TForm_Main::~TForm_Main() { // end hooks EndHooks(); }
Je patauge un peu dans le yahourt ces derniers jours, j'espère que l'un de vous pourra me donner quelques conseils ou même me trouver une solution!
Merci d'avance et bonne journée (ensoleillée je l'espère!)
Frédéric
Partager