Zpracování zpráv a obsluha klávesnice
V klasických aplikacích, které jsou orientovány spíše na textové uživatelské rozhraní (Text User Interface – TUI) a příkazovou řádku, se pro komunikaci s uživatelem používá jednoduchý systém typu dotaz-odpověď. Pokud potřebuje programátor získat nějaké informace od uživatele aplikace, zavolá funkci pro vstup dat (například gets() nebo scanf()) a teprve po jejich zadání program pokračuje dále.
V operačních systémech s grafickým uživatelským rozhraním (Graphical User Interface – GUI) se používá dosti odlišný způsob ovládání aplikací. Uživatel má mnohem větší možnosti, jak aplikaci ovládat. Místo systému typu dotaz-odpověď, který je vhodný u příkazové řádky, se používají okna s mnoha ovládacími prvky – menu, tlačítka, rozbalovací nabídky, editační boxy apod. Při práci s prvky grafického uživatelského rozhraní vznikají takzvané události (events), na něž programátor aplikace musí umět reagovat. V tom mu pomáhá operační systém, jehož část starající se o GUI při vzniku události (například stisknutí tlačítka myši) většinou generuje pro aplikaci takzvanou zprávu. Zpráva je datová struktura, která jednoznačně identifikuje zdroj události a obsahuje i další důležité informace, například kód stisknuté klávesy či pozici kurzoru myši. Aplikace tyto zprávy vybírá z takzvané fronty událostí (event queue) či fronty zpráv (message queue) a postupně na ně reaguje.
Naprogramování vlastní smyčky, která reaguje na zprávy došlé od systému, je poměrně pracné a vyžaduje značné znalosti daného operačního systému. Aplikace, která používá takovouto smyčku zpráv, je nepřenositelná na jinou platformu. Proto knihovna GLUT disponuje vlastním systémem pro zpracovávání událostí (zpráv), které přijdou od operačního systému. Uvnitř knihovny GLUT je naprogramována smyčka zpráv určená pro právě používaný operační systém, ale tato smyčka je pro programátora aplikace neviditelná. Pro zpracovávání událostí se používají takzvané callback funkce, což jsou uživatelem nadefinované funkce zavolané až v době výskytu události (tedy asynchronně k běhu programu). Jednotlivé callback funkce musí být předem zaregistrovány a poté jsou volány až po spuštění funkce glutMainLoop().
Reakce na stisk kláves
Mezi základní požadavky při ovládání grafických aplikací stále patří reakce na stisk kláves. Ukazuje se, že pro některé operace je použití klávesnice nejrychlejší a nejpřesnější možností. V knihovně GLUT je možné zaregistrovat dva typy reakcí na stisk kláves – reakce na stisk klávesy, která generuje ASCII hodnotu, a reakce na stisk takzvaných speciálních kláves, mezi něž patří například funkční klávesy a klávesy určené pro ovládání kurzoru (šipky, PageUp, PageDown, Home a End). V novějších verzích knihovny GLUT se objevují i další typy událostí – událost generovaná při stisku klávesy a další událost generovaná při puštění klávesy – které se používají při programování interaktivních programů. Všechny zmíněné typy událostí jsou generovány pro každé okno zvlášť – je tedy možné mít pro každé okno zaregistrovánu jinou callback funkci pro obsluhu kláves.
Pro registraci callback funkce reagující na stisk klávesy generující ASCII kód se používá funkce glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)). Programátorem vytvořená callback funkce musí mít tři parametry. První parametr key je typu unsigned char a je do něj uložen ASCII kód stisknuté klávesy. Další dva parametry x,y jsou typu int a je do nich uložena pozice kurzoru myši v době vzniku události. Pozice kurzoru myši je reprezentována relativně k oknu, ve kterém událost vznikla. Levý horní roh uživatelské části okna má pozici 0, 0. Je důležité si uvědomit, že ASCII kód generují kromě alfanumerických kláves i klávesy mezerník, Enter, BackSpace a Escape. Také písmenné klávesy stlačené spolu s modifikátorem CTRL (Control) generují ASCII kód (kód klávesy zmenšený o hodnotu 32), a proto jsou touto callback funkcí také zpracovány. Problémy mohou nastat s klávesou Delete, která by měla generovat ASCII kód 127. V některých starších verzích knihovny GLUT však tento kód nikdy nebyl generován a klávesu Delete tedy nešlo v programech použít.
Druhý typ callback funkce reaguje na stisk klávesy, jež negeneruje ASCII hodnotu. Příklady takových kláves jsou uvedeny v tabulce níže. Pro registraci se používá funkce glutSpecialFunc(void (*func)(int key, int x, int y)). Programátorem vytvořená callback funkce musí mít tři parametry. První parametr key je typu int a představuje kód stisknuté klávesy. Další dva parametry x a y mají stejný význam jako u funkceglutKeyboardFunc().
Aby byla zajištěna platformová nezávislost, jsou kódy stisknutých kláves definovány jako symbolické konstanty v hlavičkovém souboru glut.h. Některé často používané konstanty ukazuje následující tabulka:
symbolická konstanta | význam |
GLUT_KEY_F1 | funkční klávesa F1 |
GLUT_KEY_F2 | funkční klávesa F2 |
GLUT_KEY_F3 | funkční klávesa F3 |
GLUT_KEY_F4 | funkční klávesa F4 |
GLUT_KEY_F5 | funkční klávesa F5 |
GLUT_KEY_F6 | funkční klávesa F6 |
GLUT_KEY_F7 | funkční klávesa F7 |
GLUT_KEY_F8 | funkční klávesa F8 |
GLUT_KEY_F9 | funkční klávesa F9 |
GLUT_KEY_F10 | funkční klávesa F10 |
GLUT_KEY_F11 | funkční klávesa F11 |
GLUT_KEY_F12 | funkční klávesa F12 |
GLUT_KEY_LEFT | kurzorová klávesa šipka doleva |
GLUT_KEY_RIGHT | kurzorová klávesa šipka doprava |
GLUT_KEY_UP | kurzorová klávesa šipka nahoru |
GLUT_KEY_DOWN | kurzorová klávesa šipka dolů |
GLUT_KEY_PAGE_UP | kurzorová klávesa pro skok o stránku nahoru |
GLUT_KEY_PAGE_DOWN | kurzorová klávesa pro skok o stránku dolů |
GLUT_KEY_HOME | kurzorová klávesa pro skok na začátek řádku |
GLUT_KEY_END | kurzorová klávesa pro skok na konec řádku |
GLUT_KEY_INSERT | klávesa Insert (většinou řídí přepnutí Insert a Overwrite režimu) |
Ukázkový příklad číslo 5
Tento příklad demonstruje použití callback funkce pro zpracování události, jež vznikne při stisknutí klávesy generující ASCII hodnotu. Po stisku je vypsán znak i odpovídající ASCII kód klávesy do titulkového pruhu okna. Všimněte si, že v rámci aplikace využívající GLUT nelze od sebe rozeznat některé kódy různých kláves – například CTRL+H a BackSpace nebo CTRL+M a Enter generují stejné ASCII kódy. K dispozici je zdrojový kód pátého příkladu a zdrojový kód se zvýrazněnou syntaxí.
Ukázkový příklad číslo 6
Tento příklad demonstruje použití callback funkce pro zpracování události, jež vznikne při stisknutí klávesy, která negeneruje ASCII hodnotu. Po stisku je do titulkového pruhu okna vypsán řetězec, který popisuje účel klávesy. Všimněte si skutečnosti, že kódy speciálních kláves jsou uspořádány vzestupně za sebou, takže pro výpis řetězce je možné použít přímé indexace pole. K dispozici je zdrojový kód šestého příkladu a zdrojový kód se zvýrazněnou syntaxí.
V příštím pokračování si ukážeme ovládání dalšího důležitého vstupního zařízení – myši.