Documente Academic
Documente Profesional
Documente Cultură
Mouse-ul
Mouse-ul este un dispozitiv de indicare cu unul sau mai multe butoane. În ciuda experimentelor făcute cu mai
multe tipuri de dispozitive de indicare, cum ar fi ecranele sensibile la atingere (touch screen) sau creioanele optice
(light pen), mouse-ul (şi alte produse asemănătoare precum bilele - trackballs - folosite pentru calculatoarele
portabile) este singurul dispozitiv care a pătruns pe scară largă pe piaţa calculatoarelor personale.
Lucrurile nu au fost, însă, întotdeauna aşa. Primii dezvoltatori ai sistemului de operare Windows şi-au dat
seama că nu pot să oblige utilizatorii să cumpere un mouse, pentru a utiliza produsul software. Ca urmare, au
considerat mouse-ul un accesoriu opţional şi au furnizat o interfaţă cu tastatura pentru toate operaţiile din
Windows şi din aplicaţiile livrate împreună cu acesta, lucru pe care l-au făcut şi alţi dezvoltatori.
Deşi mouse-ul a devenit un dispozitiv aproape universal pentru calculatoarele pe care rulează Windows, eu
cred încă în acest principiu. Cei care se descurcă foarte bine cu tastatura (şi în special dactilografele) preferă să
ţină mâinele deasupra tastaturii şi presupun că multe persoane au avut surpriza de a „pierde" uneori mouse-ul pe
un birou aglomerat. Din aceste motive, eu încă mai recomand - atunci când este posibil - includerea în program a
unei interfeţe cu tastatura, care să dubleze funcţiile mouse-ului.
Elemente de bază despre mouse
Windows 95 permite folosirea mouse-ului cu un buton, cu două butoane sau cu trei butoane, precum şi
folosirea unui joystick sau a unui creion optic, pentru simularea unui mouse cu un buton. Deoarece mouse-ul cu un
singur buton reprezintă un numitor comun, mulţi programatori Windows au evitat multă vreme să folosească
celelalte butoane ale mouse-ului. Totuşi, mouse-ul cu trei butoane a devenit un standard de facto, aşa că reticenţa
tradiţională privind folosirea celui de-al doilea buton nu mai este justificată. Al doilea buton al mouse-ului este
recomandat pentru apelarea „meniurilor de context" - meniuri care apar în fereastră în afara barei de meniu - sau
pentru operaţii speciale de tragere (despre care vom discuta în curând). Puteţi să determinaţi dacă mouse-ul este
prezent folosind funcţia GetSystemMetrics:
fMouse = GetSystemMetrics (SM_MOUSEPRESENT) ;
Variabila fMouse va avea valoarea TRUE (diferită de zero) dacă mouse-ul este instalat. Pentru determinarea
numărului de butoane ale mouse-ului instalat, folosiţi tot funcţia GetSystemMetrics:
cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS) ;
Dacă în program sunt folosite atât butonul din stânga cât şi cel din dreapta al mouse-ului şi vreţi să permiteţi
folosirea programului şi de către utilizatorii care folosesc un mouse cu un singur buton, puteţi să scrieţi codul
astfel încât apăsarea tastei Shift în combinaţie cu butonul din stânga să fie echivalentă cu butonul din dreapta. În
acest caz, codul de prelucrare a mesajelor generate de mouse pentru acţionarea buloanelor ar trebui să arate astfel:
case WM_ LBUTTONDOWN
if (!MK_SHIFT & wParam)
{
[codul pentru butonul din stânga al mouse-ulul]
return 0 ;
}
// trece la următoarea secvenţa case, deoarece nu am folosit instrucţiunea break
case WM_RBUTTONDOMN
[codul pentru butonul din dreapta al mouse-ului]
return 0 ;
Dacă în stilul ferestrei nu este inclus identificatorul CS_DBLCLKS şi utilizatorul execută de două ori clic pe
butonul din stânga al mouse-ului într-o succesiune rapidă, procedura de fereastră va recepţionă următoarele
mesaje: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDOWN şi WM_LBUTTONUP. (Între
aceste mesaje s-ar putea ca procedura de fereastră să primească şi alte mesaje.) Dacă vreţi să implementaţi o logică
proprie pentru interpretarea mesajelor care reprezintă un dublu clic puteţi să folosiţi funcţia Windows
GetMessageTime ca să obţineţi timpul relativ de generare a mesajelor WM_LBUTTONDOWN. Despre această
funcţie vom discuta în detaliu în Capitolul 7.
Dacă în stilul ferestrei este inclus identificatorul CS_DBLCLKS, procedura de fereastră va recepţionă
următoarele mesaje: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK si
WM_LBUTTONUP. Mesajul WM_LBUTTONDBLCLK înlocuieşte al doilea mesaj WM_LBUTTONDOWN.
Prelucrarea mesajelor generate de dublu clic este mai simplă dacă primul dintre cele două clicuri declanşează
executarea aceloraşi acţiuni ca şi un clic simplu. Al doilea clic (care generează mesajul
WM_LBUTTONDBLCLK) poate să determine execuţia unor operaţii suplimentare faţă de primul clic. Ca
exemplu, gândiţi-vă la modul în care este folosit mouse-ul pentru lista de fişiere afişată de Windows Explorer. Un
singur clic selectează fişierul; Windows Explorer marchează fişierul respectiv afişându-i numele în mod video
invers. Un dublu clic execută două acţiuni: primul clic selectează fişierul, aşa cum face şi un clic simplu; al doilea
clic cere programului Windows Explorer să execute fişierul selectat. O logică destul de simplă. Codul de tratare a
mesajelor generate de mouse se complică dacă primul clic dintr-o serie de două nu execută aceleaşi operaţii ca şi
un clic simplu.
Mesaje generate de mouse în afara zonei client
Cele zece mesaje discutate până acum sunt generate atunci când mouse-ul este deplasat sau când se execută
clic în cadrul zonei client a unei ferestre. Dacă mouse-ul se află în afara zonei client, dar se află încă în fereastră,
Windows trimite procedurii de fereastră un mesaj „non-client". Zona „non-client" include bara de titlu, meniul şi
barele de derulare ale ferestrei.
În general nu este nevoie să prelucraţi mesajele generate în afara zonei client. Le transmiteţi pur şi simplu
funcţiei DefWindowProc pentru a permite sistemului de operare Windows să execute funcţiile de sistem
corespunzătoare. Din acest punct de vedere, mesajele „non-client" sunt asemănătoare cu mesajele de tastatură
WM_SYSKEYDOWN, WM_SYSKEYUP şi WM_SYSCHAR.
Mesajele generate de mouse în afara zonei client corespund mesajelor din zona client, dar includ caracterele
„NC" (de la „non-client"). Dacă mouse-ul este deplasat în afara zonei client a unei ferestre, procedura de fereastră
primeşte următoarele mesaje:
Recepţionaţi un mesaj generat de un clic de mouse cu coordonatele cxMouse şi cyMouse. Puteţi să determinaţi
coloana indicată de utilizator folosind formula:
iColumn = cxMouse/cxColWidth ;
Un program de exemplificare
Programul CHECKER1, prezentat în Figura 6-4, ilustrează câteva operaţii simple de testare a poziţiei.
Programul împarte zona client într-o matrice de 5x5 dreptunghiuri Daca executaţi clic pe unul dintre
dreptunghiuri, în interiorul acestuia este desenat un X. Daca executaţi din nou un clic în acelaşi dreptunghi, X-ul
este şters.
/*------------------------------------------------- DispatchMessage (&msg) ;
CHECKER1.C -- Mouse Hit-Test Demo Program No. 1 }
(c) Charles Petzold, 1996 return msg.wParam ;
-------------------------------------------------*/ }
Nu trebuie să determinaţi dacă mouse-ul este instalat înainte de apelarea funcţiei ShowCursor. Dacă vreţi să
afişaţi indicatorul mouse-ului indiferent dacă mouse-ul este prezent sau nu, incrementaţi contorul de afişare. În
cazul în care incrementaţi contorul o singură dată, după decrementare indicatorul va dispărea dacă mouse-ul nu
este instalat, dar va rămâne afişat dacă mouse-ul este instalat. Contorul de afişare este unic pentru toate
programele din Windows, aşa că trebuie să vă asiguraţi că îl incrementaţi şi îl decrementaţi de tot atâtea ori.
Puteţi să folosiţi în procedura de fereastră următoarea logică de prelucrare:
case WM SETFOCUS :
ShowCursor (TRUE) ;
return 0 ;
case WM_KILLFOCUS :
ShowCursor (FALSE) ;
return 0 ;
Procedura de fereastră primeşte mesajul WM_SETFOCUS atunci când fereastra obţine cursorul de intrare
(input focus) şi mesajul WM_KILLFOCUS atunci când pierde cursorul de intrare. Acestea sunt momentele cele
mai potrivite pentru afişaREA ŞI MASCAREA INDICATORULUI. ÎN PRIMUL RÂND, mesajele WM_SETFOCUS şi
WM_KILLFOCUS sunt transmise în număr egal - ceea ce înseamnă că procedura de fereastră va incrementa şi va
decrementa de tot atâtea ori contorul de afişare a indicatorului. În al doilea rând, pentru calculatoarele pe care nu
este instalat un mouse folosirea mesajelor WM_SETFOCUS şi WM_KILLFOCUS va determina afişarea
indicatorului numai atunci când fereastra dumneavoastră deţine cursorul de intrare. În acest fel, utilizatorul poate
să mute indicatorul mouse-ului folosind interfaţa cu tastatura pe care o proiectaţi.
Windows păstrează poziţia curentă a mouse-ului chiar dacă acesta nu este instalat. Dacă mouse-ul nu este
instalat şi afişaţi indicatorul, acesta poate apărea în orice punct al ecranului şi va rămâne acolo pană când îl mutaţi
în mod explicit. Puteţi să obţineţi poziţia indicatorului folosind funcţia GetCursorPos:
GetCursorPos (pPoint) ;
unde point este un pointer la o structură de tip POINT. Funcţia GetCursorPos completează câmpurile structurii
POINT cu coordonatele x si y ale mouse-ului. Puteţi să stabiliţi poziţia indicatorului folosind funcţia
SetCursorPos:
SetCursorPos (x, y) ;
În ambele cazuri, valorile x şi y reprezintă coordonate ecran, nu coordonate ale zonei clent. (Acest lucru ar
trebui să fie evident, deoarece funcţia nu primeşte un parametru hwnd). Aşa cum am arătat anterior, puteţi să
transformaţi coordonatele ecran în coordonate ale zonei client şi invers, folosind funcţiile ScreenToClient şi
ClientToScreen.
Dacă apelaţi funcţia GetCursorPos în timpul prelucrării unui mesaj generat de mouse şi transformaţi valorile
obţinute în coordonate ale zonei client, rezultatele obţinute s-ar putea să fie diferite de cele transmise prin
parametrul lParam al mesajului. Coordonatele returnate de funcţia GetCursorPos indică poziţia curentă a mouse-
ului, iar coordonatele transmise prin parametrul lParam indică poziţia mouse-ului în momentul generării
mesajului.
Probabil veţi dori să implementaţi o interfaţă cu tastatura care să permită deplasarea indicatorului mouse-ului
cu săgeţile de pe tastatură şi simularea butoanelor cu bara de spaţiu şi tasta Enter. Desigur, nu doriţi să mutaţi
indicatorul cu un singur pixel la fiecare apăsare de tastă. Aceasta ar obliga utilizatorul să ţină o tasta cu săgeată
apăsată mai mult de un minut ca să mute indicatorul mouse-ului dintr-o parte în alta a ecranului.
Dacă doriţi să implementaţi o interfaţă eficientă cu tastatura pentru indicatorul mouse-ului, dar să aveţi totuşi
posibilitatea să-l poziţionaţi cu precizie, trebuie să prelucraţi mesajele generate de acţionarea tastelor astfel încât
atunci când ţineţi apăsată o tastă, indicatorul să se deplaseze mai întâi încet, apoi din ce în ce mai repede. Vă
amintiţi că parametrul IParam al mesajului WM_KEYDOWN precizează dacă mesajul respectiv este rezultatul
autorepetării tastei apăsate. Aceasta poate fi o aplicaţie excelentă a informaţiei respective.
Adăugarea unei interfeţe cu tastatura la programul CHECKER
Programul CHECKER2, prezentat în Figura 6.6, este identic cu programul CHECKER1, exceptând faptul că
include şi o interfaţă cu tastatura. Puteţi să folosiţi săgeţile ca să deplasaţi indicatorul între cele 25 de
dreptunghiuri. Tasta Home trimite indicatorul în dreptunghiul din colţul din stânga-sus; tasta End îl trimite în
După apelarea funcţiei SetCapture, Windows trimite toate mesajele generate de mouse către fereastra indicată
de variabila handle hwnd. Mesajele trimise sunt generate pentru zona client a ferestrei, chiar dacă mouse-ul se află
în afara acesteia. Parametrul lParam indică poziţia indicatorului mouse-ului în coordonatele zonei client. Aceste
coordonate pot avea valori negative dacă mouse-ul se află în stânga sau deasupra zonei client a ferestrei.
După capturarea mouse-ului, funcţiile de sistem ale tastaturii sunt dezactivate. Atunci când doriţi să eliberaţi
mouse-ul, apelaţi funcţia ReleaseCapture:
ReleaseCapture () ;