Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

10. diel - SDĽ - Udalosti klávesnice

V dnešnom diele sa pozrieme na udalosti, ktoré môže vyvolať klávesnice. Najprv zistíme, ako sa s klávesnicou pracuje vo fronte udalostí, a následne ako môžeme kdekoľvek v programe zistiť aktuálny stav klávesnice.

V úvode by som mal spomenúť, že všetky udalosti sú v SDL_Event uložené pod svojimi atribúty. Napríklad k SDL_KeyboardEvent sa dostaneme skrze event.key. Podobne k udalosti upravujúce text (SDL_TextInputEvent) sa dostaneme skrz event.text. Rovnaké pravidlá platia pre každú udalosť, atribút je vždy uvedený v dokumentácii a nebudem ho pri každej udalosti uvádzať.

Scancode, keycode a Keymod

SDL disponujeme dvoma enumerátory, ktoré identifikujú kláves. Prvým je SDL_Scancode a druhý SDL_Keycode. Ich prehľad môžete vidieť tu. Sú takmer totožné, ale neplatí to vždy. SDL_Scancode je priradené na fyzické rozloženie klávesnice, zatiaľ čo SDL_Keycode na aktuálne rozloženie klávesnice určené operačným systémom. Rozdiel môžeme spoznať, keď budeme mať dve rozloženie klávesnice, jedno QWERTZ a druhé QWERTY. SDL_Scancode bude mať pre kláves Y v oboch prípadoch rovnakú hodnotu, zatiaľ čo u SDL_Keycode sa bude meniť podľa toho, ktoré rozvrhnutie bude aktuálne aktívny (Y / Z). Podľa toho by sme tiež mali zachytávať udalosti. Napríklad WSAD budeme chcieť mať vždy na rovnakom mieste, preto použijeme SDL_Scancode. Ak má klávesa "I" otvoriť inventár, mali by sme použiť SDL_Keycode.

S Enumerátor SDL_Keymod je situácia odlišná. Obsahuje hodnoty ako bitové flagy a môžeme hodnoty binárne ORovat alebo Andová. Flagy sú určené pre špeciálne klávesy, ako je Ctrl, Alt, Shift, ale aj NumLock, Tab a ďalšie. Pre klávesy, ktoré sú duplicitné (napríklad Ctrl je vpravo i vľavo), obsahuje jednotlivé flagy pre každú z týchto klávesov (KMOD_LCTRL, KMOD_RCTRL), ale aj ORovanou hodnotu pre obe klávesy (KMOD_CTRL = KMOD_LCTRL|KMOD_RCTRL). Všetko je popísané v dokumentácii.

SDL_KeyboardEvent

SDL_KeyboardEvent je základná štruktúra, z ktorej budeme vychádzať.

typedef struct SDL_KeyboardEvent
{
    Uint32 type;
    Uint32 timestamp;
    Uint32 windowID;
    Uint8 state;
    Uint8 repeat;
    SDL_Keysym keysym;
} SDL_KeyboardEvent;
  • type môže byť SDL_KEYDOWN alebo SDL_KEYUP pre stlačenie alebo uvoľnenie klávesy.
  • timestamp je čas, v ktorom bola udalosť vyvolaná.
  • windowsID je ID okná, ktoré udalosť vyvolalo. Takéto okno môžeme získať funkcií SDL_GetWindow­FromID.
  • state nadobúda hodnôt SDL_PRESSED a SDL_RELEASED. Jedná sa vlastne o duplicitné informáciu, ktorú získame aj z type.
  • z keysym sa dozvieme, o ktorú kláves sa jednalo.

Úmyselne som vynechal repeat, pretože tento atribút je komplikovanejšia. Operačný systém Windows pri stlačení klávesy vygeneruje udalosť KEYDOWN. Ak kláves držíme dlhšie, začne po určitej dobe opakovane generovať KEYDOWN udalosť, ktorá už bude mať nastavený atribút repeat na inú hodnotu ako je 0. Tým spoznáme, že klávesa nebola stlačená, ale je držaná. Pretože je SDL multiplatformový, vývojári sa rozhodli, že aj na iných systémoch ako Windows sa bude SDL správať rovnakým spôsobom a generovať opakovane KEYDOWN udalosť. Je možné, že sa to v ďalších verziách SDL zmení, preto sa oplatí kontrolovať dokumentáciu.

Štruktúru SDL_Keysym som už prakticky opísal. Obsahuje iba SDL_Keycode, SDL_Scancode a SDL_Keymod, nemal by s ňou byť teda problém.

Aktuálny stav klávesnice

Niekedy potrebujeme priamo v programe zistiť, ktorá klávesa je stlačená. Udalosť nám povie iba zmenu klávesy (teda či bola práve stlačená alebo uvoľnená). Niekedy teda môžeme vidieť v programe konštrukcie podobnej tejto.

bool PPressed = false;
bool End = false;
while (!End)
{
    while (SDL_PollEvent(event))
    {
        if (event->type == SDL_QUIT)
            End = true;
        if (event->type == SDL_KEYDOWN && event->key.keysym.scancode == SDL_SCANCODE_P)
            PPressed = true;
        if (event->type == SDL_KEYUP && event->key.keysym.scancode == SDL_SCANCODE_P)
            PPressed = false;
    }
//vykreslení
}

Pri stlačení klávesy nejakým spôsobom zaregistrujeme, že bola klávesa stlačená, a obdobne sa zachováme pri uvoľnení. Podobným konštrukciám sa môžeme vyhnúť použitím funkcie SDL_GetKeyboar­dState, ktorá nám vráti pole aktuálneho stavu. Indexy polia sú scancode klávesov. Ak budeme chcieť zistiť, či je aktuálne stlačená šípka hore, použijeme túto časť programu.

const Uint8 *state = SDL_GetKeyboardState(NULL);
if (state[SDL_SCANCODE_UP])
{
   //šipka nahoru je stisknutá
}

Do funkcie môžeme podľa potreby vložiť ukazovateľ na int, v ktorom nám SDL vráti dĺžku poľa.

Vyššie spomenutá funkcia prepadla klávesy ako Shift, Ctrl a podobné. K tomu slúži funkcia SDL_GetModState, ktorá ale na rozdiel od predchádzajúcej funkcie nevracia poľa, ale ORované hodnoty jednotlivých kláves. Pre vykonanie kódu pri stlačenom Ctrl použijeme tento kód.

SDL_Keymod mod=SDL_GetModState();
if (mod & KMOD_CTRL)
{
    //jedno z Ctrl je stisknuté
}

Môžeme aj ručne nastaviť, ktoré z týchto klávesov sa budú tváriť ako stlačené. Použijeme na to funkciu SDL_SetModState. Funkcia prijíma ako parameter binárne ORované hodnoty z SDL_Keysym. Klávesy, ktoré nastavíme, budú pri najbližšom volaní SDL_GetModState zahrnuté v návratovej hodnote.

Posledná funkcia, ktorú môžeme niečo zistiť o aktuálnej situácii, je funkcia SDL_GetKeyboar­dFocus. Vracia SDL_Window, ktoré je aktuálne aktívny, a prijíma udalosti vyvolané klávesnicou.

Text

SDL poskytuje aj rozhranie pre zachytávanie textu. Prečo potrebujeme separátne rozhranie pre text, keď vieme, ktorá klávesa bola stlačená? Pre text je nepreberné množstvo kombinácií a klávesnica samotná môže mať niekoľko rozvrhnutie. Ak by sme chceli každý znak vytvárať ručne, bola by to veľa práce (v súčasnosti existuje približne 110 000 znakov). Toto rozhranie nás od konkrétnej implementácie utlmia a môžeme pracovať len so samotným textom.

Základné funkcie sú SDL_StartTextIn­put a SDL_StopTextIn­put. Po zavolaní prvá funkcia SDL začne generovať udalosti typu SDL_TEXTINPUT, poprípade SDL_TEXTEDITING. SDL_TextInputE­vent má okrem základných atribútov iba jeden vlastný, a tým je text. Ten je ukazovateľ typu char a je v ňom uložený reťazec formátu UTF-8 ukončený nulovým znakom. SDL_TextEditin­gEvent je o niečo rozsiahlejšie, preto si ho ukážeme.

typedef struct SDL_TextEditingEvent
{
    Uint32 type;
    Uint32 timestamp;
    Uint32 windowID;
    char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
    Sint32 start;
    Sint32 length;
} SDL_TextEditingEvent;

Okrem základných atribútov obsahuje atribút text, ktorý obsahuje nový text. Ďalej atribút start (kde editácia začína) a length (dĺžka editovaného textu). Taká je aspoň predstava. Z pokusov na Windows som zistil, že SDL_TextEditingEvent sa generuje z neznámeho dôvodu iba pri zmene okna, ale neodovzdáva žiadne informácie. text, start i length sú 0. Vôbec nezohľadňuje backspace, o tom, že by som sa chcel v texte posúvať pomocou šípok ani nehovoriac. Neviem aká je situácia na Linuxe a poprípade na ďalších systémoch, ak niekto bude skúšať program spustiť aj pod iným operačným systémom, prosím dajte vedieť, ako program reaguje.

Klávesnica na obrazovke

Pretože je SDL multiplatformový, a to vrátane platformy Android a iOS, môže nastať situácia, keď nebudeme mať pripojenú fyzickú klávesnicu. U tabletov a mobilných telefónov si musíme vystačiť so softvérovou klávesnicou, ktorú nám poskytuje operačný systém. Funkciou SDL_HasScreen­KeyboardSuppor zistíme, či aktuálne platforma podporuje klávesnicu na obrazovke. Druhou funkciou, ktorá sa môže hodiť, je SDL_IsScreenKe­yboardShown, ktorá vráti SDL_bool, ak je klávesnica zobrazená. Klávesnica by sa mala automaticky zobraziť pri volaní SDL_StartTextInput a pri SDL_StopTextInput by sa mala opäť skryť.

Na Windows 8.1 mi funkcionalita opäť nefungovala. Aj keď som zapol klávesnicu na obrazovke, klávesnica sa nie a nie zobraziť. Pravdepodobne sa opäť jedná o záležitosť konkrétnej platformy.

Príklad

V dnešnom príklade som pripravil ukážku, ako zachytávať práve textový vstup. Pri stlačení klávesy nahor sa vstup aktivuje, pri stlačení klávesy dole sa text prestane zapisovať.

V budúcom dieli sa pozrieme bližšie na myš a jej udalosti.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 698x (9.51 MB)

 

Predchádzajúci článok
SDĽ - Práca s časovačom
Všetky články v sekcii
SDĽ
Preskočiť článok
(neodporúčame)
SDĽ - Udalosti myši
Článok pre vás napísal Patrik Valkovič
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity