Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Répétition du clique gauche de la souris

9 réponses
Avatar
Tao
Bonsoir à tous.
En fouillant dans mon disque dur externe, j'ai retrouvé un projet que je
n'ai pas su finir (ce qui m'arrive fréquement à vrai dire). J'ai voulu m'y
remettre, en pensant que le temps écoulé m'aurait servi d'expérience. Mais
le soucis est que je n'y arrive toujours pas...
Le projet est le suivant, je voudrais pouvoir intercépter le clique gauche
de la souris et le répéter un certain nombre de fois. J'ai tenté de créer un
dll de hook avec, pour un premier temps, la touche contrôle comme
déclencheur, mais je n'y suis pas arrivé. Pourriez-vous m'aider ? Ou me
proposer une autre méthode beaucoup plus simple ?

Voici le code de ma dll :

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "main.h"

__declspec(dllexport) int lancerHook();
__declspec(dllexport) int arreterHook();

LRESULT CALLBACK fonctionTraitementHookClavier(int nCode, WPARAM wParam,
LPARAM lParam);

HINSTANCE hinstanceDLL; // handle dll
HHOOK hookClavier; // Handle hook
int repetitionClique = 1;


__declspec(dllexport) int lancerHook()
{
hookClavier = SetWindowsHookEx( WH_KEYBOARD ,
fonctionTraitementHookClavier , hinstanceDLL , 0 );

if(hookClavier == NULL)
{
return 0;
}

return 1;
}

__declspec(dllexport) int arreterHook()
{
int test1 = UnhookWindowsHookEx(hookClavier); return (test1 !=
0)?1:0;
}

LRESULT CALLBACK fonctionTraitementHookClavier(int nCode, WPARAM wParam,
LPARAM lParam)
{
POINT pt;
int i = 0;

if (nCode == HC_ACTION && wParam == VK_CONTROL)
{
while(i < 5)
{
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
Sleep(15);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
Sleep(15);
i++;
}
}

return CallNextHookEx(hookClavier,nCode,wParam,lParam);
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
{
hinstanceDLL = hinstDLL;
break;
}

case DLL_PROCESS_DETACH:
arreterHook();
break;
}
return TRUE;
}


Et le code du programme l'utilisant :

void FenPrincipale::onHook()
{
HINSTANCE hDll;
lancerHook test;

hDll = LoadLibraryA("hookRepetition.dll");
if(hDll != NULL)
{
QMessageBox::information(this, "Test", "Chargement Ok");
test = (lancerHook) GetProcAddress((HINSTANCE)hDll, "lancerHook");
test();

FreeLibrary(hDll);
}
}

(Peut être que le problème ne vient pas de la DLL mais j'en doute...).
En espérant être aidé. Bonsoir.

9 réponses

Avatar
Christian ASTOR
Tao wrote:

Le projet est le suivant, je voudrais pouvoir intercépter le clique gauche
de la souris et le répéter un certain nombre de fois. J'ai tenté de créer un
dll de hook avec, pour un premier temps, la touche contrôle comme
déclencheur, mais je n'y suis pas arrivé. Pourriez-vous m'aider ? Ou me
proposer une autre méthode beaucoup plus simple ?



Avec une DLL, il faut utiliser une "Shared Data Section"
C'est plus simple de faire sans DLL avec un Low Level Hook.
Pour reprendre ton exemple (avec Ctrl Gauche, en testant sur Paint Shop
Pro par exemple, il clique bien 5 fois au même endroit) =>

HHOOK hKeyboardHook;
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
hInst, 0);

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
DWORD dwKey = 0;
if (lParam)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;
if (dwKey == VK_LCONTROL)
{
POINT pt;
int i = 0;
while(i < 5)
{
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
Sleep(15);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
Sleep(15);
i++;
}
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
Avatar
Tao
"Christian ASTOR" a écrit dans le message de
news: 4921f210$0$28672$
Tao wrote:

Le projet est le suivant, je voudrais pouvoir intercépter le clique
gauche de la souris et le répéter un certain nombre de fois. J'ai tenté
de créer un dll de hook avec, pour un premier temps, la touche contrôle
comme déclencheur, mais je n'y suis pas arrivé. Pourriez-vous m'aider ?
Ou me proposer une autre méthode beaucoup plus simple ?



Avec une DLL, il faut utiliser une "Shared Data Section"
C'est plus simple de faire sans DLL avec un Low Level Hook.
Pour reprendre ton exemple (avec Ctrl Gauche, en testant sur Paint Shop
Pro par exemple, il clique bien 5 fois au même endroit) =>

HHOOK hKeyboardHook;
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
hInst, 0);

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
DWORD dwKey = 0;
if (lParam)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;
if (dwKey == VK_LCONTROL)
{
POINT pt;
int i = 0;
while(i < 5)
{
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
Sleep(15);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
Sleep(15);
i++;
}
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}



Merci de ta réponse claire et précise, le soucis maintenant est que je
n'arrive pas à la réutiliser... (Pas de commentaires).
En fait je bloque sur le paramètre hInst... Voici l'utilisation du code que
je fais dans un projet C++ classique :

#include <iostream>
#include <string>
#include <windows.h>

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam);

HHOOK hKeyboardHook;

int main(void)
{
std::cout << "Test Hook" << std::endl;
getchar();
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
hInst, 0);

return 0;
}

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
DWORD dwKey = 0;
if (lParam)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;

if (dwKey == VK_LCONTROL)
{
POINT pt;
int i = 0;

while(i < 5)
{
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
Sleep(15);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
Sleep(15);
i++;
}
}
}

return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}

Pourrais-tu m'aider ?
Avatar
Christian ASTOR
Tao wrote:

Merci de ta réponse claire et précise, le soucis maintenant est que je
n'arrive pas à la réutiliser... (Pas de commentaires).
En fait je bloque sur le paramètre hInst...



Il faut faire une appli Win32 GUI, pas Console, sinon il faut créer un
thread.
hInst est le hInstance de WinMain() (= GetModuleHandle(NULL))
Avatar
Tao
"Christian ASTOR" a écrit dans le message de
news: 4922be7e$0$28670$
Il faut faire une appli Win32 GUI, pas Console, sinon il faut créer un
thread.
hInst est le hInstance de WinMain() (= GetModuleHandle(NULL))



Bonsoir à tous (encore). Je suis désolé d'avoir autant de mal mais j'ai
l'impression (ou plutôt la certitude) que le hook lancé s'arrête
quasi-aussitôt. Le problème est que je ne sais pas comment faire pour que le
hook fonctionne en continu et qu'à chaque touche appuyée, la fonction de
traitement la compare à la touche contrôle et que si cela correspond, alors
il simule le clic gauche de la souris.

Pourriez-vous m'aider à surmonter ce problème ?

Voici le code utilisé :

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam);

HHOOK hKeyboardHook;

int WINAPI WinMain(HINSTANCE a, HINSTANCE b, LPSTR c, int d)
{
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
a, 0);
if(hKeyboardHook == NULL)
{
printf("Le hook n'a pas pu être lancénn");
getchar();
}

return 0;
}

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
DWORD dwKey = 0;
if (lParam)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;

if (dwKey == VK_LCONTROL)
{
POINT pt;
int i = 0;

while(i < 5)
{
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
Sleep(15);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
Sleep(15);
i++;
}
}
}

return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}

Ps : Merci de votre prochaine aide et veuillez m'excuser si je suis un peu
"lent à la détente" mais j'ai un peu de mal avec l'API Windows, bien qu'elle
soit très pratique.
Avatar
Christian ASTOR
Tao wrote:
Bonsoir à tous (encore). Je suis désolé d'avoir autant de mal mais j'ai
l'impression (ou plutôt la certitude) que le hook lancé s'arrête
quasi-aussitôt. Le problème est que je ne sais pas comment faire pour que le
hook fonctionne en continu et qu'à chaque touche appuyée



Parce qu'il n'y a pas de Message Loop.
Il suffit de partir du Winzard Win32 de VC++ ou VS.NET.
Par ex, avec ajout touche F11 pour arrêter le Hook =>

#include <windows.h>
#include <tchar.h>

HINSTANCE hInst;
HHOOK hKeyboardHook;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
hInstance, 0);
Beep(200, 200);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}


LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
DWORD dwKey = 0;
if (lParam)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;
if (dwKey == VK_LCONTROL)
{
POINT pt;
int i = 0;
while(i < 5)
{
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
Sleep(15);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
Sleep(15);
i++;
}
}
if (dwKey == VK_F11)
{
Beep(500, 200);
UnhookWindowsHookEx(hKeyboardHook);
PostQuitMessage(0);
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
Avatar
Tao
"Christian ASTOR" a écrit dans le message de
news: 49232df2$0$28668$

Parce qu'il n'y a pas de Message Loop.
Il suffit de partir du Winzard Win32 de VC++ ou VS.NET.
Par ex, avec ajout touche F11 pour arrêter le Hook =>

#include <windows.h>
#include <tchar.h>

HINSTANCE hInst;
HHOOK hKeyboardHook;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
hInstance, 0);
Beep(200, 200);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}


LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
DWORD dwKey = 0;
if (lParam)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;
if (dwKey == VK_LCONTROL)
{
POINT pt;
int i = 0;
while(i < 5)
{
GetCursorPos(&pt);
mouse_event(MOUSEEVENTF_LEFTDOWN, pt.x, pt.y, 0, 0);
Sleep(15);
mouse_event(MOUSEEVENTF_LEFTUP, pt.x, pt.y, 0, 0);
Sleep(15);
i++;
}
}
if (dwKey == VK_F11)
{
Beep(500, 200);
UnhookWindowsHookEx(hKeyboardHook);
PostQuitMessage(0);
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}




Je vous remercie pour votre aide très précieuse ainsi que pour votre
patiente. Grâce à vous, je crois avoir saisi les contours des hooks de
windows et je vous en remercie. Votre méthode marche au poil et c'est à mon
plus grand bonheur. Malgré le fait que je n'ai pas fait grand chose, je
pense avoir profité de vos connaissances. Sur ce je vous souhaite une bonne
soirée et à une prochaine fois.
Amicalement votre, Tao.
Avatar
Tao
Rebonsoir à tous, j'ai voulu reprendre le code pour l'insérer dans une
fenêtre (avec Qt). Le soucis est que je me retrouve avec une message
d'erreur que je n'arrive pas à résoudre. Voici la partie du code consernée :

int APIENTRY FenPrincipale::abc(HINSTANCE hInstance, HINSTANCE
hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{

MSG msg;

hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
hInstance, 0);


while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return (int) msg.wParam;

}



Et voici le message d'erreur, qui concerne la 4e ligne du code posté :

argument of type `LRESULT (FenPrincipale::)(int, WPARAM, LPARAM)' does not
match `LRESULT(*)(int, WPARAM, LPARAM)'Pourriez-vous m'aider ?
Avatar
antoine
"Tao" wrote in message
news:gg1ite$o41$

Et voici le message d'erreur, qui concerne la 4e ligne du code posté :

argument of type `LRESULT (FenPrincipale::)(int, WPARAM, LPARAM)' does not
match `LRESULT(*)(int, WPARAM, LPARAM)'Pourriez-vous m'aider ?



Pace que t'as dû mettre la fonction dans une classe et il faut pas (si pas
statique)
Avatar
Tao
Oui merci, j'ai reglé le problème, en effet je l'avais mise dans une classe.
Merci encore et bonne soirée.