Détourner la frappe clavier

Description

En réponse à une question du forum, voici un code source montrant comment détourner la frappe au clavier pour afficher, lettre par lettre, un message personnalisé. Un hook global clavier est utilisé. L'astuce réside dans l'emploi de la fonction keybd_event() pour simuler l'appui sur des touches différentes de celles interceptées dans la fonction de hook. Les lettres majuscules et les lettres avec accent circoflexe ou tréma les plus courament utilisées sont traitées.
Pour tester l'exécutable, renommez le en detourneur.exe. Il fonctionne en tâche de fond. Pour regarder son effet, lancez le et essayez de taper du texte dans n'importe quelle application. Lisez le texte qui s'affiche au fur et à mesure de la frappe jusqu'à la fin pour voir comment le quitter.
Amusez-vous bien.

Source / Exemple :


#define _WIN32_WINNT  0x0500 // Windows 2000 et supérieur
#include <windows.h>

HHOOK hHook; // Handle du hook clavier
int position=0;// Indicateur de position dans la chaine à afficher

// Chaine à afficher:
char texte[]="Vous êtes victime d'un programme qui détourne la frappe au clavier pour afficher le présent texte. Pour l'arrêter appuyez sur CTRL + Q ou attendez 3 minutes.\n";
// Liste des lettres avec accent circonflexe ou tréma:
BYTE avecaccents[]={'â','ê','û','î','ô','ë','ï'};
// Liste des lettres sans accent circonflexe ni tréma:
BYTE sansaccents[]={'a','e','u','i','o','e','i'};
// Liste des flags indiquant l'utilisation de la touche SHIFT:
BYTE shifts[]={0,0,0,0,0,1,1};

/*******************************  Fonction de gestion du hook  ****************************/
LRESULT CALLBACK HookProc ( int nCode, WPARAM wParam, LPARAM lParam)
{
	// Vérifier si une touche est appuyée:
	if ((nCode == HC_ACTION) && (wParam == WM_KEYDOWN))
	{
		// Obtenir pointeur sur structure KBDLLHOOKSTRUCT:
		KBDLLHOOKSTRUCT* hookstruct = ((KBDLLHOOKSTRUCT*)lParam);
		// S'assurer que l'appui sur les tpuches n'est pas simulé:
		if(hookstruct->dwExtraInfo!=255)
		{
			// Vérifier si la touche "Q" est appuyée:
			if(hookstruct->vkCode==0x51 )
			{
				// S'assurer que la touche Control est enfoncée:
				if(GetKeyState(VK_CONTROL) & 0x8000)
				{
					// Envoyer le message de fermeture de l'application:
					PostThreadMessage(GetCurrentThreadId(),WM_QUIT,0,0);
					// Sauter les autres hooks:
					return 1;
				}
			}
			// Convertir le caractère courant en virtual-key code: 
			SHORT vcode=VkKeyScan(texte[position]);
			SHORT vcode2;
			// Si le caractère comporte un tréma ou accent circonflexe:
			if(vcode==-1)
			{
				int i;
				// Chercher le caractère dans la liste:
				for(i=0; i<7; i++)
				{
					if((BYTE)texte[position]==avecaccents[i]) break;
				}
				// Si pas trouvé alors sauter les autres hooks:
				if(i==7) return 1;
				// Trouver le virtuel-key code de la lettre non accentuée correspondante:
				vcode2=VkKeyScan(sansaccents[i]);
				// Si tréma, simuler appui sur la touche SHIFT:
				if(shifts[i]) keybd_event(VK_SHIFT,0,0,255);
				// Simuler appui sur la dead-key de l'accent circonflexe et le tréma:
				keybd_event(VK_OEM_6,26,0,255);
				keybd_event(VK_OEM_6,26,KEYEVENTF_KEYUP,255);
				// Si tréma simuler relachement de la touche SHIFT:
				if(shifts[i]) keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,255);
			}
			// Si le caractère ne comporte ni tréma ni accent circonflexe, le traiter directement:
			else vcode2=vcode;
			// Obtenir la lettre:
			BYTE lettre=LOBYTE(vcode2);
			// Obtenir l'état des touches SHIFT,CTRL et ALT pour le caractère courant:
			BYTE etat=HIBYTE(vcode2);
			// Simuler l'appui sur la touche SHIFT pour les lettres majuscules:
			if(etat==1) keybd_event(VK_SHIFT,0,0,255);
			// Simuler l'appui sur la touche Alt Gr pour certains caractères:
			if(etat==6) 
			{
				keybd_event(VK_CONTROL,0,0,255);
				keybd_event(VK_MENU,0,0,255);
			}
			// Simuler l'appui de la touche correspondant au caractère courant:
			keybd_event(lettre,0,0,255);
			keybd_event(lettre,0,KEYEVENTF_KEYUP,255);
			// Simuler relachement dela touche SHIFT pour les lettres majuscules:
			if(etat==1) keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,255);
			// Simuler relachement de la touche Alt Gr pour certains caractères:
			if(etat==6) 
			{
				keybd_event(VK_MENU,0,KEYEVENTF_KEYUP,255);
				keybd_event(VK_CONTROL,0,KEYEVENTF_KEYUP,255);
			}
			// Incrémenter notre indicateur de position dans la chaine à afficher:
			position++;
			// Si la fin de chaine est atteinte, mettre à 0 l'indicateur de position:
			if(position==lstrlen(texte)) position=0;
			// Sauter les autres hooks:
			return 1;
		}
	}
	// Renvoi des messages au sytème pour permettre d'autres hooks
	return CallNextHookEx(hHook, nCode, wParam, lParam);
}
/********************************************************************************************/

/*********************************** Fonction WinMain ***************************************/
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmd, int show)
{
	// Créer le timer de chronométrage:
	UINT_PTR timer=SetTimer(0,0,180000,0);// 3 minutes
	// Lancer le hook clavier:
	hHook = SetWindowsHookEx( WH_KEYBOARD_LL, (HOOKPROC) HookProc, hinst, 0);
	// Boucle des messages:
	MSG msg;
	while (GetMessage(&msg, 0, 0, 0)) 
	{
		// Sortir de la boucle des messages si les 3 minutes sont écoulées:
		if(msg.message==WM_TIMER && msg.wParam==timer) break;
	}
	// Arrêter le hook clavier:
	UnhookWindowsHookEx(hHook);
	// Détruire le timer:
	KillTimer(0,timer);
	// Quitter:
	return 0;
}
/*********************************************************************************************/

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.