Cómo simular la entrada del teclado para todas las aplicaciones
La forma en que los programas de Windows obtienen la entrada del teclado: la entrada del teclado se pasa al proceso de ventana del programa en forma de mensajes. De hecho, cuando se aprende por primera vez sobre los mensajes, el teclado es un ejemplo obvio del tipo de información que los mensajes deben transmitir a una aplicación.
Windows utiliza ocho mensajes diferentes para comunicar diferentes eventos del teclado. Esto puede parecer demasiado, pero (como hemos visto) el programa puede ignorar al menos la mitad de estos mensajes sin ningún problema. Además, en la mayoría de los casos, estos mensajes contienen más información del teclado de la que necesita el programa. Parte del manejo de un teclado es reconocer qué información es importante y cuál no.
2. Conceptos básicos del teclado
Aunque en muchos casos, las aplicaciones pueden usar el mouse para ingresar información, el teclado sigue siendo un dispositivo de entrada importante e irreemplazable en la PC.
Cuando se utiliza un teclado como dispositivo de entrada, se genera una interrupción cada vez que el usuario presiona o suelta una tecla, activando el controlador de teclado KEYBOARD.DRV para manejar las interrupciones del teclado. El programa KEYBOARD.DRV codifica diferentes operaciones de usuario y luego llama al módulo de usuario de Windows USER.EXE para generar mensajes de teclado y enviarlos a la cola de mensajes para su procesamiento.
1. Códigos de escaneo y códigos virtuales
Los códigos de escaneo corresponden a diferentes teclas del teclado. Cada tecla genera un código de escaneo único cuando se presiona o se suelta. Los códigos de escaneo dependen del dispositivo de hardware específico, es decir, diferentes máquinas pueden generar códigos de escaneo diferentes cuando se presiona o suelta la misma tecla. Es común que los programas utilicen código virtual independiente del dispositivo definido por el sistema de Windows. Mientras se presiona una tecla se genera un código de escaneo, el controlador de teclado KEYBOARD.DRV intercepta el código de escaneo de la tecla y lo convierte en el código virtual correspondiente, y luego codifica el código de escaneo y el código virtual juntos para formar información del teclado. Por lo tanto, el mensaje final del teclado enviado a la cola de mensajes contiene el código de escaneo y el código ficticio.
Los códigos virtuales de uso común se definen en el archivo WINDOWS.H. Los valores, símbolos constantes y significados de los códigos virtuales de uso común se muestran en la tabla.
Valor (hexadecimal) Significado del símbolo constante
01 VK_LBUTTON botón izquierdo del mouse
02 VK_RBUTTON botón derecho del mouse
03 VK_CANCEL Tecla Break Break
04 VK_MBUTTON Botón central del ratón
05-07 -- Indefinido
08 Tecla VK_BACK (Retroceso)
09 Tecla Tabulador VK_TAB
0A-0B -- Indefinido
08 Tecla VK_BACK (Retroceso)
09 Tecla Tabulador VK_TAB
0A-0B -- Indefinido
0A-0B -- Indefinido
0A-0B Indefinido
0C VK_CLEAR borrar clave
0D VK_RETURN Introducir claves
0E-0F -- indefinido
10 Tecla Mayús VK_SHIFT
11 VK_CONTROL presiona la tecla Ctrl
12 VK_MENU presiona la tecla Alt
13 VK_PAUSE Tecla de pausa
14 VK_CAPTIAL Tecla Bloq Mayús
15 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Clave 19 -- Sistema de caracteres chinos reservados
1A -- Indefinido
1B VK_ESCAPE Tecla Esc
1C-1F -- Sistema de caracteres chinos reservado
1B VK_ESCAPE Tecla Esc
1C-1F. Sistema de caracteres chinos reservado
20 Tecla de espacio VK_SPACE
21 Tecla VK_PRIOR PageUp
22 Tecla VK_NEXT PageDown
23 Tecla de fin VK_END p >
24 Tecla de inicio VK_HOME
25- Tecla de retención OEM
2B Tecla de ejecución VK_EXECUTE
2C Tecla de impresión de pantalla VK_SNAPSHOT
2D VK_INSERT insertar clave
2E VK_DELETE eliminar clave
2F VK_HELP clave de ayuda
30---.
39 VK_0-VK_9 Teclas numéricas 0-9
3A-40 -- Indefinido
41-5A VK_A-VK_Z Teclas de letras A-Z
5B-5F - - Indefinido
60-69 VK_NUMPAD0-VK_NUMPAD9 Teclas numéricas 0-
6A VK_MULTIPLY * tecla (multiplicación)
6B VK_ADD + tecla (suma)
p>6C VK_SEPAPATOR Tecla separadora
6E VK_SUBTRACT - Tecla (signo menos)
6F VK_DECIMAL Tecla (decimal)
70-87 VK_DIVIDE / Tecla (división)
88-8F VK_F1-VK_F24 Teclas de función F1-F24
90 Tecla de bloqueo numérico VK_NUMBERLOCK
91 Tecla de bloqueo de desplazamiento VK_SCROLL
92-B9 -- Indefinido
BA-C0 -- OEM reservado
C1-DA -- Indefinido
DB_E4 -- OEM reservado p>
E5 -- Indefinido
E6 -- OEM reservado
E7-E8 -- Indefinido
E9-F5 - - OEM reservado p>
F6-FE - Indefinido
2. Enfoque de entrada
Al mismo tiempo, es posible que se estén ejecutando varios programas diferentes en Windows. Esto significa que existen varias ventanas en. al mismo tiempo. En este momento, el teclado está ocupado por varias ventanas, pero solo una ventana puede recibir mensajes del teclado. Esta ventana que puede recibir mensajes del teclado se llama ventana con foco de entrada.
La ventana con foco de entrada debe ser la ventana actualmente activa o una ventana secundaria de la ventana activa, con su título y borde resaltados para distinguirla de otras ventanas. También puede ser un ícono en lugar de la ventana con foco de entrada, en cuyo caso Windows también enviará información al ícono, pero en un formato ligeramente diferente.
Un procedimiento de ventana puede hacer que un formulario gane o pierda el foco de entrada enviando mensajes WM_SETFOCUS y WM_KILLFOCUS. Los programas también pueden determinar cuándo un formulario gana o pierde el foco de entrada capturando los mensajes WM_SETFOCUS y WM_KILLFOCUS. El mensaje WM_SETFOCUS indica que la ventana está ganando el foco de entrada y el mensaje WM_KILLFOCUS indica que la ventana está perdiendo el foco de entrada.
3. Mensajes de teclado
Los mensajes de teclado se dividen en mensajes clave del sistema y mensajes clave que no son del sistema. La información clave del sistema es la información clave generada por la combinación de la tecla de popa y otras teclas. El mensaje WM_SYSKEYDOWN se genera cuando se presiona la tecla del sistema y el mensaje WM_SYSKEYUP se genera cuando se suelta la tecla del sistema. Las combinaciones de teclas que consisten en el botón izquierdo y otras teclas se utilizan a menudo para seleccionar entre menús de programas y menús del sistema, o para cambiar entre diferentes programas. Por lo tanto, la información clave del sistema debe dejarse en manos de Windows. Los programas escritos por el usuario generalmente no procesan información clave del sistema, sino que la envían a la función DefWindowProc. Si el usuario desea procesar la información de la clave del sistema, debe enviarla a la función DefWindowProc después de procesar la información de la clave del sistema para que el sistema Windows pueda funcionar correctamente.
Alguna información clave se puede convertir en información de caracteres, como teclas de letras, teclas numéricas, etc. Algunas teclas solo generan información de clave pero no información de caracteres, como la tecla Mayús, la tecla Insertar, etc. La función TranslateMessage en el bucle de mensajes puede convertir información clave en información de caracteres.
Cuando la función GetMessage captura el mensaje WM_SYSKEYDOWN o el mensaje WM_KEYDOWN, la función TranslateMessage determinará si la clave que generó el mensaje se puede convertir en un mensaje de caracteres. Si es así, el mensaje se convertirá en un mensaje de caracteres y luego el carácter convertido. El mensaje se enviará a través de la función DispatchMessage. Enviado a la cola de mensajes. Hay cuatro tipos de información de caracteres***, como se muestra en la siguiente tabla.
Caracteres caracteres del sistema caracteres que no son del sistema
Caracteres binarios WM_SYSCHAR WM_CHAR
Caracteres muertos WM_SYSDEADCHAR WM_DEADCHAR
Esto es causado por algunos teclados especiales Windows generalmente ignora los mensajes generados por caracteres inactivos causados por pulsaciones de teclas. Windows generalmente ignora los mensajes generados por caracteres inactivos.
Los mensajes de Windows generalmente se pasan a los controladores de mensajes a través de variables de estructura MSG. Para mensajes de teclado, los campos más importantes en las variables de estructura MSG son los campos lParam y wParam. Para información que no es de caracteres, el campo wParam almacena el código de clave virtual de la clave; para información de caracteres, el campo wParam no almacena el código ASCII del carácter. De hecho, una variable lParam de 32 bits se divide en seis partes, que registran la siguiente información relevante: el número de repeticiones, el código de escaneo OEM, el indicador de clave extendido, el indicador de clave relacionado, el estado de la última pulsación de tecla y el estado. de la última pulsación de tecla. El significado de cada bit en el campo lParam se muestra en la tabla.
Significado del bit
0-15 Número acumulado de repeticiones de teclas
16-23 Código de escaneo OEM
24 Si se trata de un modelo extendido tecla
p>
25-28 Indefinido
Si 29 es una tecla asociada y si la tecla Alt se presiona al mismo tiempo.
30 Último estado de la clave, 0 significa que se levantó el último estado de la clave, 1 significa que se presionó el último estado de la clave
31 Estado de transición
La secuencia de pulsación de teclas es diferente y la información generada también es diferente. Por ejemplo, al presionar y soltar la tecla 1, el proceso de lectura producirá secuencialmente los tres datos que se muestran en la tabla. Mensaje generado al presionar la tecla 1 y el valor de wParam
Mensaje valor de la variable wParam
WM_KEYDOWN código virtual 1
WM_CHAR código ASCII "1"
WM_KEYUP código ficticio 1
Si presiona la tecla Shift y luego presiona y suelta la tecla 1, la información que se muestra en la tabla se genera en secuencia. Información generada al presionar 1 y valor de wParam después de presionar la tecla Shift
Información valor de la variable wParam
Código virtual WM_KEYDOWN VK_SHIFT
Código virtual WM_KEYDOWN VK_1
WM_CHAR código ASCII "1"
WM_KEYUP código virtual VK_1
WM_KEYUP código virtual VK_SHIF
Ejemplo de aplicación de teclado
A continuación se muestra Un ejemplo de aplicación que ilustra cómo manejar mensajes de teclado en programación real.
#include
#include
//Variables globales
RECT rc //Registra el área rectangular del desplazamiento; screen
int xChar, yChar; //Coordenadas del punto de entrada de texto
WNDCLASSEX wnd; //Variable de estructura de clase de ventana
char szAppName[ ] = "Programa de monitoreo de mensajes de teclado";//Nombre de clase de ventana
/Declaración de función
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL MyRegisterClass (HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance,int iCmdShow);
//Función: WinMain
//Rol: Función de entrada
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow)
{
MSG msg;
if( !MyRegisterClass( hInstance))
{
return FALSE;
}
if(!InitInstance(hInstance,iCmdShow))
{
devuelve FALSO;
}
mientras (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg );
}
return msg.wParam;
}
// Función: ShowKey
// Propósito: mostrar información clave en la ventana
void ShowKey (HWND hwnd, int iType ,char * szMessage,WPARAM wParam, LPARAM lParam)
{
Carbón estático *szFormat[2] ={"%-14s %3d %c %6u %4d %5s % 5s %6s %6s",
"%-14s %3d %c %6u %4d %5s %5s %6s %6s" };
char szBuffer[80];
HDC hdc;
ScrollWindowEx(hwnd, 0, -yChar, &rc,&rc,NULL,NULL,SW_INVALIDATE).
hdc = GetDC (hwnd)
p>SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT));
TextOut (hdc,
xChar,
rc.bottom - yChar,
p>szBuffer,
wsprintf szBuffer,
szFormat[iType],
szMessage, //mensaje p>
wParam, //v
código de clave virtual
(BYTE) (iType ?wParam :' '), // Mostrar valor del carácter
LOWORD (lParam), // Número de repeticiones
HIWORD (lParam) & 0xFF, // Código de escaneo de teclado OEM
// Determinar si se deben usar las teclas extendidas del teclado mejorado
(PSTR) (0x01000000 & lParam ?Sí ":"No "),
//Determinar si usar la tecla ALT al mismo tiempo
(PSTR) (0x20000000 & lParam ? "Sí": "No") ,
( PSTR) (0x40000000 & lParam ?"Press" : "Lift"),
//Juzga la pulsación de tecla anterior
(PSTR) (0x80000000 & lParam ? "pressed" : "raised"))
//¿Juzgar el estado de transición?
);
ReleaseDC (hwnd, hdc); ? p>
ValidateRect (hwnd, NULL ?
}
// Función: WndProc
/ / Función: Procesar mensajes desde la ventana principal
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static char szTop[] = "Caracteres clave del mensaje Conteo repetido Código de escaneo Código de extensión ALT Estado anterior Estado de conversión";
static char szUnd[] = "_______ __ ____ _____ ______ ___ _______ ______"; p>
/En ventana Mostrar texto como título del mensaje
HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
switch (iMsg)
{
case WM_CREATE: //Creación de ventana de procesamiento&tm);
xChar = tm.WM_CREATE: //Creación de ventana de procesamiento&tm);