Condividi tramite


Input da tastiera (Introduzione a Win32 e C++)

La tastiera viene usata per diversi tipi distinti di input, tra cui:

  • Input carattere. Testo digitato dall'utente in un documento o in una casella di modifica.
  • Tasti di scelta rapida. Tratti chiave che richiamano le funzioni dell'applicazione; ad esempio CTRL+O per aprire un file.
  • Comandi di sistema. Tratti chiave che richiamano le funzioni di sistema; ad esempio ALT + TAB per cambiare finestra.

Quando si pensa all'input da tastiera, è importante ricordare che un tratto del tasto non è uguale a un carattere. Ad esempio, la pressione del tasto A potrebbe comportare uno dei caratteri seguenti.

  • a
  • A
  • á (se la tastiera supporta la combinazione di segni diacritici)

Inoltre, se il tasto ALT viene premuto, premendo il tasto A viene generato ALT+A, che il sistema non considera affatto un carattere, ma piuttosto come comando di sistema.

Codici chiave

Quando si preme un tasto, l'hardware genera un codice di analisi. I codici di analisi variano da una tastiera a quella successiva e sono disponibili codici di analisi separati per gli eventi di tasti su e di tasto giù. Non ti interessa quasi mai i codici di scansione. Il driver della tastiera converte i codici di analisi in codici di tasto virtuale. I codici di chiave virtuale sono indipendenti dal dispositivo. Premendo il tasto A su qualsiasi tastiera viene generato lo stesso codice di tasto virtuale.

In generale, i codici di chiave virtuale non corrispondono a codici ASCII o ad altri standard di codifica dei caratteri. Ciò è ovvio se si pensa, perché la stessa chiave può generare caratteri diversi (a, A, á) e alcuni tasti, ad esempio i tasti funzione, non corrispondono ad alcun carattere.

Detto questo, i codici di chiave virtuale seguenti eseguono il mapping agli equivalenti ASCII:

  • Da 0 a 9 chiavi = ASCII '0' - '9' (0x30 - 0x39)
  • Tasti da A a Z = ASCII 'A' - 'Z' (0x41 - 0x5A)

Per alcuni aspetti, questo mapping è sfortunato, perché non è mai consigliabile considerare i codici di chiave virtuale come caratteri, per i motivi illustrati.

Il file di intestazione WinUser.h definisce le costanti per la maggior parte dei codici di chiave virtuale. Ad esempio, il codice della chiave virtuale per il tasto FRECCIA SINISTRA è VK_LEFT (0x25). Per l'elenco completo dei codici di chiave virtuale, vedere Codici di chiave virtuale. Non vengono definite costanti per i codici di chiave virtuale che corrispondono ai valori ASCII. Ad esempio, il codice della chiave virtuale per la chiave A è 0x41, ma non esiste alcuna costante denominata VK_A. Usare invece solo il valore numerico.

messaggi Key-Down e Key-Up

Quando si preme un tasto, la finestra con lo stato attivo della tastiera riceve uno dei messaggi seguenti.

Il messaggio WM_SYSKEYDOWN indica una chiave di sistema, ovvero un tratto di chiave che richiama un comando di sistema. Esistono due tipi di chiave di sistema:

  • ALT + qualsiasi tasto
  • F10

Il tasto F10 attiva la barra dei menu di una finestra. Varie combinazioni di tasti ALT richiamano i comandi di sistema. Ad esempio, ALT + TAB passa a una nuova finestra. Inoltre, se una finestra ha un menu, è possibile usare il tasto ALT per attivare le voci di menu. Alcune combinazioni di tasti ALT non eseguono alcuna operazione.

Tutti gli altri tratti chiave sono considerati chiavi non di sistema e producono il messaggio WM_KEYDOWN . Sono inclusi i tasti di funzione diversi da F10.

Quando si rilascia una chiave, il sistema invia un messaggio di key-up corrispondente:

Se tieni premuto un tasto abbastanza a lungo per avviare la funzionalità di ripetizione della tastiera, il sistema invia più messaggi di tasto in giù, seguiti da un singolo messaggio di tasto su.

In tutti e quattro i messaggi della tastiera illustrati finora, il parametro wParam contiene il codice di tasto virtuale del tasto. Il parametro lParam contiene alcune informazioni varie compresse in 32 bit. In genere non sono necessarie le informazioni in lParam. Un flag che potrebbe essere utile è bit 30, il flag "stato della chiave precedente", che è impostato su 1 per i messaggi di tasti ripetuti.

Come suggerisce il nome, i tratti chiave di sistema sono destinati principalmente all'uso da parte del sistema operativo. Se si intercetta il messaggio di WM_SYSKEYDOWN , chiamare DefWindowProc in seguito. In caso contrario, si impedisce al sistema operativo di gestire il comando.

Messaggi di carattere

I tratti chiave vengono convertiti in caratteri dalla funzione TranslateMessage , illustrata per la prima volta nel Modulo 1. Questa funzione esamina i messaggi chiave-down e li converte in caratteri. Per ogni carattere generato, la funzione TranslateMessage inserisce un messaggio WM_CHAR o WM_SYSCHAR nella coda di messaggi della finestra. Il parametro wParam del messaggio contiene il carattere UTF-16.

Come si può immaginare, WM_CHAR messaggi vengono generati da messaggi di WM_KEYDOWN , mentre WM_SYSCHAR messaggi vengono generati da messaggi di WM_SYSKEYDOWN . Si supponga, ad esempio, che l'utente preme il tasto MAIUSC seguito dal tasto A. Supponendo un layout di tastiera standard, si otterrebbe la sequenza di messaggi seguente:

WM_KEYDOWN: MAIUSC
WM_KEYDOWN: A
WM_CHAR: 'A'

D'altra parte, la combinazione ALT + P genera:

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

Il codice della chiave virtuale per la chiave ALT è denominato VK_MENU per motivi cronologici.

Il messaggio WM_SYSCHAR indica un carattere di sistema. Come per WM_SYSKEYDOWN, in genere è consigliabile passare questo messaggio direttamente a DefWindowProc. In caso contrario, è possibile interferire con i comandi di sistema standard. In particolare, non considerare WM_SYSCHAR come testo digitato dall'utente.

Il messaggio WM_CHAR è quello che normalmente si pensa come input di caratteri. Il tipo di dati per il carattere è wchar_t, che rappresenta un carattere Unicode UTF-16. L'input di caratteri può includere caratteri esterni all'intervallo ASCII, in particolare con i layout della tastiera comunemente usati al di fuori del Stati Uniti. È possibile provare layout di tastiera diversi installando una tastiera a livello di area e quindi usando la funzionalità Tastiera su schermo.

Gli utenti possono anche installare un IME (Input Method Editor) per immettere script complessi, ad esempio caratteri giapponesi, con una tastiera standard. Ad esempio, usando un IME giapponese per immettere il carattere katakana カ (ka), è possibile che vengano visualizzati i messaggi seguenti:

WM_KEYDOWN: VK_PROCESSKEY (chiave processo IME)
WM_KEYUP: 0x4B
WM_KEYDOWN: VK_PROCESSKEY
WM_KEYUP: 0x41
WM_KEYDOWN: VK_PROCESSKEY
WM_CHAR: カ
WM_KEYUP: VK_RETURN

Alcune combinazioni di tasti CTRL vengono convertite in caratteri di controllo ASCII. Ad esempio, CTRL+A viene convertito nel carattere ASCII CTRL-A (SOH) (valore ASCII 0x01). Per l'input di testo, in genere è consigliabile filtrare i caratteri di controllo. Evitare inoltre di usare WM_CHAR per implementare i tasti di scelta rapida. Usare invece WM_KEYDOWN messaggi; o ancora meglio, usare una tabella di acceleratore. Le tabelle di acceleratore sono descritte nell'argomento successivo, Tabelle acceleratori.

Il codice seguente visualizza i messaggi principali della tastiera nel debugger. Provare a giocare con combinazioni di tasti diversi e vedere quali messaggi vengono generati.

Nota

Assicurarsi di includere wchar.h o altrimenti swprintf_s sarà indefinito.

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);
}

Messaggi di tastiera vari

Alcuni altri messaggi da tastiera possono essere ignorati dalla maggior parte delle applicazioni.

  • Il messaggio WM_DEADCHAR viene inviato per una chiave di combinazione, ad esempio un diacritico. Ad esempio, su una tastiera spagnola, digitando accento (') seguito da E produce il carattere é. Il WM_DEADCHAR viene inviato per il carattere accentato.
  • Il messaggio WM_UNICHAR è obsoleto. Consente ai programmi ANSI di ricevere l'input dei caratteri Unicode.
  • Il carattere WM_IME_CHAR viene inviato quando un IME converte una sequenza di sequenza di tasti in caratteri. Viene inviato oltre al normale messaggio di WM_CHAR .

Stato della tastiera

I messaggi della tastiera sono basati su eventi. Questo significa che viene visualizzato un messaggio quando accade qualcosa di interessante, ad esempio una pressione del tasto e il messaggio indica cosa è successo. È anche possibile testare lo stato di una chiave in qualsiasi momento chiamando la funzione GetKeyState .

Si consideri, ad esempio, come rilevare la combinazione del mouse a sinistra fare clic su + TASTO ALT. È possibile tenere traccia dello stato della chiave ALT ascoltando i messaggi del tratto di chiave e archiviando un flag, ma GetKeyState salva i problemi. Quando si riceve il messaggio di WM_LBUTTONDOWN , chiamare getKeyState come indicato di seguito:

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

Il messaggio GetKeyState accetta un codice chiave virtuale come input e restituisce un set di flag di bit (in realtà solo due flag). Il valore 0x8000 contiene il flag di bit che verifica se il tasto è attualmente premuto.

La maggior parte delle tastiere ha due tasti ALT, sinistra e destra. L'esempio precedente verifica se uno di essi è premuto. È anche possibile usare GetKeyState per distinguere le istanze a sinistra e destra dei tasti ALT, MAIUSC o CTRL. Ad esempio, il codice seguente verifica se viene premuto il tasto ALT destro.

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

La funzione GetKeyState è interessante perché segnala uno stato della tastiera virtuale . Questo stato virtuale si basa sul contenuto della coda dei messaggi e viene aggiornato durante la rimozione dei messaggi dalla coda. Quando il programma elabora i messaggi della finestra, GetKeyState fornisce uno snapshot della tastiera al momento in cui ogni messaggio è stato accodato. Ad esempio, se l'ultimo messaggio della coda era WM_LBUTTONDOWN, GetKeyState segnala lo stato della tastiera al momento in cui l'utente ha fatto clic sul pulsante del mouse.

Poiché GetKeyState si basa sulla coda dei messaggi, ignora anche l'input della tastiera inviato a un altro programma. Se l'utente passa a un altro programma, tutti i tasti inviati a tale programma vengono ignorati da GetKeyState. Se si vuole davvero conoscere lo stato fisico immediato della tastiera, esiste una funzione per questo: GetAsyncKeyState. Per la maggior parte del codice dell'interfaccia utente, tuttavia, la funzione corretta è GetKeyState.

Prossima

Tabelle acceleratori