ToAscii && ToUnicode ( Y las versiones Ex )
Posted by Ahharu | Posted in Programación | Posted on 02:42
Dicese, que un buen día tuve que retomar algo muy...muy...muy abandonado como lo es DIKE, los que recuerden sabrán que DIKE tiene un problema en Windows 7 con los acentos, ya que los desactiva al usuario aunque los loguee correctamente, después de 2 días investigando y probando llegue a la solución del problema, la cual ni siquiera documentada esta, así que a explicar.
ToAscii && ToAsciiEx && ToUnicode && ToUnicodeEx
Estas funciones estan diseñadas para realizar la "traducción" de códigos de teclas virtuales + flags de estas + estado del teclado + configuración regional del teclado, a sus correspondientes teclas, estas proveen un mecanismo de detección de la tecla bastante efectivo y preciso, el problema de estas es el manejo de "Dead Keys".
Dead Keys
Las Dead Keys son teclas especiales que actúan como modificadoras de una tecla base, un claro ejemplo de esto son las tildes, tenemos como base la tecla "a" y como dead key "´", siendo que la misma no se muestra a menos de ser presionada nuevamente, en combinación con una tecla base como "a" tenemos el resultado "á", esto significa que la información acerca de las dead keys presionadas es almacenada en un buffer.
ToAscii && ToAsciiEx && ToUnicode && ToUnicodeEx
Estas funciones estan diseñadas para realizar la "traducción" de códigos de teclas virtuales + flags de estas + estado del teclado + configuración regional del teclado, a sus correspondientes teclas, estas proveen un mecanismo de detección de la tecla bastante efectivo y preciso, el problema de estas es el manejo de "Dead Keys".
Dead Keys
Las Dead Keys son teclas especiales que actúan como modificadoras de una tecla base, un claro ejemplo de esto son las tildes, tenemos como base la tecla "a" y como dead key "´", siendo que la misma no se muestra a menos de ser presionada nuevamente, en combinación con una tecla base como "a" tenemos el resultado "á", esto significa que la información acerca de las dead keys presionadas es almacenada en un buffer.
Dead Keys en el Buffer
Cuando hacemos uso de ToAscii, ToUnicode, etc... este toma la información del buffer del teclado que posee y realiza la traducción de la tecla segun los diferentes que toma, en determinados casos cuando se procesan dead keys la funcion falla y al realizar la traducción realiza una limpieza de este buffer, removiendo la dead key, esto constituye el que la tecla no se envíe como un evento del teclado a las demás aplicaciones, la documentación oficialmente dice:
The parameters supplied to the ToAsciiEx function might not be sufficient to translate the virtual-key code, because a previous dead key is stored in the keyboard layout.
En este caso el problema que nos causan las dead keys al estar presentes es el tener que procesarlas, en este caso lo que tenemos que hacer es intentar el dejar el buffer con la misma información que poseía cuando intentamos procesar la dead key y pasar a la siguiente tecla que vamos a loguear. Oficialmente no existe una documentación que mencione el proceso, pero gracias a un programador de microsoft y su blog ( lo siento, perdí el enlace ) el mismo nos menciona como.
El truco es el realizar múltiples llamadas a ToAscii, etc... con la misma información de la dead key hasta que el valor de retorno sea mayor a 0, esto logra limpiar el buffer para poder posteriormente re introducir la dead key en combinación con una tecla base si llegase a ser el caso. Una vez "procesada" la dead key lo que debemos hacer es restablecer el estado del buffer usando la información inicial ( la de la dead key ) una vez procesada la tecla base, logrando limpiar el buffer totalmente:
GetKeyboardState( btKeybState );
hklKeybLayout = GetKeyboardLayout( GetWindowThreadProcessId( GetForegroundWindow(), NULL));
iRet = ToAsciiEx( iKey, iKeyData, btKeybState, (LPWORD)szKeyName, 0, hklKeybLayout);
if (iRet == -1) {
iLastKey = iKey;
iLastKeyData = iKeyData;
while (ToAsciiEx( iKey, iKeyData, btKeybState, (LPWORD)szKeyName, 0, hklKeybLayout) <> 0)
WriteToFile( iRet, szKeyName);
if (iLastKey != 0) {
memset( btKeybState, 0, TWOKEY_KEYB_SIZE + 1);
ToAsciiEx( iLastKey, iLastKeyData, btKeybState, (LPWORD)szKeyName, 0, hklKeybLayout);
iLastKey = 0;
}
return;
Aunque la solución parezca simple, si no esta documentada ( y no lo esta ) es un verdadero martirio el encontrar la solución y sobre todo algo de documentación al respecto que pueda ayudar, como complemento podemos elegir el no procesar ciertas teclas que de por si pueden ser mejor traducidas con "GetKeyNameText", en código es algo como:
#define IS_SPECIAL_CHAR( x ) ((ispunct(x) != 0 && iscntrl(x) != 0 && isalnum(x) == 0) || ((x >= VK_LBUTTON && x <= VK_HELP && x != VK_SPACE) || (x >= VK_LWIN && x <= VK_NUMPAD9) || (x >= VK_F1 && x <= VK_F12))) if (IS_SPECIAL_CHAR( iKey ) != 0) { iRet = GetKeyNameText( iKeyData, szKeyName, 32); if (iRet > 0)
WriteToFile( "[%s]", szKeyName);
return;
}
Ya con esto debemos tener un manejo casi perfecto de las dead keys ;).
PD: DKEY esta terminado ya pero en private release and testing.
Saludos.
Att: Iker


Comments (0)
Publicar un comentario en la entrada