Lekce 11 - SDL - Události myši
V minulé lekci, SDL - Události klávesnice, jsme se věnovali obsluze událostí vyvolaných klávesnicí a myší.
Dnes se blíže podíváme na události, které může vyvolat myš. Myš má dva typy událostí - posun a stisk tlačítka. Nejdříve se podíváme na stisk tlačítka myši, poté na posun a nakonec i na kolečko myši. V závěru také uvedu funkce, které SDL poskytuje pro editaci ukazatele myši.
SDL_MouseButtonEvent
SDL_MouseButtonEvent nám poskytuje informaci o stisku tlačítka myši. Opět uvedu definici.
typedef struct SDL_MouseButtonEvent { Uint32 type; Uint32 timestamp; Uint32 windowID; Uint32 which; Uint8 button; Uint8 state; Uint8 clicks; Sint32 x; Sint32 y; } SDL_MouseButtonEvent;
- type je stejně jako u klávesnice rozdílný pro stisk nebo
uvolnění tlačítka. Může nabývat hodnot
SDL_MOUSEBUTTONDOWN
neboSDL_MOUSEBUTTONUP
. - which může obsahovat
SDL_TOUCH_MOUSEID
nebo ID myši. ID myši nám v aplikaci moc platné není, aleSDL_TOUCH_MOUSEID
se generuje ve chvíli, kdy je událost původně dotyková. Pokud zachytáváme SDL_TouchFingerEvent můžeme událost s tímto příznakem ignorovat. V opačném případě vidíme, že můžeme s dotykovou obrazovkou pracovat stejně, jako by uživatel používal klasickou myš. - state je stejně jako u klávesnice duplicitní informace. Nabývá
hodnot
SDL_PRESSED
aSDL_RELEADED
. - clicks nám řekne, jestli se jednalo o jedno kliknutí nebo dvojité (double click), popřípadě zda uživatel kliknul vícekrát. Tento atribut je zařazený do SDL až od verze 2.0.2.
- Z x a y se dozvíme, kde uživatel kliknul. Jedná se o celé číslo udávané v pixelech a měřeno relativně k levému hornímu rohu okna.
Úmyslně jsem vynechal nejdůležitější část - atribut button.
Ten může nabývat jedné z pěti hodnot a řekne nám, kterého tlačítka se
událost týká. Nejčastěji používané hodnoty jsou
SDL_BUTTON_LEFT
, SDL_BUTTON_MIDDLE
,
SDL_BUTTON_RIGHT
pro levné, prostřední (kolečko) a pravé
tlačítko. Na Windows jsem zjistil, že i když nastavíme tlačítka
obráceně (volba „zaměnit levé a pravé tlačítko“), bude brát pravé
tlačítko jako levé a obráceně, tedy tak, jak odpovídá jejich
funkcionalitě. Pro vývojáře určitě dobrá zpráva.
SDL poskytuje navíc ještě další dvě konstanty, a to
SDL_BUTTON_X1
a SDL_BUTTON_X2
pro myši s pěti
tlačítky (například na boku). Bohužel aktuálně takovou myš nevlastním,
proto jsem funkčnost nemohl ověřit.
SDL_MouseMotionEvent
SDL_MouseMotionEvent informuje o posunu myši na obrazovce. Opět přiložím definici a popis.
typedef struct SDL_MouseMotionEvent { Uint32 type; Uint32 timestamp; Uint32 windowID; Uint32 which; Uint32 state; Sint32 x; Sint32 y; Sint32 xrel; Sint32 yrel; } SDL_MouseMotionEvent;
Atributy type, timestamp, windowID, which
i state jsou shodné s předcházející událostí, proto se
podíváme pouze na charakteristické atributy pro
SDL_MouseMotionEvent
. Atributy x a y jsou
souřadnice, kde myš s pohybem skončila. Tyto souřadnice jsou relativní k
aktuálnímu oknu. Atributy xrel a yrel nám udávají, o
kolik se myš posunula ve směru vodorovném, popřípadě horizontálním.
SDL poskytuje i dvě funkce, které ukazatel myši přesunou. Jsou jimi SDL_WarpMouseInWindow
a SDL_WarpMouseGlobal.
První uvedená přesune myš na souřadnice relativní k oknu aplikace, druhá
poté relativní k obrazovce. Proč bychom tyto dvě funkce potřebovali?
Představme si, že programujeme FPS (střílečku z první osoby). Pokud by
hráč přesunul myš ke kraji okna, program by nedostával zprávy o pohybu
myši, protože by se myš vlastně nikam nepřesouvala, ale zůstávala by u
okraje. V takových případech budeme nejčastěji po každém pohybu
přesouvat myš zpět na střed obrazovky. Aplikace tak bude neustále
zachytávat pohyby myši. Obě funkce sami vyvolávají událost
SDL_MouseMotionEvent
, kterou budeme muset z fronty událostí
odstranit. Tedy za předpokladu, že aplikace nebude událost znovu potřebovat.
Ukázka bude v přiloženém programu na konci článku.
V SDL můžeme také nařídit, aby byla myš zachytávána i mimo okno. Použijeme k tomu funkci SDL_CaptureMouse. Není ale doporučeno toho využívat příliš často. Na některých zařízení tato funkcionalita ani není možná. Po nastavení se může stát, že ostatní aplikace přestanou dostávat zprávy o pohybu myši, protože půjdou všechny zprávy naší aplikaci. Hodnoty souřadnic, kde je myš, jsou stále stáhnuty k oknu naší aplikace, to znamená, že můžou nabývat i záporných hodnot, s čímž je potřeba v aplikaci počítat.
SDL_MouseWheelEvent
Nakonec tu máme SDL_MouseWheelEvent,
který nám řekne informace o rotaci kolečka myši. V předchozí verzi SDL
byla tato událost zařazena pod SDL_MouseButtonEvent
s tím, že
mezi tlačítky byli zařazena ještě konstanty SDL_BUTTON_WHEELUP
a SDL_BUTTON_WHEELDOWN
. V novější verzi už má kolečko svou
samostatnou událost.
typedef struct SDL_MouseWheelEvent { Uint32 type; Uint32 timestamp; Uint32 windowID; Uint32 which; Sint32 x; Sint32 y; } SDL_MouseWheelEvent;
Stěžejní jsou atributy x a y. První z nich nám poví o horizontální rotaci kolečka – tedy zprava do leva. Pro rotaci doprava bude obsahovat hodnotu kladnou, pro posun doleva hodnotu zápornou. Druhý atribut obsahuje data z vertikální rotaci kolečka. Pokud bude uživatel točit kolečkem nahoru (od sebe), bude hodnota záporná, obrácený směr bude generovat hodnoty kladné.
V dokumentaci je uveden ještě atribut direction
, který je zde
pravděpodobně kvůli ostatním platformám, koneckonců stejně jako atribut x
- kolik z nás má na myši kolečko, které lze točit do všech 4 stran?
Některé platformy můžou mít převrácenou orientaci (budou generovat
záporné hodnoty tam, kde očekáváme kladné). V direction
je
uložena informace, která nám to oznámí. Tento atribut je relevantní až od
verze 2.0.4, která nebyla v době psaní článku stabilní, proto se jím
dále zabývat nebudeme.
Změna kurzoru
SDL poskytuje několik funkcí, pomocí kterých můžeme změnit vzhled
kurzoru. Tyto funkce vrací ukazatel na SDL_Cursor
, který je
nutné poté uvolnit funkcí SDL_FreeCursor.
Jediný kurzor, který není nutné uvolnit, je výchozí. Vytvořený kurzor
poté aktivujeme funkcí SDL_SetCursor.
Základní funkce pro vytváření kurzoru je SDL_CreateCursor. Tento kurzor může být pouze černobílý a jeho vytvoření není tak snadné, jako u ostatních funkcí, proto funkci nebudu popisovat. Pro případné zájemce je v dokumentaci SDL uveden příklad.
Funkci, kterou budeme používat častěji, je SDL_CreateSystemCursor,
která vytvoří jeden z předpřipravených kurzorů, které poskytuje
operační systém. Jako parametr přijímá konstantu, která definuje
jednotlivé kurzory. Najdeme tak klasické systémové kurzory jako přesýpací
hodiny, ruka (která se objeví po přejetí na odkaz) a další. Seznam je
opět v dokumentaci. Poslední funkcí (a pro nás nejzajímavější), je
funkce SDL_CreateColorCursor.
Kurzor vytvoří z SDL_Surface
, kterou předáme jako parametr.
Můžeme nastavit i bod, kterým je aktivační místo – místo, ze kterého
se bere vstup myši. Použijeme k tomu parametry hot_x
a
hot_y
. Toto místo tedy nemusí být pouze v rohu
SDL_Surface
, ale může být kdekoliv . Ukázka bude opět v
programu na konci článku.
Kurzor můžeme v aplikaci i úplně schovat, a to funkcí SDL_ShowCursor.
Předáme-li v parametru SDL_ENABLE
nebo SDL_DISABLE
,
kurzor se zobrazí nebo skryje. Pro zjištění aktuálního stavu můžeme
předat SDL_QUERY
a funkce vrátí hodnotu 1, pokud je kurzor
zobrazený, v opačném případě vrátí 0.
Předposlední funkce je SDL_GetCursor,
která vrátí aktuálně používaný kurzor, nebo NULL
, pokud
není kurzor na zařízení podporovaný. A konečně poslední je SDL_GetDefaultCursor,
která vrátí výchozí kurzor, který byl systémem nastaven.
Aktuální stav myši
U myši kromě stisknutých tlačítek můžeme zjistit také její
aktuální pozici. Všechny tři funkce, které SDL poskytuje, vrací ORované
hodnoty jednotlivých tlačítek. Předtím, než konstanty použijeme, na ně
musíme aplikovat SDL_BUTTON
makro. Funkce také přijímají dva
ukazatele typu int
, ve kterých se nám vrátí aktuální pozice
myši. Můžeme předat NULL
, pokud nás souřadnice nezajímají.
První funkcí je SDL_GetMouseState,
která uspěje , pouze je-li myš v okně a vrací souřadnice relativní k
tomuto oknu, dále je funkce SDL_GetRelativeMouseState,
která vrací souřadnice z celé obrazovky, ale stále relativní k oknu -
souřadnice mohou být i záporné. Poslední funkcí je SDL_GetGlobalMouseState,
která opět bere myš z celé obrazovky, ale zároveň jsou hodnoty relativní
k obrazovce – levý horní roh má souřadnice 0,0. Použití je ukázáno v
následujícím kódu.
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)) { SDL_Log("Levé tlačítko myši bylo stisknuto"); }
Příklad
Jako příklad jsem zvolil aplikaci, která si nastaví vlastní ukazatel, který nemá aktivační oblast v levém horním rohu. Červený čtverec se poté pohybuje podle pohybu myši, která se po překročení definované plochy přemístí zpět. Levým tlačítkem myši můžeme přesunout čtverec zpět do středu, pravým tlačítkem kurzor skryjeme. Aplikaci ukončíme kombinací Alt+F4.

V příští lekci, SDL - Obecná práce s událostmi, zůstaneme u událostí a blíže se podíváme na manipulaci s frontou událostí.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkamiStaženo 908x (38.19 kB)