IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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_MouseButto­nEvent

SDL_MouseButto­nEvent 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 nebo SDL_MOUSEBUTTONUP.
  • which může obsahovat SDL_TOUCH_MOUSEID nebo ID myši. ID myši nám v aplikaci moc platné není, ale SDL_TOUCH_MOUSEID se generuje ve chvíli, kdy je událost původně dotyková. Pokud zachytáváme SDL_TouchFinge­rEvent 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 a SDL_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_MouseMoti­onEvent

SDL_MouseMoti­onEvent 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_WarpMouse­InWindow a SDL_WarpMouse­Global. 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_MouseWhee­lEvent, 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_CreateSys­temCursor, 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_CreateColor­Cursor. 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_GetDefaultCur­sor, 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_GetMouseS­tate, která uspěje , pouze je-li myš v okně a vrací souřadnice relativní k tomuto oknu, dále je funkce SDL_GetRelati­veMouseState, 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_GetGlobal­MouseState, 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.

Demo - SDL

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ínkami

Staženo 770x (38.19 kB)

 

Předchozí článek
SDL - Události klávesnice
Všechny články v sekci
SDL
Přeskočit článek
(nedoporučujeme)
SDL - Obecná práce s událostmi
Článek pro vás napsal Patrik Valkovič
Avatar
Uživatelské hodnocení:
1 hlasů
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity