ToAscii/ToUnicode dans un hook clavier détruit les touches mortes
Il semble que si vous appelez ToAscii()
ou ToUnicode()
alors que dans un mondial WH_KEYBOARD_LL crochet, et un mort-touche est enfoncée, il va être "détruits".
Par exemple, disons que vous avez configuré votre langue d'entrée dans Windows en espagnol, et vous souhaitez saisir une lettre accentuée à dans un programme. Normalement, vous seriez appuyez sur le guillemet simple touche (la touche morte), puis la lettre "a", puis sur l'écran un caractère accentué à sera affiché, comme prévu.
Mais cela ne fonctionne pas si vous appelez ToAscii()
ou ToUnicode()
dans un hook clavier de bas niveau de la fonction. Il semble que la touche morte est détruit, et donc pas de lettre accentuée à s'affiche sur l'écran. Retrait d'un appel pour les fonctions ci-dessus ne résout le problème... mais malheureusement, j'ai besoin d'être en mesure d'appeler ces fonctions.
J'ai Googlé un peu et bien que beaucoup de gens semblent avoir ce problème, aucune solution satisfaisante n'a été fournie.
Toute aide serait grandement appréciée!
EDIT: je vais appeler ToAscii()
pour convertir le code de touche virtuelle et de scan de code reçu dans ma LowLevelKeyboardProc fonction de raccordement dans la de caractères qui sera affichée sur l'écran de l'utilisateur.
J'ai essayé MapVirtualKey(kbHookData->vkCode, 2)
, mais ce n'est pas "complète" d'une fonction comme ToAscii()
; par exemple, si vous appuyez sur Maj + 2, vous obtiendrez '2', pas '@' (ou quel que soit Maj + 2 va produire pour l'utilisateur du clavier/de la langue).
ToAscii()
est parfait... jusqu'à ce qu'un mort-touche est enfoncée.
EDIT2: Voici la fonction de raccordement, avec pertinence info supprimée:
LRESULT CALLBACK keyboard_LL_hook_func(int code, WPARAM wParam, LPARAM lParam) {
LPKBDLLHOOKSTRUCT kbHookData = (LPKBDLLHOOKSTRUCT)lParam;
BYTE keyboard_state[256];
if (code < 0) {
return CallNextHookEx(keyHook, code, wParam, lParam);
}
WORD wCharacter = 0;
GetKeyboardState(&keyboard_state);
int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
keyboard_state, &wCharacter, 0);
/* If ta == -1, a dead-key was pressed. The dead-key will be "destroyed"
* and you'll no longer be able to create any accented characters. Remove
* the call to ToAscii() above, and you can then create accented characters. */
return CallNextHookEx(keyHook, code, wParam, lParam);
}
Eh bien, personnellement, je suis d'appel ToAscii, mais j'ai lu, il arrive avec ToUnicode, trop. Mon appel est fondamentalement ToAscii(kbHookData->vkCode, kbHookData->scanCode, GetKeyboardState(), &lpchar, 0) dans le WH_KEYBOARD_LL fonction de raccordement. Lorsque le ToAscii appel renvoie -1, cela signifie une mort touche a été pressée... et la touche morte est "détruits" comme je l'ai expliqué ci-dessus.
J'ai supprimé ma réponse, il a été complètement inexacte, fondée sur l'hypothèse que vous faisiez référence à la c-runtime des fonctions permettant de convertir des chaînes de caractères plutôt que des api Win32 pour convertir les scancodes... désolé.
Je m'aiderait beaucoup si vous pouviez décrire le but de ce faire, nous pouvons trouver d'autres solutions à votre problème.
Voir la modifier à ma question d'origine pour plus d'info. 🙂
OriginalL'auteur 00010000 | 2009-12-26
Vous devez vous connecter pour publier un commentaire.
Vous ne devriez pas mélanger les boutons avec des personnages - en supposant que n'importe quel touche/bouton a une représentation de texte (Unicode) est erroné.
Donc:
Essayez de faire une copie de l'état du clavier, de la structure pour empêcher Windows de modifier l'original.
OriginalL'auteur sorin
Appel 'ToAscii fonction deux fois pour un traitement correct des morts-clé, comme dans:
OriginalL'auteur Blue eyes
L'appel de la
ToAscii
ouToUnicode
deux fois, c'est la réponse.J'ai trouvé cela et converti pour Delphi, et ça marche!!!
En fait, votre réponse est la même que @les yeux Bleus ci-dessous :stackoverflow.com/a/3625039/2165463
OriginalL'auteur Martin
Tout à fait un vieux thread. Malheureusement, il ne contient pas la réponse que je cherchais et aucune réponse ne semblait fonctionner correctement. J'ai finalement résolu le problème en cochant la MSB de la
MapVirtualKey
fonction, avant d'appelerToUnicode
/ToAscii
. Semble fonctionner comme un charme:Citant MSDN sur la valeur de retour de
MapVirtualKey
, siMAPVK_VK_TO_CHAR
est utilisé:Dans le cas où il ne pénètre pas dans le cas actuel, la touche est une touche morte. Selon ce que vous souhaitez atteindre, vous pouvez réagir, ou simplement l'ignorer, dans le cas où vous souhaitez seulement écouter de la non-mort de touches. Espérons que cette aide.
Merci, je l'ai eu
Ne fonctionne pas pour les morts caractères qui utilisent la touche "ALT GR" pour l'exemple (ALT droite, comme il produit "CTRL + ALT" message clé). Exemple de français de disposition de clavier en essayant d'ajouter un accent, cet accent sur une lettre : ` = ì
OriginalL'auteur Kristian Kraljic
Je copie le vkCode dans une file d'attente et de faire la conversion à partir d'un autre thread
Cela a l'avantage de ne pas retarder la clé de traitement par le système d'exploitation
OriginalL'auteur battmanux