Dela via


Tangentbordsindata (Kom igång med Win32 och C++)

Tangentbordet används för flera olika typer av indata, inklusive:

  • Teckeninmatning. Text som användaren skriver i ett dokument eller en redigeringsruta.
  • Kortkommandon. Nyckeldrag som anropar programfunktioner; Till exempel CTRL + O för att öppna en fil.
  • Systemkommandon. Nyckelstreck som anropar systemfunktioner; till exempel ALT + TAB för att växla fönster.

När du tänker på tangentbordsinmatning är det viktigt att komma ihåg att ett tangentstreck inte är detsamma som ett tecken. Om du till exempel trycker på A-tangenten kan det resultera i något av följande tecken.

  • a
  • A
  • á (om tangentbordet stöder kombination av diakritiska tecken)

Om ALT-tangenten hålls nere skapar du alt+A genom att trycka på A-tangenten, vilket systemet inte behandlar som ett tecken alls, utan snarare som ett systemkommando.

Nyckelkoder

När du trycker på en tangent genererar maskinvaran en skanningskod . Genomsökningskoderna varierar från ett tangentbord till ett annat, och det finns separata genomsökningskoder för key-up- och key-down-händelser. Du kommer nästan aldrig bry dig om genomsökningskoder. Tangentbordsdrivrutinen översätter genomsökningskoder till virtuella nyckelkoder. Virtuella nyckelkoder är enhetsoberoende. Om du trycker på A-tangenten på valfritt tangentbord genereras samma kod för virtuell nyckel.

I allmänhet motsvarar virtuella nyckelkoder inte ASCII-koder eller någon annan teckenkodningsstandard. Detta är uppenbart om du tänker på det, eftersom samma nyckel kan generera olika tecken (a, A, á) och vissa nycklar, till exempel funktionsnycklar, inte motsvarar något tecken.

Med detta sagt mappar följande virtuella nyckelkoder till ASCII-motsvarigheter:

  • 0 till och med 9 nycklar = ASCII "0" – "9" (0x30 – 0x39)
  • A till Z-nycklar = ASCII "A" – "Z" (0x41 – 0x5A)

I vissa avseenden är den här mappningen olycklig eftersom du aldrig bör tänka på virtuella nyckelkoder som tecken, av de skäl som beskrivs.

Huvudfilen WinUser.h definierar konstanter för de flesta av de virtuella nyckelkoderna. Till exempel är den virtuella nyckelkoden för VÄNSTERPIL-tangenten VK_LEFT (0x25). Den fullständiga listan över virtuella nyckelkoder finns i Virtual-Key Codes. Inga konstanter definieras för de virtuella nyckelkoder som matchar ASCII-värden. Till exempel är koden för virtuell nyckel för A-nyckeln 0x41, men det finns ingen konstant med namnet VK_A. Använd i stället det numeriska värdet.

Key-Down och Key-Up meddelanden

När du trycker på en tangent får fönstret med tangentbordsfokus något av följande meddelanden.

Meddelandet WM_SYSKEYDOWN anger en systemnyckel, vilket är ett nyckeldrag som anropar ett systemkommando. Det finns två typer av systemnyckel:

  • ALT + valfri nyckel
  • F10

F10-nyckeln aktiverar menyraden i ett fönster. Olika ALT-nyckelkombinationer anropar systemkommandon. Till exempel växlar ALT + TAB till ett nytt fönster. Om ett fönster dessutom har en meny kan ALT-nyckeln användas för att aktivera menyalternativ. Vissa ALT-tangentkombinationer gör ingenting.

Alla andra nyckeldrag betraktas som icke-systemnycklar och skapar meddelandet WM_KEYDOWN. Detta inkluderar andra funktionsnycklar än F10.

När du släpper en tangent skickar systemet ett motsvarande tangent-släppmeddelande.

Om du håller ned en tangent tillräckligt länge för att starta tangentbordets upprepningsfunktion skickar systemet flera nedtryckta tangentmeddelanden, följt av ett enda tangentuppsläppningsmeddelande.

I alla fyra av de tangentbordsmeddelanden som diskuterats hittills innehåller parametern wParam den virtuella nyckelkoden för nyckeln. Parametern lParam innehåller viss övrig information som är packad i 32 bitar. Du behöver vanligtvis inte informationen i lParam. En flagga som kan vara användbar är bit 30, flaggan "föregående tangenttillstånd", som är inställd på 1 för upprepade meddelanden om nertryckta tangenter.

Som namnet antyder är systemnyckelstreck främst avsedda att användas av operativsystemet. Om du fångar upp meddelandet WM_SYSKEYDOWN, anropar du DefWindowProc efteråt. Annars blockerar du operativsystemet från att hantera kommandot.

Teckenmeddelanden

Tangentstreck konverteras till tecken av funktionen TranslateMessage, som vi först såg i modul 1. Den här funktionen undersöker nedtangentsmeddelanden och översätter dem till tecken. För varje tecken som skapas placerar funktionen TranslateMessage ett WM_CHAR- eller WM_SYSCHAR meddelande i fönstrets meddelandekö. Parametern wParam i meddelandet innehåller UTF-16-tecknet.

Som du kanske gissar genereras WM_CHAR meddelanden från WM_KEYDOWN meddelanden, medan WM_SYSCHAR meddelanden genereras från WM_SYSKEYDOWN meddelanden. Anta till exempel att användaren trycker på SKIFT-tangenten följt av A-tangenten. Om du antar en vanlig tangentbordslayout får du följande sekvens med meddelanden:

WM_KEYDOWN: SKIFT
WM_KEYDOWN: A
WM_CHAR: "A"

Å andra sidan skulle kombinationen ALT + P generera:

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

(Den virtuella nyckelkoden för ALT-nyckeln heter VK_MENU av historiska skäl.)

Meddelandet WM_SYSCHAR anger ett systemtecken. Precis som med WM_SYSKEYDOWNbör du vanligtvis skicka det här meddelandet direkt till DefWindowProc. Annars kan du störa standardsystemkommandon. I synnerhet ska du inte behandla WM_SYSCHAR som text som användaren har skrivit.

Det WM_CHAR meddelandet är vad du normalt ser som teckeninmatning. Datatypen för tecknet är wchar_t, som representerar ett UTF-16 Unicode-tecken. Teckeninmatning kan innehålla tecken utanför ASCII-intervallet, särskilt med tangentbordslayouter som ofta används utanför USA. Du kan prova olika tangentbordslayouter genom att installera ett regionalt tangentbord och sedan använda funktionen Skärmtangentbord.

Användare kan också installera en IME (Input Method Editor) för att ange komplexa skript, till exempel japanska tecken, med ett standardtangentbord. Om du till exempel använder en japansk IME för att ange katakana-tecknet カ (ka) kan du få följande meddelanden:

WM_KEYDOWN: VK_PROCESSKEY (IME PROCESS-Nyckeln)
WM_KEYUP: 0x4B
WM_KEYDOWN: VK_PROCESSKEY
WM_KEYUP: 0x41
WM_KEYDOWN: VK_PROCESSKEY
WM_CHAR: カ
WM_KEYUP: VK_RETURN

Vissa CTRL-tangentkombinationer översätts till ASCII-kontrolltecken. Till exempel översätts CTRL+A till ASCII ctrl-A-tecknet (SOH) (ASCII-värde 0x01). För textinmatning bör du vanligtvis filtrera bort kontrolltecken. Undvik också att använda WM_CHAR för att implementera kortkommandon. Använd i stället WM_KEYDOWN meddelanden. eller ännu bättre, använd en acceleratortabell. Acceleratortabeller beskrivs i nästa avsnitt acceleratortabeller.

Följande kod visar de viktigaste tangentbordsmeddelandena i felsökningsprogrammet. Prova att spela med olika tangenttryckningskombinationer och se vilka meddelanden som genereras.

Notera

Se till att ta med wchar.h, annars kommer swprintf_s att vara odefinierat.

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

Diverse tangentbordsmeddelanden

Vissa andra tangentbordsmeddelanden kan ignoreras på ett säkert sätt av de flesta program.

  • Meddelandet WM_DEADCHAR skickas för en kombinationsnyckel, till exempel ett diakritiskt meddelande. På ett spanskt tangentbord kan man till exempel skapa tecknet é genom att skriva accenttecken (') följt av E. WM_DEADCHAR skickas för accenttecknet.
  • Meddelandet WM_UNICHAR är föråldrat. Det gör att ANSI-program kan ta emot Unicode-teckenindata.
  • Tecknet WM_IME_CHAR skickas när en IME översätter en tangenttryckningssekvens till tecken. Det skickas utöver det vanliga WM_CHAR meddelandet.

Tangentbordstillstånd

Tangentbordsmeddelandena är händelsedrivna. Det vill: du får ett meddelande när något intressant händer, till exempel en tangenttryckning, och meddelandet berättar vad som just hände. Men du kan också testa tillståndet för en nyckel när som helst genom att anropa funktionen GetKeyState.

Tänk till exempel på hur skulle du identifiera kombinationen av vänster musklick + ALT-nyckel. Du kan spåra Alt-tangentens tillstånd genom att lyssna efter keystroke-meddelanden och lagra en flagga, men GetKeyState sparar dig besväret. När du får WM_LBUTTONDOWN-meddelandet anropar du bara GetKeyState på följande sätt:

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

Meddelandet GetKeyState tar en kod med virtuell nyckel som indata och returnerar en uppsättning bitflaggor (egentligen bara två flaggor). Värdet 0x8000 innehåller den bitflagga som testar om nyckeln för närvarande är tryckt.

De flesta tangentbord har två ALT-tangenter, vänster och höger. I det föregående exemplet testar man om någon av dem har tryckts. Du kan också använda GetKeyState för att skilja mellan de vänstra och högra instanserna av ALT-, SKIFT- eller CTRL-tangenterna. Följande kod testar till exempel om rätt ALT-nyckel trycks in.

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

Funktionen GetKeyState är intressant eftersom den rapporterar ett virtuellt tangentbordstillstånd. Det här virtuella tillståndet baseras på innehållet i meddelandekön och uppdateras när du tar bort meddelanden från kön. När programmet bearbetar fönstermeddelanden ger GetKeyState dig en ögonblicksbild av tangentbordet när varje meddelande köades. Om det sista meddelandet i kön till exempel var WM_LBUTTONDOWNrapporterar GetKeyState tangentbordstillståndet när användaren klickade på musknappen.

Eftersom GetKeyState baseras på meddelandekön ignoreras även tangentbordsindata som skickades till ett annat program. Om användaren växlar till ett annat program ignoreras alla tangenttryckningar som skickas till programmet av GetKeyState. Om du verkligen vill veta tangentbordets omedelbara fysiska tillstånd finns det en funktion för det: GetAsyncKeyState. För de flesta UI-kod är dock rätt funktion GetKeyState.

Nästa

acceleratortabeller