Mesdames et messieurs, pour ceux qui ne sont pas encore au courant et pour votre plus grande joie, je vais vous apprendre qu’il est aisé de faire un programme en C qui simule les événements du clavier et de la souris. Je m’explique :
Lorsque vous appuyez sur une touche de votre clavier, ou que vous cliquez sur un bouton de votre souris, c’est un signal (sous forme d’un code) qui est récupéré par votre système d’exploitation qui ensuite traite ce signal envoyé. On appelle ceci un événement.
Il y a plusieurs sortes d’événements par touches, par exemple, on peut définir quand l’utilisateur à enfoncé la touche « Entrée » et quand il l’a relâché. Ces deux actions sont scindées en événements distincts. Même lorsque le curseur de la souris bouge d’un pixel, ceci est un événement et les nouvelles coordonnées du pointeur sont appliquées.
Le clavier:
Nous allons devoir inclure le header windows.h pour pouvoir utiliser ces méthodes. Je vais ensuite créer mon objet qui me permettra de récupérer l’ID de la fenêtre qui à le focus :
HWND hFore = GetForegroundWindow();
Dans hFore je stocke les informations de la fenêtre actuelle. Si la fenêtre sur laquelle on veut récupérer les entrées clavier n’est pas celle ouverte par défaut, on peut aussi utiliser :
SetForegroundWindow(FindWindow("%s",NULL));
Dans lequel %s est la chaîne de caractère contenant le nom de la fenêtre que l’on veut appeler au premier plan, puis appeller GetForegroundWindow(), comme ci-dessus. Ensuite il faut écrire ceci :
PostMessage(hFore,WM_KEYDOWN,VK_CONTROL,0);
pour permettre l’appui simulé sur les touches. Et on peut ensuite rentrer librement, des lettres à écrire avec la méthode keybd_event(), qui s’utilise comme suit :
keybd_event('S', 0,0 ,0); keybd_event('A', 0,0 ,0); keybd_event('L', 0,0 ,0); keybd_event('U', 0,0 ,0); keybd_event('T', 0,0 ,0);
A noter que le premier argument de la fonction keybd_event est le scan code et ne correspond malheureusement pas au code ASCII de la lettre, vous pourrez avoir toutes les informations sur cette fonction ici : msdn.microsoft.com
La souris :
Je vous proposerais ici de coder un petit simulateur de souris, commandable via le clavier. Non pas que ça soit très pratique en cas de problème avec votre souris, mais ça sera extrêmement pédagogique et je pense que cet exemple simple permettra à bon nombre de personnes de voir le mécanisme. Windows nous mâche énormément le travail, nous n’avons plus qu’à utiliser sa librairie !
Tout d’abord on va avoir besoin d’inclure windows.h pour que cela fonctionne. Puis de créer quelques objets, comme ceci :
#include <windows.h> POINT pt; BOOL bContinue = TRUE; SHORT Mask = 32768; DWORD dwEventFlags; DWORD dwData;
pt sera tout simplement un point, constitué de deux coordonnées x et y. Vous imaginez qu’il nous servira à définir la position du curseur.
Mask et un masque avec lequel on fera un & bit-à-bit pour pouvoir utiliser correctement la fonction GetKeyState(), mais j’y reviendrais plus tard.
dwEventFlags sera simplement la variable d’évènement de la souris, dans laquelle on stockera l’action à effectuer.
dwData servira à stocker les événements de la molette de la souris.
Note : Pas de panique ! DWORD n’est rien d’autre qu’un type entier utilisé dans la plupart des librairies Windows.
Ensuite je vais faire ma boucle qui permettra au programme de tourner tant que bContinue sera égal à TRUE.
while (bContinue) { dwData = 0; dwEventFlags = MOUSEEVENTF_ABSOLUTE; if (GetKeyState(VK_ESCAPE) & Mask) bContinue = FALSE; }
Alors, le on définit la roulette à la position 0 avec dwData, (qu’on incrémentera ou décrémentera en fonction des événements futurs), et puis on initialise la variable d’événements de la souris à « 0 » (elle n’effectue aucune action). La condition « if » sert ici à vérifier si l’on appuie ou non sur la touche Echap. C’est ici que vient la petite explication sur le GetKeyState(int kCode). Cette fonction renvoie le statut de la touche spécifiée en paramètre. Le & bit-à-bit avec le masque sert à déterminer si la touche à été relâchée. Vous pourrez trouver la liste des constantes utilisées pour caractériser les touches du clavier par là : Liste des touches MSDN.
Toujours dans la boucle, à la suite, passons maintenant à la simulation des événements souris. Ou plutôt devrais-je dire, l’émulation.
GetCursorPos(&pt); if (GetKeyState(VK_NUMPAD1) & Mask) { if (!(GetKeyState(VK_LBUTTON) & Mask)) dwEventFlags |= MOUSEEVENTF_LEFTDOWN; } else if (GetKeyState(VK_LBUTTON) & Mask) // Ce test est nécessaire pour s'assurer qu'on n'envoie pas plus // de relevés de touche que d'abaissements dwEventFlags |= MOUSEEVENTF_LEFTUP;
Ici, on constate que au début du programme on récupère la position du curseur et qu’on la stocke dans le point pt. Ensuite, on précise que si l’utilisateur appuie sur la touche « 1 » du pavé numérique, on stocke dans dwEventFlags l’action « bouton gauche abaissé », nommé sous la constante MOUSEVENTF_LEFTDOWN. On fait aussi la vérification, si le bouton gauche est déjà enfoncé, alors on le relâche. Comme le dit le commentaire associé, cela sert a vérifier que l’on relève pas plus de fois que l’on abaisse le bouton.
Note : Pour affecter à un DWORD les événements, n’oubliez pas d’utiliser l’opérateur surchargé « |= »
if (GetKeyState(VK_NUMPAD2) & Mask) { if (!(GetKeyState(VK_MBUTTON) & Mask)) dwEventFlags |= MOUSEEVENTF_MIDDLEDOWN; } else if (GetKeyState(VK_MBUTTON) & Mask) dwEventFlags |= MOUSEEVENTF_MIDDLEUP; if (GetKeyState(VK_NUMPAD3) & Mask) { if (!(GetKeyState(VK_RBUTTON) & Mask)) dwEventFlags |= MOUSEEVENTF_RIGHTDOWN; } else if (GetKeyState(VK_RBUTTON) & Mask) dwEventFlags |= MOUSEEVENTF_RIGHTUP;
Ici, on fait la même chose que précédemment, mais avec les boutons molette et droit de la souris. Qui seront respectivement simulé lors de l’appui de la touche « 2 » et « 3 » du pavé numérique.
if (GetKeyState(VK_ADD) & Mask) { dwEventFlags |= MOUSEEVENTF_WHEEL; dwData += WHEEL_DELTA; } else if (GetKeyState(VK_SUBTRACT) & Mask) { dwEventFlags |= MOUSEEVENTF_WHEEL; dwData -= WHEEL_DELTA; }
C’est par la qu’on gère la molette. C’est simple, si on appui sur la touche « + » ou « – » du pavé numérique, on monte ou baisse la molette.
Note : L’écart utilisé pour le déplacement vertical avec la molette est défini par la constante WHEEL_DELTA qui se trouve dans windows.h.
Notre boucle est bientôt finie, il ne nous reste plus qu’à gérer le déplacement du curseur avec les touches fléchées :
if (GetKeyState(VK_UP) & Mask) pt.y -= 1; if (GetKeyState(VK_DOWN) & Mask) pt.y += 1; if (GetKeyState(VK_LEFT) & Mask) pt.x -= 1; if (GetKeyState(VK_RIGHT) & Mask) pt.x += 1; SetCursorPos(pt.x,pt.y); mouse_event(dwEventFlags,pt.x,pt.y,dwData,0); Sleep(10);
Dans les 4 premiers ‘if » on s’occupe d’incrémenter ou de décrémenter x ou y, en fonction de l’appui sur une/plusieurs touches fléchées. Puis avec SetCursorPos(DWORD x,DWORD y) on définit la nouvelle position du pointeur de la souris. Enfin, on applique tout les changements, grâce à mouse_event(), qui prend en paramètre :
- DWORD dwEventFlag : La variable dans laquelle on à stocké l’action à réaliser grâce aux précédentes condition (par exemple appui bouton droit)
- DWORD x : La nouvelle coordonnée horizontale du curseur (en pixel)
- DWORD y : La nouvelle coordonnée verticale du curseur (en pixel)
- DWORD dwData : Le déplacement à réaliser au niveau de la molette de la souris.
- Le 5ème argument étant des informations supplémentaires que je n’ai jamais utilisé, nous allons mettre 0
Le Sleep(10) est une simple pause de 10 ms du programme pour permettre au programme d’avoir le temps de capter les appuis sur les touches, car l’exécution d’une boucle est très rapide.
J’espère que vous aurez trouvé cet article intéressant, moi je me suis bien amusé avec ces fonctionnalités Windows, que j’ai testées sur un Seven et compilé avec un MinGW32 sur l’IDE Codeblocks. Le code complet ainsi que le projet Codeblocks est disponible dans l’espace « Téléchargement » du site 🙂
Super tuto, très utile : BRAVO !
Merci 🙂
merci pour cette informations grandement utile pour moi car sur internet ce que je voyez ne correspondait jamais a ce que je voulait!!!!!!!!!!!!! « bisous d’amis »
Je ne sais pas qui tu es mais merci 😉
au fait j’ai dit merci avant d’essayer mais sa marche pas du tout help me please
Il me faudrait un peu plus de précisions pour t’aider. Qu’essaies-tu de faire ? Quel IDE, environnement et compilateur ? Quel est la partie de ton code qui ne fonctionne pas ?
non en fait le code il marche mais je ne comprenais pas le
getasinckeystate
parce que je ne savais pas quoi faire avec.