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

GetKeyNameText me renvoie toujours la lettre 'G'

16 réponses
Avatar
Pascal Rito
Bonjour =E0 tous.
Je suis en train de travailler sur le hook system de l'API Windows et
je me heurte =E0 un probl=E8me.
Comme ToAscii ne g=E8re 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=E0d la longueur de
'G' et inscrit 'G' dans le buffer).

Vois mon code :

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


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

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

10 réponses

1 2
Avatar
Christian ASTOR
On 28 nov, 19:09, Pascal Rito 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("%sn", sBuffer);
Avatar
Pascal Rito
On 28 nov, 19:59, Christian ASTOR wrote:
On 28 nov, 19:09, Pascal Rito 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("%sn", sBuffer);



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 ?
Avatar
Christian ASTOR
On 28 nov, 21:12, Pascal Rito 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.
Avatar
Pascal Rito
On 28 nov, 21:35, Christian ASTOR wrote:
On 28 nov, 21:12, Pascal Rito 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 CreateFi le
> (); 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.



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'éc ran.
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.
Avatar
Pascal Rito
On 28 nov, 21:55, Pascal Rito wrote:
On 28 nov, 21:35, Christian ASTOR wrote:

> On 28 nov, 21:12, Pascal Rito 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 Create File
> > (); je ne suis pas obligé d'utiliser CharToOem(); vu que ce n'est p as
> > pour l'afficher dans la console. N'est-ce pas ?

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

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 ToAs cii 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 ToAs cii 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 j e ne
suis pas sûr de savoir comment l'extraire.
Une petite aide ? Merci.



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 CAP S
LOCK et [CAPS LOCK OFF] le moment où je l'active...

Un complément de solution ? Ou carrément une autre solution ?
Merci
Avatar
Christian ASTOR
On 28 nov, 21:55, Pascal Rito 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;
Avatar
Pascal Rito
On 29 nov, 02:01, Christian ASTOR wrote:
On 28 nov, 21:55, Pascal Rito 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;



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 : Onn");

bAltOn = (DWORD)(GetKeyState(VK_MENU)) & 0x1000;
if(bAltOn == 0x1000) printf("Alt onn");

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é.
Avatar
Christian ASTOR
On 29 nov, 14:48, Pascal Rito 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;
Avatar
Pascal Rito
On 29 nov, 19:39, Christian ASTOR wrote:
On 29 nov, 14:48, Pascal Rito 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;



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 onn");

bAltOn = GetKeyState(VK_MENU) & 0x8000;
if(bAltOn) printf("Alt onn");

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 ?
Avatar
Christian ASTOR
On 29 nov, 20:11, Pascal Rito 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 == v kCode
||
VK_MENU == vkCode || VK_LMENU == vkCode || VK_RMENU == vkCo de;
}
1 2