Zpět

Jak detekovat kliknutí myši do nepravidelné oblasti

Detekovat kliknutí do obdélníku je jednoduché:

if (mysX>=x1) and (mysX<=x2) and (mysY>=y1) and (mysY<=y2) then {myš je uvnitř}
                                                           else {myš je mimo};

[x1,y1] je levý horní roh klikací oblasti, [x2,y2] pravý dolní. MysX a mysY jsou souřadnice myši.

Kruhové tlačítko je taky ještě celkem v pohodě:

if sqrt(sqr(mysX-stredX)+sqr(mysY-stredY))<=PolomerTlacitka then {myš je uvnitř}
                                                            else {myš je mimo};

StredX a stredY je střed tlačítka, počítali jsme vzdálenost myši od středu pomocí obyčejné Pythagorovy věty. Pozor jedině na možnost přetečení druhých mocnin - výrazy v závorkách za Sqr musí být minimálně longinty.

Někdy ale potřebujeme klikat do nějakého naprostého patvaru, např.:

ukázka šišoidního tlačítka

Necháme stranou případ, kdy bychom ho jednoduše ohraničili obdélníkem a testovali klik do něj, a zkusíme to poctivě. Předpokládám, že bitmapa tlačítka je ve skutečnosti obdélníková a prázdný prostor okolo té klikací kaňky je vyplněn pixely o hodnotě "Průhledná" (jedna barva, kterou si zvolíte).

if MysVPoli(x1,x2,x2,y2) and (bitmapa[mysY-y1,mysX-x1]<>pruhledna) then {myš je uvnitř}
                                                                   else {myš je mimo};

[x1,y1] je poloha levého horního rohu bitmapy na obrazovce, [x2,y2] pravého dolního. Funkce MysVPoli testuje, jestli je myš uvnitř daného obdélníku - dejme tomu, že dělá to samé, co ty čtyři podmínky v prvním příkladě (tady je jenom pro zkrácení zápisu). Dále předpokládám, že bitmapa je dvojrozměrné pole pixelů řazených po řádcích, tj. první index určuje číslo řádku (y) a druhý číslo sloupce (x) a oba indexy jsou počítané od nuly.

Zjišťování, jestli je myš nad bitmapou, je nutné - zkuste si představit, jak by to dopadlo, kdyby se pak začaly za indexy bitmapy dosazovat záporné hodnoty.

Dobře, ale co když máme bitmapu ve formě dynamického pole? Žádný problém:

... and (bitmapa^[(mysY-y1)*sirka+(mysX-x1)]<>pruhledna) then ...

Sirka je šířka bitmapy v pixelech. Tohle je obecný postup, jak indexovat prvky dynamického pole, které je vždy fyzicky uloženo jako 1D, ale my s ním potřebujeme pracovat jako s 2D. Bitmapa by mohla být definována nějak jako TypBitmapy = ^array[0..něco] of TypPixelu. Pokud by to byl beztypový datový blok alokovaný přes Getmem a odkazovaný přes pointer, spraví se to vhodným přetypováním. Typ pixelu bude nejspíš Byte pro 256barevný obrázek, Word pro hicolor a Dword (Longint) pro truecolor; záleží na tom, co zrovna používáte.

Tento postup předpokládá, že neaktivní plochy tlačítka jsou vyplněny jednou barvou. Když nechcete mít prostor okolo tlačítka jednobarevný, stačí tlačítko vykreslit přes jakkoli složité pozadí pomocí nějaké procedury, která neaktivní pixely vynechává. Pokud ale z nějakého důvodu takovýto způsob kreslení použít nechcete a okolí tlačítka uložené uvnitř bitmapy máte různobarevné, je třeba přistoupit k plánu B.

Vytvoříme si masku:

maska vymezující aktivní oblast

Bílá barva je zde aktivní, černá neaktivní. Tlačítko si tedy můžeme zobrazit obyčejnou zobrazovací procedurou (Putimage). Jediný rozdíl je, že potom netestujeme polohu myši vůči obrázku tlačítka, ale vůči masce:

if MysVPoli(x1,y1,x2,y2) and (maska[mysY-y1,mysX-x1]<>pruhledna) then {myš je uvnitř}
                                                                 else {myš je mimo};

Kdo nevěří, nechť se na přiloženém demu přesvědčí na vlastní oči, že tyhle způsoby detekce polohy opravdu fungují. Zip obsahuje zkompilovaný EXE a dva datové soubory (kurzor myši a obrázek tlačítka), zdroják není potřeba (jen by mátl).

Zpět

Reklamy: