BeLZeL
Messages postés110Date d'inscriptionmardi 10 octobre 2000StatutMembreDernière intervention20 décembre 2005
-
28 juil. 2004 à 23:13
BeLZeL
Messages postés110Date d'inscriptionmardi 10 octobre 2000StatutMembreDernière intervention20 décembre 2005
-
29 avril 2006 à 14:38
J'ai fait un programme simple dont le but est de faire un hook clavier global, et de tout mettre dans un fichier log.
Tout fonctionne, sauf une chose, les accents circonflexes ! En voulant obtenir ê, dans l'application hookée, j'obtiens ^^e et dans le log, ^e.
Je fais bien les return CallNextHookEx. Si je ne n'écris plus dans le fichier log, tout redevient normal. Peut-être que l'erreur vient de la fonction ToAscii ou GetKeyboardState. Il doit y avoir une modification toute simple à faire, mais je ne trouve pas !
Voilà ma source ( http://belzel.free.fr/hook.zip ), avec la DLL et l'EXE (pour DevCpp, mais ca doit marcher aussi avec Visual C). L'EXE crée un fichier c:\log.txt.
Voilà le code de la DLL :
//------------------------------------------------------------------------------
// INCLUDES
//------------------------------------------------------------------------------
#include <windows.h> // Header pour DevCpp
#include <stdio.h> // Header pour l'écriture dans un fichier
#include <time.h>
// A ajouter devant une fonction pour l'exporter ou l'importer
#define DLLEXPORT __declspec (dllexport)
#define DLLIMPORT __declspec (dllimport)
//------------------------------------------------------------------------------
// Variables Globales De La DLL
//------------------------------------------------------------------------------
HHOOK HKEYBOARD; // Hook Clavier
HINSTANCE HInst; // Handle d'intance de la DLL
FILE * logfic; // Fichier LOG
clock_t tpsBase; // Temps de base (point de départ)
char LastWindowText[256]; // Nom de la fenêtre
char FILENAME[256] = "c:\\log.txt"; // Chemin du log
//------------------------------------------------------------------------------
// Fonctions executée lorsqu'on appuie sur une touche
//------------------------------------------------------------------------------
LRESULT CALLBACK KeyboardProc ( int nCode,WPARAM wParam,LPARAM lParam )
{
char ch;
BYTE KeyState[256]; // address of key-state array
WORD Char; // buffer for translated key
// On ne fait rien dans ce cas
if ( nCode < 0 || nCode == HC_NOREMOVE )
return CallNextHookEx ( HKEYBOARD, nCode, wParam, lParam );
// Pour éviter les répétitions
// Bit 30 : Spécifie l'état précédent de la touche
if ( ((DWORD)lParam & 1<<30) != FALSE )
return CallNextHookEx ( HKEYBOARD, nCode, wParam, lParam );
//------------------------------------------------------------------------------
// Fonction principale d'Initialisation De La DLL
//------------------------------------------------------------------------------
// hinst : l'instance de notre programme
// raison : pourquoi notre DLL est utilisée
// reserv : non utilisé
// retourne vrai si l'opération s'est bien déroulé
//------------------------------------------------------------------------------
BeLZeL
Messages postés110Date d'inscriptionmardi 10 octobre 2000StatutMembreDernière intervention20 décembre 2005 30 juil. 2004 à 00:55
Dernier Point :
ToAscii est très buggée. Impossible de l'appeler lorsqu'un DEAD CHAR est en mémoire. Voici une alternative assez bonne : GetKeyNameText, qu'on appellera lorsqu'un DEAD CHAR a précédemment été tapé.
Les programmes hookés recoivent bien l'accent circonflexe sur le "e". Dans le log, on aura ca :
test [DK]E [DK]R [DK]Edssfdfs [DK]Ds[ENTER]
au lieu de
test ê ^r êdssfdf ^ds
Ce qui est assez compréhensible. J'ai pas mieux pour le moment et je pense que ca me suffit.
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 28 juil. 2004 à 23:45
Si tu procedes ainsi, teste si deadchar et lequel dans ton 'default:', si oui enregistre lequel dans une variable car sera a combiner avec la prochaine touche.
Faudrait aussi faire un code coherent, FILE* etc n'ont rien a faire dans du code Windows, CreateFile, WriteFile...
BeLZeL
Messages postés110Date d'inscriptionmardi 10 octobre 2000StatutMembreDernière intervention20 décembre 2005 29 juil. 2004 à 00:58
Je n'ai pas la possibilité de savoir si mon caractère est un WM_DEADCHAR (l'accent circonflexe) ou un WM_CHAR (un caractère normal). Et même si je pouvais le savoir, je ne vois pas comment le combiner, normalement, le hook ne devrait pas altérer les messages.
Avec le hook WH_KEYBOARD, on a la touche (VK_...) sur wParam et 32 bits sur lParam (etat up / down, scancode, etc...).
Sinon, j'ai regardé vite fait CreateFile. Est-ce qu'il y a un flag particulier pour ajouter à la suite d'un fichier ?
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 29 juil. 2004 à 01:10
tu ouvres avec OPEN_ALWAYS si tu ne veux pas ecraser ce qui existerait deja dans le fichier et illico:
SetFilePointer(hfl, 0, 0, FILE_END);
et ainsi le pointeur est a la fin.
On verra d'avancer cela des que je vais pouvoir.
ciao...
BruNews, Admin CS, MVP Visual C++
Vous n’avez pas trouvé la réponse que vous recherchez ?
cosmobob
Messages postés700Date d'inscriptionmardi 30 décembre 2003StatutMembreDernière intervention27 janvier 20094 29 juil. 2004 à 12:48
ha et sinon au début de ton KeyBoardProc mets ca :
//détecte si c'est une répétition (la frappe a déja été traitée)
if (! ( (DWORD) lParam & 0x40000000) )
return CallNextHookEx( HKEYBOARD, nCode, wParam, lParam );
BeLZeL
Messages postés110Date d'inscriptionmardi 10 octobre 2000StatutMembreDernière intervention20 décembre 2005 29 juil. 2004 à 21:20
BruNews > J'ai viré FILE* pour mettre un HANDLE. Tjrs le même pb.
cosmobob > J'ai placé HInst au "bon endroit", tjrs le mêm pb. Pour le test que tu m'as donné ensuite -> 0x40000000 est une façon que je trouve moins jolie pour écrire 1<<30 (décalage de bits). Donc ce test est déjà présent dans mon code, il évite les répétitions de touches.
J'ai essayé d'avancé un peu sur la sauvegarde de la touche (^ ou š), puis la combinaison de la touche avec une lettre (ê, â, etc ...). Voilà le code. Le log est bon, mais dans l'application, au lieu de me faire ê, j'ai uniquement e (c'est déjà mieux que ^^e).
Lorsqu'on appuie sur ^ ou š, on fait le premier test et on retourne 1. L'accent n'est pas envoyée au programme !
Lorsqu'on appuie sur une nouvelle lettre, on utilise keybd_event pour combiner l'accent circonflexe et le "e" (c'est un cas particulier).
Le troisième test s'effectue pour une touche normale. Ce test fonctionne correctement.
Le problème, c'est que keybd_event n'envoie pas l'accent circonflexe à l'application, juste le "e". Je travaille la dessus.
BeLZeL
Messages postés110Date d'inscriptionmardi 10 octobre 2000StatutMembreDernière intervention20 décembre 2005 29 juil. 2004 à 22:17
Aux dernières nouvelles, le hook fonctionne parfaitement. Ca coince juste sur la fonction ToAscii. Voilà ce que j'ai trouvé dans l'aide de la fonction ToAscii :
Remarks :
The parameters supplied to the ToAscii function might not be sufficient to translate the virtual-key code, because a previous dead key is stored in the keyboard layout.
En gros, la fonction n'a pas la possibilité de gérer les "dead char", comme les accents circonflexes. Je cherche une alternative à la fonction ToAscii et ca devrait être bon.
Le code précédent est inutile ! il peut être remplacé simplement par ca pour le moment (même si ToAscii et ToAsciiEx bug) :
BeLZeL
Messages postés110Date d'inscriptionmardi 10 octobre 2000StatutMembreDernière intervention20 décembre 2005 29 avril 2006 à 14:38
Perso, j'ai complètement oublié comment tout ca fonctionnait lol
Mais normalement, il y a un code ascii différents pour les majuscules et les minuscules.
J'sais pas si ca t'aide ...