e-mail    Debatní kniha    Mapa stránek    Hlavní  
 perličky 
 

Double cklick & spol.

Jiří Nesládek

V graficky orientovaných programech je znakem uživatelské přívětivosti možnost ovládání myší. Když jsem dodělal svůj poslední program (samozřejmě ovladatelný myší), přišel mi ho "zkolaudovat" můj přítel. Zhýčkaný prostředím Windows 3.1 po chvíli testování prohlásil: "Chybí tomu dablklik." Slíbil jsem mu, že ho příští program mít bude.

Původní záměr vytvořit něco na testování doubleclicku jsem rozšířil na vytvoření "myších front" stisků, uvolnění a doubleclicků každého ze tří tlačítek myši zvlášť.

Uvedený výpis v assembleru je pouze polotovarem, který by měl nakonec získat formu přerušení nebo rezidentního programu.

Program vychází z toho, že standartní ovladač myši má službu 0ch, která umožňuje vyvolat libovolný program při změně stavu myši.

Způsob volání služby INT 33h: Vstup: AX 0ch CX volací maska ES:DX adresa obslužného programu

Volací maska určuje událost, při které má být program vyvolán:

Bit masky Událost 0 změna polohy kurzoru 1 stisknuto levé tlačítko 2 uvolněno levé tlačítko 3 stisknuto pravé tlačítko 4 uvolněno pravé tlačítko 5 stisknuto prostřední tlačítko 6 uvolněno prostřední tlačítko 7--15 nepoužito

Je-li příslušný bit masky 1, je volání povoleno, je-li 0, je zakázáno. Před ukončením práce programu je nutné masku vynulovat.

Procedura Instal provádí instalaci obsluhy Butt s maskou 126. Znamená to, že při změně stavu tlačítek ovladač myši provede standardní obsluhu, potom do AX nastaví kód události (stejný formát jako maska), do CX a DX x-ovou a y-ovou souřadnici kurzoru a vyvolá proceduru Butt.

Tato procedura zjistí, o jakou událost jde, SI nastaví v případě stisku na proměnnou udávající čas posledního stisku daného tlačítka, v případě uvolnění na ukazetel do bufferu pro dané tlačítko. Potom se zavolá obsluha stisku nebo uvolnění.

Instal: push cs ;přesměrování do našeho programu pop es ;ošetřujícího změnu stavu mov dx,offset butt ;tlačítek myši mov ax,0ch mov cx,126 int 33h ret Cteni: mov si,offset L.su mov ax,103 ;podle parametrů v CX a DX se mul dl ;vypočítá poloha ukazatelů do add si,ax ;daného bufferu add si,cx mov al,[byte ptr cs:si] ;ukazatele do AX mov ah,0 ;každý ukazatel má tři bity a mov bx,ax ;v paměti jsou v jednom bytu shr ax,3 ;je tedy třeba je rozdělit do and ax,7 ;registru AX a BX and bx,7 cmp ax,bx ;ukazují-li oba na stejné místo jne po1 ;znamená to,že buffer je prázdný mov ax,0 ;procedura pak vrací AX=0 ret po1: mov di,si ;není-li prázdný, uchová se adr. sub si,cx ;ukaztelů a vypočítá se poloha shl cx,5 ;bufferu v paměti add si,cx ;protože je každá souřadnice add si,3 ;ve frontě dvoubytová ukazatel shl bx,1 ;v BX se vynásobí 2 mov cx,[word ptr cs:si+bx] ; x-ová -> CX mov dx,[word ptr cs:si+bx+16] ; y-ová -> DX shr bx,1 ;ukazatel se zpátky vydělí, inc bx ;posune na další souřadnici and bx,7 ;vymaskuje shl ax,3 ;oba ukazatelé se opět složí do or ax,bx ;jednoho bytu, mov [byte ptr cs:di],al ;uloží se do paměti a mov ax,1 ;procedura vrací CX=x, DX=y, ret ;AX=1 butt: cli ;zde začíná obsluha tl. myši push ax bx si di es ;uloží se používané reg. mov bx,-2 ;převede se kód akce z kódu 1z7 bu1: rcr ax,1 ;do BIN (BX) inc bx jnc bu1 shl bx,1 ;tento se vynásobí dvěmi mov si,offset taboff ;do SI se nahraje mov si,[word ptr cs:si+bx] ;příslušný offset and bx,2 ;zjistí se bylo-li tl. stisknuto jz stisk ;nebo uvolněno pusteni:mov di,34 ;DI <- vzdálenost ukazatelů od zapis: mov al,[byte ptr cs:si] ;bufferu mov ah,0 ;do AL ukazatelé mov bx,ax ;ukazatelé se opět rozloží shr bx,3 ;do AX a BX and ax,7 and bx,7 shl bx,1 ;ukazatel zápisu se opět vynásobí add bx,di ;a přičte se vzdálenost k bufferu mov [word ptr cs:si+bx],cx ;mem <- x mov [word ptr cs:si+bx+16],dx ;mem <- y sub bx,di ;BX se obnoví shr bx,1 inc bx ;zvýší se hodnota ukazatele and bx,7 ;vymaskuje se cmp ax,bx ;je-li fronta plná posune se jne o1 ;i druhý ukazatel inc ax and ax,7 o1: shl bx,3 ;oba ukazatelé se opět spojí or ax,bx ;a uloží zpět do paměti mov [byte ptr cs:si],al pop es di si bx ax ;ubnoví se registry sti ;a předá se řízení ovladači retf ;myši stisk: call testd ;bylo-li tl. stisknuto otestuje jnb nstisk ;se na doubleclick double: mov di,65 ;nastaví se posun od bufferu add si,6 ;a posun od času jmp zapis ;a zapíší se souř. do fronty nstisk: mov di,3 add si,4 jmp zapis testd: mov ax,0 ;přečte se čas od RESETu mov es,ax ;z proměnné BIOSu (0:046ch) mov ax,[word ptr es:046ch] mov bx,[word ptr es:046eh] push ax bx ;uloží se na později sub ax,[word ptr cs:si] ;odečte se čas sbb bx,[word ptr cs:si+2] ;posledního sub ax,[word ptr cs:rozdil] ;stisku a délka sbb bx,[word ptr cs:rozdil+2] ;doubleclicku pop bx ax ;obnva AX a BX jnb ned1 ;je-li dc zabrání se dvoum dc inc bx ;na 3 stisky ned1: mov [word ptr cs:si],ax ;uloží se nynější mov [word ptr cs:si+2],bx ;čas do paměti ret Tl struc cas dd 0 ;čas posledního stisku su db 0 ;ukazatelé do fronty stisků uu db 0 ;ukazatelé do fronty uvolnění du db 0 ;ukazatelé do fronty doubleů buffsx dw 8 dup(?) ;buffer x-ových souř. stisků buffsy dw 8 dup(?) ; y buffux dw 8 dup(?) ; x uvolnění buffuy dw 8 dup(?) ; y buffdx dw 8 dup(?) ; x doubleů buffdy dw 8 dup(?) ; y Tl ends L: Tl <> P: Tl <> S: Tl <> taboff: dw offset L.cas dw offset L.uu dw offset P.cas dw offset P.uu dw offset S.cas dw offset S.uu rozdil: dd 11 ;citlivost doubleclicku

Bylo-li tlačítko uvolněno, pak se jen zapíšou souřadnice kurzoru do bufferu. Bylo-li stisknuto, provede se test na doubleclick a teprve potom se souřadnice zapíšou do příslušného bufferu.

Pro čtení souřadnic z bufferů slouží procedura Cteni. Před vstupem do ní musíte naplnit CX a DX podle toho, co chcete číst.

CX: 0...stisk 1...uvolnění 2...doubleclick DX: 0...levé tlačítko 1...pravé tlačítko 2...prostřední tlačítko

Procedura vrací AX=0, když není ve frontě pro požadované tlačítko a akci žádná souřadnice.

Jak program pracuje? Pro každé tlačítko je definována datová struktura. Skládá se z bufferů, času posledního stisku a ukazatelů. Buffery jsou organizovány jako kruhové, poberou osm souřadnic každé akce. Ukazatelé "hlavy a paty" jsou tříbitové a jsou složeny v jenom bajtu. Při požadavku o zapsání deváté souřadnice se obětuje nejstarší údaj.

Procedura na testování doubleclicku není zcela "čistá". Aby byla co nejkratší, čte přímo proměnnou BIOSu 0:046ch. Proměnnou každých cca 50 ms inkrementuje osmé přerušení. Playnite-li si sampling nebo jinak upravíte režim časovače nebo INT 8, budete muset změnit citlivost doubleclicku (proměnná rozdíl), nebo čas testovat nějak jinak (třeba funkcí DOSu).

Možná jste si všimli, že veškerá práce s pamětí je prefixována registrem CS. To proto, že všechny uvedené procedury jsou volány odkudkoli a hodnota v DS se nerovná CS. Pokud si tedy hodnotu DS nenastavíte, nezbyde vám nic jiného, než jako já adresovat skrze kódový segment. Při upravování mých procedur také dbejte na vzdálenost volání (NEAR,FAR) a přizpůsobte tomu RETy. Ve výpisu jsou všechny blízké.

Jak jsem uvedl na začátku, program je pouze neživotnou kostrou. Budete-li ho chtít využívat, měli byste si vytvořit další procedury zajišťující výmaz bufferů a nastavující citlivost doubleclicku.




Pascal - hlavní
Překladače
Vlastní články
Převzaté články
Věci na stáhnutí
Odkazy k tématu
BP7 buglist
Chyba Run-time 200

BASIC