Compartir a través de


Entrada de teclado (Introducción con Win32 y C++)

El teclado se usa para varios tipos distintos de entrada, entre los que se incluyen:

  • Entrada de caracteres. Texto que el usuario escribe en un documento o cuadro de edición.
  • Métodos abreviados de teclado. Trazos clave que invocan funciones de aplicación; por ejemplo, CTRL + O para abrir un archivo.
  • Comandos del sistema. Trazos clave que invocan funciones del sistema; por ejemplo, ALT + TAB para cambiar las ventanas.

Al pensar en la entrada del teclado, es importante recordar que un trazo de tecla no es el mismo que un carácter. Por ejemplo, presionar la tecla A podría dar lugar a cualquiera de los caracteres siguientes.

  • a
  • A
  • á (si el teclado admite la combinación de diacríticos)

Además, si la tecla ALT se mantiene presionada, al presionar la tecla A se genera ALT+A, que el sistema no trata como un carácter en absoluto, sino como un comando del sistema.

Códigos de clave

Al presionar una tecla, el hardware genera un código de examen. Los códigos de examen varían de un teclado a otro y hay códigos de examen independientes para eventos de tecla arriba y de reducción de teclas. Casi nunca se preocupará por los códigos de examen. El controlador de teclado traduce los códigos de examen en códigos de tecla virtual. Los códigos de clave virtual son independientes del dispositivo. Al presionar la tecla A en cualquier teclado, se genera el mismo código de tecla virtual.

En general, los códigos de clave virtual no corresponden a códigos ASCII ni a ningún otro estándar de codificación de caracteres. Esto es obvio si lo piensa, porque la misma tecla puede generar caracteres diferentes (a, A, á) y algunas teclas, como las teclas de función, no se corresponden con ningún carácter.

Dicho esto, los siguientes códigos de clave virtual se asignan a equivalentes ASCII:

  • De 0 a 9 claves = ASCII '0' – '9' (0x30 – 0x39)
  • Claves A a la Z = ASCII "A" – "Z" (0x41 – 0x5A)

En algunos aspectos, esta asignación es desafortunada, ya que nunca debería pensar en códigos de clave virtual como caracteres, por las razones descritas.

El archivo de encabezado WinUser.h define constantes para la mayoría de los códigos de clave virtual. Por ejemplo, el código de clave virtual de la tecla FLECHA IZQUIERDA es VK_LEFT (0x25). Para obtener la lista completa de códigos de clave virtual, consulte Códigos de clave virtual. No se definen constantes para los códigos de clave virtual que coinciden con los valores ASCII. Por ejemplo, el código de clave virtual de la clave A es 0x41, pero no hay ninguna constante denominada VK_A. En su lugar, use el valor numérico.

mensajes de Key-Down y Key-Up

Al presionar una tecla, la ventana que tiene el foco del teclado recibe uno de los siguientes mensajes.

El WM_SYSKEYDOWN mensaje indica una clave del sistema, que es un trazo de tecla que invoca un comando del sistema. Hay dos tipos de clave del sistema:

  • ALT + cualquier tecla
  • F10

La tecla F10 activa la barra de menús de una ventana. Varias combinaciones de teclas ALT invocan comandos del sistema. Por ejemplo, ALT + TAB cambia a una nueva ventana. Además, si una ventana tiene un menú, se puede usar la tecla ALT para activar elementos de menú. Algunas combinaciones de teclas ALT no hacen nada.

Todos los demás trazos de clave se consideran claves no del sistema y generan el mensaje WM_KEYDOWN . Esto incluye las teclas de función distintas de F10.

Al liberar una clave, el sistema envía un mensaje de inicio de clave correspondiente:

Si mantiene presionada una tecla lo suficientemente larga como para iniciar la característica de repetición del teclado, el sistema envía varios mensajes de tecla abajo, seguidos de un único mensaje de tecla arriba.

En los cuatro mensajes de teclado descritos hasta ahora, el parámetro wParam contiene el código de tecla virtual de la tecla. El parámetro lParam contiene información variada empaquetada en 32 bits. Normalmente no necesita la información en lParam. Una marca que podría ser útil es el bit 30, la marca "estado de clave anterior", que se establece en 1 para los mensajes repetidos de tecla abajo.

Como su nombre indica, los trazos de clave del sistema están pensados principalmente para su uso por parte del sistema operativo. Si intercepta el mensaje de WM_SYSKEYDOWN , llame a DefWindowProc después. De lo contrario, impedirá que el sistema operativo controle el comando.

Mensajes de caracteres

Los trazos clave se convierten en caracteres por la función TranslateMessage , que vimos por primera vez en el módulo 1. Esta función examina los mensajes de tecla hacia abajo y los traduce en caracteres. Para cada carácter que se genera, la función TranslateMessage coloca un WM_CHAR o WM_SYSCHAR mensaje en la cola de mensajes de la ventana. El parámetro wParam del mensaje contiene el carácter UTF-16.

Como puede adivinar, WM_CHAR mensajes se generan a partir de mensajes de WM_KEYDOWN , mientras que los mensajes de WM_SYSCHAR se generan a partir de mensajes de WM_SYSKEYDOWN . Por ejemplo, supongamos que el usuario presiona la tecla MAYÚS seguida de la tecla A. Suponiendo un diseño de teclado estándar, obtendría la siguiente secuencia de mensajes:

WM_KEYDOWN: MAYÚS
WM_KEYDOWN: A
WM_CHAR: "A"

Por otro lado, la combinación ALT + P generaría:

WM_SYSKEYDOWN: VK_MENU
WM_SYSKEYDOWN: 0x50
WM_SYSCHAR: 'p'
WM_SYSKEYUP: 0x50
WM_KEYUP: VK_MENU

(El código de clave virtual de la clave ALT se denomina VK_MENU por motivos históricos).

El mensaje WM_SYSCHAR indica un carácter del sistema. Al igual que con WM_SYSKEYDOWN, normalmente debe pasar este mensaje directamente a DefWindowProc. De lo contrario, puede interferir con los comandos del sistema estándar. En concreto, no trate WM_SYSCHAR como texto que el usuario ha escrito.

El WM_CHAR mensaje es lo que normalmente se piensa como entrada de caracteres. El tipo de datos del carácter es wchar_t, que representa un carácter Unicode UTF-16. La entrada de caracteres puede incluir caracteres fuera del intervalo ASCII, especialmente con diseños de teclado que se usan normalmente fuera del Estados Unidos. Puede probar diferentes diseños de teclado instalando un teclado regional y, a continuación, usando la característica Teclado en pantalla.

Los usuarios también pueden instalar un Editor de métodos de entrada (IME) para escribir scripts complejos, como caracteres japoneses, con un teclado estándar. Por ejemplo, con un IME japonés para escribir el carácter katakana カ (ka), es posible que reciba los siguientes mensajes:

WM_KEYDOWN: VK_PROCESSKEY (la clave PROCESS de IME)
WM_KEYUP: 0x4B
WM_KEYDOWN: VK_PROCESSKEY
WM_KEYUP: 0x41
WM_KEYDOWN: VK_PROCESSKEY
WM_CHAR: カ
WM_KEYUP: VK_RETURN

Algunas combinaciones de teclas CTRL se traducen en caracteres de control ASCII. Por ejemplo, CTRL+A se traduce al carácter ctrl-A (SOH) ASCII (valor ASCII 0x01). Para la entrada de texto, normalmente debe filtrar los caracteres de control. Además, evite usar WM_CHAR para implementar métodos abreviados de teclado. En su lugar, use WM_KEYDOWN mensajes; o incluso mejor, use una tabla de aceleradores. Las tablas de acelerador se describen en el tema siguiente, Tablas de acelerador.

En el código siguiente se muestran los mensajes de teclado principales en el depurador. Pruebe a jugar con diferentes combinaciones de pulsación de tecla y vea qué mensajes se generan.

Nota

Asegúrese de incluir wchar.h o de lo contrario swprintf_s no estará definido.

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    wchar_t msg[32];
    switch (uMsg)
    {
    case WM_SYSKEYDOWN:
        swprintf_s(msg, L"WM_SYSKEYDOWN: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_SYSCHAR:
        swprintf_s(msg, L"WM_SYSCHAR: %c\n", (wchar_t)wParam);
        OutputDebugString(msg);
        break;

    case WM_SYSKEYUP:
        swprintf_s(msg, L"WM_SYSKEYUP: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_KEYDOWN:
        swprintf_s(msg, L"WM_KEYDOWN: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_KEYUP:
        swprintf_s(msg, L"WM_KEYUP: 0x%x\n", wParam);
        OutputDebugString(msg);
        break;

    case WM_CHAR:
        swprintf_s(msg, L"WM_CHAR: %c\n", (wchar_t)wParam);
        OutputDebugString(msg);
        break;

    /* Handle other messages (not shown) */

    }
    return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}

Mensajes de teclado varios

La mayoría de las aplicaciones pueden omitir de forma segura algunos otros mensajes de teclado.

  • El WM_DEADCHAR mensaje se envía para una clave combinada, como un diacrítico. Por ejemplo, en un teclado de idioma español, al escribir énfasis (') seguido de E se genera el carácter é. El WM_DEADCHAR se envía para el carácter de énfasis.
  • El mensaje de WM_UNICHAR está obsoleto. Permite que los programas ANSI reciban la entrada de caracteres Unicode.
  • El carácter WM_IME_CHAR se envía cuando un IME traduce una secuencia de pulsación de teclas en caracteres. Se envía además del mensaje de WM_CHAR habitual.

Estado del teclado

Los mensajes de teclado están controlados por eventos. Es decir, recibe un mensaje cuando sucede algo interesante, como una pulsación de teclas, y el mensaje le indica lo que acaba de pasar. Pero también puede probar el estado de una clave en cualquier momento llamando a la función GetKeyState .

Por ejemplo, considere cómo detectaría la combinación de clic del mouse izquierdo + tecla ALT. Puede realizar un seguimiento del estado de la clave ALT escuchando mensajes de trazo de tecla y almacenando una marca, pero GetKeyState le ahorra el problema. Cuando reciba el mensaje WM_LBUTTONDOWN , llame a GetKeyState de la siguiente manera:

if (GetKeyState(VK_MENU) & 0x8000)
{
    // ALT key is down.
}

El mensaje GetKeyState toma un código de clave virtual como entrada y devuelve un conjunto de marcas de bits (en realidad solo dos marcas). El valor 0x8000 contiene la marca de bits que comprueba si la tecla está presionada actualmente.

La mayoría de los teclados tienen dos teclas ALT, izquierda y derecha. En el ejemplo anterior se comprueba si se presiona cualquiera de ellas. También puede usar GetKeyState para distinguir entre las instancias izquierda y derecha de las teclas ALT, MAYÚS o CTRL. Por ejemplo, el código siguiente comprueba si se presiona la tecla ALT derecha.

if (GetKeyState(VK_RMENU) & 0x8000)
{
    // Right ALT key is down.
}

La función GetKeyState es interesante porque informa de un estado de teclado virtual . Este estado virtual se basa en el contenido de la cola de mensajes y se actualiza a medida que quita los mensajes de la cola. A medida que el programa procesa mensajes de ventana, GetKeyState le proporciona una instantánea del teclado en el momento en que se puso en cola cada mensaje. Por ejemplo, si se WM_LBUTTONDOWN el último mensaje de la cola, GetKeyState notifica el estado del teclado en el momento en que el usuario hizo clic en el botón del mouse.

Dado que GetKeyState se basa en la cola de mensajes, también omite la entrada del teclado que se envió a otro programa. Si el usuario cambia a otro programa, GetKeyState omite cualquier tecla que se envíe a ese programa. Si realmente quieres conocer el estado físico inmediato del teclado, hay una función para eso: GetAsyncKeyState. Sin embargo, para la mayoría del código de interfaz de usuario, la función correcta es GetKeyState.

Siguientes

Tablas de aceleradores