Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GetKeyNameText me renvoie toujours la lettre 'G'

4 views
Skip to first unread message

Pascal Rito

unread,
Nov 28, 2009, 1:09:26 PM11/28/09
to
Bonjour à tous.
Je suis en train de travailler sur le hook system de l'API Windows et
je me heurte à un problème.
Comme ToAscii ne gère pas les dead keys, je me suis rabattu sur
GetKeyNameText et le soucis c'est que cette fonction me retourne
toujours la lettre 'G' (en vraie elle retourne 1, càd la longueur de
'G' et inscrit 'G' dans le buffer).

Vois mon code :

LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if ((nCode == HC_ACTION) && (wParam == WM_KEYDOWN))
{
char nomTouche[256] = "";
int i = 0;


// On récupère la touche
GetKeyNameText(lParam, nomTouche, 256);
printf("Traduction : ");
for(i = 0; i < 256; i++) printf("%c", nomTouche[i]);
printf("\n");
}
// Renvoi des messages au sytème pour permettre d'autres hooks
return CallNextHookEx(hHook, nCode, wParam, lParam);
}

Si quelqu'un pouvait m'expliquer pourquoi j'ai ce problème, je vous en
serais reconnaissant.

Christian ASTOR

unread,
Nov 28, 2009, 1:59:24 PM11/28/09
to
On 28 nov, 19:09, Pascal Rito <pascal.r...@gmail.com> wrote:

> Comme ToAscii ne gère pas les dead keys, je me suis rabattu sur
> GetKeyNameText et le soucis c'est que cette fonction me retourne
> toujours la lettre 'G' (en vraie elle retourne 1, càd la longueur de
> 'G' et inscrit 'G' dans le buffer).

Il faut faire, par exemple, pour un Hook WH_KEYBOARD_LL =>
(il faut normalement aussi tester les touches comme VK_RMENU avec
GetKeyState()...)

KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
DWORD dwMsg = 1;
dwMsg += (pkbhs->scanCode << 16);
dwMsg += (pkbhs->flags << 24);
char sKeyName[MAX_PATH] = "";
GetKeyNameText (dwMsg, sKeyName, MAX_PATH);
char sBuffer[MAX_PATH];
CharToOem(sKeyName, sBuffer);
printf("%s\n", sBuffer);

Pascal Rito

unread,
Nov 28, 2009, 3:12:52 PM11/28/09
to

Merci pour ta réponse, elle fonctionne selon mes attentes. Mais si je
veux enregistrer la frappe dans un fichier texte à l'aide de CreateFile
(); je ne suis pas obligé d'utiliser CharToOem(); vu que ce n'est pas
pour l'afficher dans la console. N'est-ce pas ?

Christian ASTOR

unread,
Nov 28, 2009, 3:35:21 PM11/28/09
to
On 28 nov, 21:12, Pascal Rito <pascal.r...@gmail.com> wrote:

> Merci pour ta réponse, elle fonctionne selon mes attentes. Mais si je
> veux enregistrer la frappe dans un fichier texte à l'aide de CreateFile
> (); je ne suis pas obligé d'utiliser CharToOem(); vu que ce n'est pas
> pour l'afficher dans la console. N'est-ce pas ?

Tout-à-fait, c'est juste pour l'affichage.
WriteFile() suffit.

Pascal Rito

unread,
Nov 28, 2009, 3:55:36 PM11/28/09
to

Merci pour ton aide. Maintenant je me heurte à un second problème.
Alors voilà comment fonctionne mon hook :

Intercepte message clavier:
Si touche = dead key
On rend la main en mettant BOOL deadkey = TRUE; pour le
prochain appel
On traite le message
Si deadkey != TRUE
ToAscii(message); //schématique ici vu que ToAscii attend
en vrai 5 paramètres
Sinon
GetKeyNameText(message);
On rend la main

Mon problème maintenant ce serait de traiter CAPS LOCK. Car avec ce
schéma là, si CAPS LOCK est appuyé, on affiche [CAPS LOCK] à l'écran.
Mais si on appuie sur ')' alors que CAPS LOCK est appuyé, mon
programme affiche ')' et non '°'.
En clair, je voudrais transformer mon schéma en ceci :

Intercepte message clavier:
Si touche = dead key
On rend la main en mettant BOOL deadkey = TRUE; pour le
prochain appel
Si CAPS LOCK est appuyé
BOOL maj = TRUE;
On traite le message
Si deadkey != TRUE && maj != TRUE
ToAscii(message); //schématique ici vu que ToAscii attend
en vrai 5 paramètres
Sinon
GetKeyNameText(message);
On rend la main

Pourrais-tu me dire comment faire pour savoir que CAPS LOCK est
appuyé ? Car avec la msdnn, je m'y perds un peu... J'ai cru comprendre
que cette information était contenue dans lParam (je me trompe peut
être) et même plus précisément dans KBDLLHOOKSTRUCT (idem) mais je ne
suis pas sûr de savoir comment l'extraire.
Une petite aide ? Merci.

Pascal Rito

unread,
Nov 28, 2009, 4:47:42 PM11/28/09
to

Alors pour ce soucis de CAPS LOCK, j'ai procédé comme ceci :

KBDLLHOOKSTRUCT *hookstruct = ((KBDLLHOOKSTRUCT*)lParam);
static BOOL maj;

if(hookstruct->vkCode == VK_CAPITAL)
{
if(maj)
{
myfprintf("[CAPS LOCK OFF]");
maj = FALSE;
}
else if(!hookstruct->flags)
{
myfprintf("[CAPS LOCK ON]");
maj = TRUE;
}
}

Et ensuite, en même temps que je teste si c'est une deadkey, je teste
aussi la valeur de maj. Si maj == TRUE alors on utilise
GetKeyNameText, sinon on utilise ToAscii.

Cette solution fonctionne, à l'affichage j'ai : "[CAPS LOCK ON]TEST
[CAPS LOCK OFF]test".

Mais le soucis que j'ai, c'est que si CAPS LOCK était déjà appuyé
avant la mise en route du Hook, lorsque j'affiche les messages
interceptés à l'écran, je me retrouve avec : "[CAPS LOCK ON]TEST[CAPS
LOCK OFF]TEST" où le [CAPS LOCK ON] est le moment où je désactive CAPS
LOCK et [CAPS LOCK OFF] le moment où je l'active...

Un complément de solution ? Ou carrément une autre solution ?
Merci

Christian ASTOR

unread,
Nov 28, 2009, 8:01:54 PM11/28/09
to
On 28 nov, 21:55, Pascal Rito <pascal.r...@gmail.com> wrote:

> Pourrais-tu me dire comment faire pour savoir que CAPS LOCK est
> appuyé ?

Comme je l'avais évoqué pour AltGr (VK_RMENU), avec GetKeyState() =>
BOOL bCapsOn = GetKeyState(VK_CAPITAL) & 0x0001;

Pascal Rito

unread,
Nov 29, 2009, 8:48:08 AM11/29/09
to

J'ai essayer d'adapter ton exemple (qui fonctionne parfaitement pour
VK_CAPITAL) pour VK_MENU et VK_RMENU en faisant comme ceci :
DWORD bAltGrOn;
DWORD bAltOn;

bAltGrOn = (DWORD)(GetKeyState(VK_RMENU)) & 0x1000;
if(bAltGrOn == 0x1000) printf'("AltGr : On\n");

bAltOn = (DWORD)(GetKeyState(VK_MENU)) & 0x1000;
if(bAltOn == 0x1000) printf("Alt on\n");

Cela fonctionne lorsque j'appuie sur Alt (left), car en sortie j'ai :
'Alt on'
Mais lorsque j'appuie sur Alt (right), en sortie j'ai :
'Alt On
AltGr On
Alt On
AltGr On'

Alors pourquoi est-ce que j'ai les deux touches d'affichées alors que
je n'appuie que sur AltGr ? Et pourquoi me l'affiche-t-il deux fois ?
Comme si il l'affichait lorsque AltGr était enfoncé, puis relâché.

Christian ASTOR

unread,
Nov 29, 2009, 1:39:26 PM11/29/09
to
On 29 nov, 14:48, Pascal Rito <pascal.r...@gmail.com> wrote:

> Alors pourquoi est-ce que j'ai les deux touches d'affichées alors que
> je n'appuie que sur AltGr ? Et pourquoi me l'affiche-t-il deux fois ?
> Comme si il l'affichait lorsque AltGr était enfoncé, puis relâché.

Le code n'est pas bon.
Pour AltGr, qui n'est pas "lockable" comme Caps Lock, c'est :
BOOL bAltGrDown = GetKeyState(VK_RMENU) & 0x8000;

Pascal Rito

unread,
Nov 29, 2009, 2:11:47 PM11/29/09
to

J'avais compris la différence entre Caps Lock et AltGr. Juste mon
erreur était le '& 0x1000' alors qu'on était avec de l'hexadécimale.
Donc j'ai corrigé comme tu me le proposes, et j'ai toujours ce
problème :
BOOL bAltOn; //'ALT ON'
BOOL bAltGrOn; //'ALT GR'

bAltGrOn = GetKeyState(VK_RMENU) & 0x8000;
if(bAltGrOn) printf("AltGr on\n");

bAltOn = GetKeyState(VK_MENU) & 0x8000;
if(bAltOn) printf("Alt on\n");

Qui me donne en sortie :
'Alt on
AltGr on
Alt on
AltGr on' lorsque j'appuie sur AltGr.

J'ai pensé que cela pouvait venir de la répétition des touches. Alors
j'ai ajouté :
if (((DWORD)lParam & 0x40000000) != FALSE) //Bit 30 permet de savoir
si c'est une répétition
return CallNextHookEx (hHook, nCode, wParam, lParam);

Le problème c'est que ce code ne règle pas l'autre soucis (qui doit
surement venir d'autre part) mais en plus, lorsque je maintient la
touche 'a' enfoncé, la console m'affiche 'aaaaaaaaaaaaaaaaaaaaaaaaa'
au lieu de 'a' (par exemple).

Saurais-tu m'aider à résoudre ces deux problèmes ?

Christian ASTOR

unread,
Nov 30, 2009, 3:00:26 PM11/30/09
to
On 29 nov, 20:11, Pascal Rito <pascal.r...@gmail.com> wrote:
> Donc j'ai corrigé comme tu me le proposes, et j'ai toujours ce
> problème :

Dans un de mes vieux Keyloggers, je teste :

if(nCode == HC_ACTION && ( wParam == WM_KEYDOWN || wParam ==
WM_SYSKEYDOWN ) & !IsModifierKey(pkbhs->vkCode))
{


BOOL bAltGrDown = GetKeyState(VK_RMENU) & 0x8000;

BOOL bAltDown = GetKeyState(VK_LMENU) & 0x8000;
// ... etc...
}

avec :

BOOL
IsModifierKey(DWORD vkCode)
{
return
VK_CONTROL == vkCode || VK_RCONTROL == vkCode || VK_LCONTROL ==
vkCode ||
VK_SHIFT == vkCode || VK_RSHIFT == vkCode || VK_LSHIFT == vkCode
||
VK_MENU == vkCode || VK_LMENU == vkCode || VK_RMENU == vkCode;
}


Pascal Rito

unread,
Nov 30, 2009, 5:12:56 PM11/30/09
to

Excuse moi mais je n'ai pas saisi l'intérêt de ta fonction. De ce que
j'ai compris, elle retourne TRUE si vkCode est l'une de ces touches.
Et ensuite dans ta fonction CALLBACK, tu n'entre pas dans ta condition
si cette fonction IsModifierKey vaut TRUE alors qu'après tu traites le
cas de VK_RMENU et VK_LMENU par exemple.
Si j'ai bien saisi la logique de ta fonction, le traitement de
VK_RMENU et VK_LMENU ne seras jamais fait car si on entre dans la
condition, c'est que vkCode n'est pas l'une de ces touches (entre
autres).
Pourrais-tu m'éclaircir sur ce point ? Et aussi me dire pourquoi la
répétition des touches est quand même prise en compte alors que
j'ai :
// Pour éviter les répétitions
// Bit 30 : Spécifie si la touche est maintenue (si TRUE, on passe
notre chemin)


if (((DWORD)lParam & 0x40000000) != FALSE)

return CallNextHookEx (hHook, nCode, wParam, lParam);

Merci

Christian ASTOR

unread,
Dec 1, 2009, 6:47:10 AM12/1/09
to
On 30 nov, 23:12, Pascal Rito <pascal.r...@gmail.com> wrote:

> Si j'ai bien saisi la logique de ta fonction, le traitement de
> VK_RMENU et VK_LMENU ne seras jamais fait car si on entre dans la
> condition, c'est que vkCode n'est pas l'une de ces touches (entre
> autres).
> Pourrais-tu m'éclaircir sur ce point ?

Si, le traitement sera fait : c'est pour éviter d'enregistrer le
premier appui sur Shift par exemple
(on ne logge que si on a Shif+Touche, pas Shift seul)

>Et aussi me dire pourquoi la
> répétition des touches est quand même prise en compte alors que
> j'ai :
>     // Pour éviter les répétitions
>     // Bit 30 : Spécifie si la touche est maintenue (si TRUE, on passe
> notre chemin)
>     if (((DWORD)lParam & 0x40000000) != FALSE)
>             return CallNextHookEx (hHook, nCode, wParam, lParam);

Le "repeat count", soit HIWORD(lParam) & KF_REPEAT n'est normalement
pas pris en compte par un LowLevel hook, mais bien pris par un hook
clavier classique (avec une DLL)
(je viens de retester les 2 hooks sur XP SP2...)

Pascal Rito

unread,
Dec 6, 2009, 4:37:49 PM12/6/09
to

Pardon pour le temps de réponse, mais j'étais ailleurs ces derniers
temps.
Sinon j'ai tenté quelques manipulations pour m'en sortir avec ce Alt,
et je crois que j'ai réussi à m'en sortir en faisant comme ceci :
http://pastebin.com/m1bbe819
(Je préfère la coloration syntaxique de ce site plutôt que rien du
tout)

Je voudrais surtout que l'on me confirme les lignes 28, 79 et 168,
pour savoir ci ce que j'ai fait fonctionnera bel et bien chez tout le
monde (je pense aux Windoziens NT) ou si ces lignes de codes auront un
résultat différent en fonction des ordinateurs, claviers, etc.

Aussi je voudrais une dernière aide (normalement). Lorsque Caps lock
est sur 'On', et que j'appuie sur '_', cela m'affiche bien '8'. Mais
lorsque je combine 'Shift' + '_', cela m'affiche '_' et non '8'.
Comme régler ce problème ?

Merci.

marc

unread,
Dec 7, 2009, 5:27:57 AM12/7/09
to
On 6 déc, 22:37, Pascal Rito <pascal.r...@gmail.com> wrote:

> Aussi je voudrais une dernière aide (normalement). Lorsque Caps lock
> est sur 'On', et que j'appuie sur '_', cela m'affiche bien '8'. Mais
> lorsque je combine 'Shift' + '_', cela m'affiche '_' et non '8'.
> Comme régler ce problème ?

C'est le comportement normal.. (avec notepad)
Tous les 'case' sont inutiles aussi
Pour Alt, tu te compliques la vie , au lieu de sauter les 'modifier
keys', mais si ça marche sous XP, ça marchera en principe sous NT
(meme noyau)...

Pascal Rito

unread,
Dec 7, 2009, 12:41:54 PM12/7/09
to

Pourrais-tu m'expliquer comment faire plus simplement ? Comment puis-
je éviter les 'case' et aussi comment faire simple avec 'Alt' ?

marc

unread,
Dec 8, 2009, 12:48:26 PM12/8/09
to
Pascal Rito a écrit :

> > Pour Alt, tu te compliques la vie , au lieu de sauter les  'modifier
> > keys', mais si ça marche sous XP, ça marchera en principe sous NT
> > (meme noyau)...
>
> Pourrais-tu m'expliquer comment faire plus simplement ? Comment puis-
> je éviter les 'case' et aussi comment faire simple avec 'Alt' ?

Comme ça a été dit au-dessus pour 'Alt' mais si ta méthode marche,
c'est bon., et pour les 'case', tu les enlèves, vu que GetKeyNameText
() le fait déjà.

0 new messages