Home - Rasfoiesc.com
Educatie Sanatate Inginerie Business Familie Hobby Legal
Doar rabdarea si perseverenta in invatare aduce rezultate bune.stiinta, numere naturale, teoreme, multimi, calcule, ecuatii, sisteme




Biologie Chimie Didactica Fizica Geografie Informatica
Istorie Literatura Matematica Psihologie

Informatica


Index » educatie » Informatica
» Gestiunea Mouse-lui


Gestiunea Mouse-lui


Gestiunea Mouse-lui

Mesaje de tratare a miscarii mouse-lui si apasarii butoanelor

Sistemul de operare Windows accepta atat mouse cu 3 butoane (tip Genius) cat si cu 2 butoane (tip Microsoft). Programele pot intercepta (sesizarea si tratarea unui eveniment produs in starea sistemului de calcul se numeste interceptare) doua tipuri de evenimente referitoare la butoanele mouse-lui: un eveniment de apasare si un eveniment de eliberare. In scopul interceptarii acestor mesaje, sistemul de operare trimite mesaje corespunzatoare catre clasa de baza a ferestrei programului.

Mesajele corespunzatoare mouse-lui sunt:



Mesaj

Descriere

WM_LBUTTONDOWN

WM_LBUTTONDBLCLK

WM_LBUTTONUP

WM_RBUTTONDOWN

WM_RBUTTONDBLCLK

WM_RBUTTONUP

WM_MOUSEMOVE

WM_MOUSEWHEEL

WM_SETCURSOR

WM_MBUTTONDOWN

WM_MBUTTONDBLCLK

WM_MBUTTONUP

Buton stanga apasat

Dublu click pe buton stanga

Buton stanga eliberat

Buton dreapta apasat

Dublu click pe buton dreapta

Buton dreapta eliberat

A fost modificata pozitia prompterului mouse-lui

A fost modificata pozitia bilei mouse-lui

Se modifica forma prompterului

Buton din mijloc (daca exista) apasat

Dublu click pe buton din mijloc (daca exista)

Buton din mijloc eliberat (daca exita)

Pozitia prompterului mouse-lui este citita la fiecare miscare a acestuia. Mesajul transmis de Windows la miscarea prompterului este WM_MOUSEMOVE. Functia de tratare a evenimentului primeste doi parametri:

nFlags, care specifica asupra carui element al mouse-lui s-a efectuat o modificare; acest parametru este in general utilizat impreuna cu o masca de biti, care poate fi apelata prin indicatori formali, ca in tabelul de mai jos:

Valoare indicator

Descriere

MK_LBUTTON

MK_MBUTTON

MK_RBUTTON

MK_CONTROL

MK_SHIFT

Butonul stang a fost apasat

Butonul din mijloc a fost apasat

Butonul drept a fost apasat

Tasta CTRL a fost apasata

Tasta SHIFT a fost apasata

point - care este un obiect de tip CPoint cu structura:

typedef struct tagCPoint CPoint;

unde x este abscisa iar y ordonata pozitiei punctului specificat. Aceste coordonate sunt relative la marginile ferestrei.

Similar interceptarii mesajelor de apasare a butoanelor, se face interceptarea mesajelor de eliberare a butoanelor.

Capturarea propmpterului

Atunci cand prompterul depaseste marginile ferestrei mesajele nu vor mai fi receptionate de fereastra activa ci de fereastra peste care este suprapus cursorul. Pentru ca si dupa ce prompterul depaseste marginile ferestrei active sa fie trimise mesajele tot catre aceasta, este necesar sa fie realizata capturarea prompterului. Aceasta se face prin intermediul metodei SetCapture(). Operatia inversa, de eliberare a prompterului, se face prin metoda ReleaseCapture(). In cazul in care nu se face eliberarea prompterului celelalte ferestre nu vor mai primi mesaje normale de la mouse si Windows nu va mai functiona corect.

Implementarea unui test de click

In marea majoritate a aplicatiilor apare necesitatea determinarii daca s-a efectuat un click deasupra unei anumite zone. Cazul cel mai des intalnit este executarea unui click asupra unui obiect pentru selectarea lui.. Acest test se efectueaza prin intermediul unui test de click. Testul de click presupune verificarea faptului ca la apasarea unui buton, prompterul se afla sau nu in interiorul unui anumit obiect, specificat uzual prin intermediul unui dreptunghi de context. Pentru realizarea testului de click pozitia prompterului la apasarea butonului trebuie retinuta intr-o variabila care este comparata cu marginile contextului dispozitiv pentru obiectul dorit.

Utilizarea clasei CRectTracker

In marea majoritate a aplicatiilor, la apasarea butonului stang si deplasarea mouse-lui cu butonul apasat, apare un dreptunghi elastic care selecteaza simultan toate obiectele din interiorul lui. Aceasta operatie se numeste incadrare dreptunghiulara. Ea este implementata prin intermediul clasei CRectTracker, care realizeaza capturarea mouse-lui, selectarea unei suprafete si testarea daca anumite puncte se afla in interiorul dreptunghiului. Pentru testarea apartenentei anumitor obiecte la suprafata selectata se va defini o variabila membru de tip CRectTracker. Pentru utilizarea incadrarii dreptunghiulare, obiectul de incadrare trebuie initializat cu un dreptunghi si un stil initial. Stilurile pentru dreptunghiurile de incadrare sunt:

Valoare de stil

Descriere

CRectTracker::SolidLine

CRectTracker::dottedLine

CRectTracker::hatchedBorder

CrectTracker::hatchInside

CrectTracker::resizeInside

CRectTracker::resizeOutside

Traseaza dreptunghiul cu linie continua

Traseaza dreptunghiul cu linie intrerupta

Traseaza dreptunghiul cu linie groasa, hasurata

Deseneaza hasura pe suprafata selectata

Marginea de dimensionare este in interiorul dreptunghiului

Marginea de dimensionare este in exteriorul dreptunghiului

Procesul de incadrare elastica este realizat de metoda TrackRubberBand() a clasei CRectTracker. Ea necesita trei parametrii, primul fiind un pointer la fereastra in care va avea loc operatia de incadrare elastica. Al doilea parametru este originea dreptunghiului elastic de incadrare, care trebuie sa fie pozitia in care s-a executat click. Al treilea parametru este optional si daca este TRUE permite extinderea dreptunghiului de incadrare si inspre stanga sus fata de pozitia initiala, altfel permite doar extinderea inspre dreapta jos.

Pentru a testa daca punctul specificat ca parametru se afla in interiorul suprafetei selectate se utilizeaza metoda HitTest(). Aceasta intoarce urmatoarele valori:

Valoare

Semnificatie

CRectTracker::hitNothing

CRectTracker::hitTopLeft

CRectTracker::hitTopRight

CRectTracker::hitBottomRight

CRectTracker::hitBottomLeft

CRectTracker::hitTop

CRectTracker::hitRight

CRectTracker::hitLeft

CRectTracker::hitBottom

CRectTracker::hitMiddle

Punctul nu se afla in interiorul dreptunghiului

Punctul se afla in coltul stanga sus

Punctul se afla in coltul dreapta sus

Punctul se afla in coltul dreapta jos

Punctul se afla in coltul stanga jos

Punctul se afla in partea de sus

Punctul se afla in partea dreapta

Punctul se afla in partea stanga

Punctul se afla in partea de jos

Punctul se afla in centru

Exemplul 1. Sa se creeze proiectul Proj1 care afiseaza continuu in antetul ferestrei, pozitia curenta (relativa si absoluta) a prompterului. Sa se intercepteze apasarile butoanelor in functie de apasarea sau nu a tastei CTRL, sa se selecteze o pictograma standard din setul de pictograme de mai jos:

Pictograma

Descriere

IDI_EXCLAMATION

IDI_HAND

IDI_APPLICATION

IDI_ASTERISK

IDI_QUESTION

Semn de exclamare in interiorul unui triunghi galben

Un X intr-un cerc rosu

Pictograma implicita a aplicatiei

Un I intr-o forma alba

Un semn de intrebare intr-o forma alba

a.       Se intra in pagina Class View a WorkSpace. Se selecteaza clasa de dialog de baza a aplicatiei, Cproj1Dlg. In meniul contextual se selecteaza optiunea Add Windows Message Handler, in caseta New Window Message and Event Handlers se selecteaza evenimentul de tip WM_.. Dorit, se apasa butonul Add and Edit si se accepta numele functiei care urmeaza sa fie creata. Astfel se creeaza se se editeaza functiile de mai jos:

void CPr1Dlg::OnMouseMove(UINT nFlags, CPoint point)

void CPr1Dlg::OnLButtonDown(UINT nFlags, CPoint point)

void CPr1Dlg::OnRButtonDown(UINT nFlags, CPoint point)

void CPr1Dlg::OnLButtonUp(UINT nFlags, CPoint point)

Observatii:

1. Mesajul transmis de Windows la miscarea prompterului este WM_MOUSEMOVE. Acest mesaj va fi selectat pentru interceptarea miscarii mouse-lui, fiind creata functia OnMouseMove(), care este completata cu codul de mai sus.

2. Pentru interceptarea apasarii butonului stang, va fi selectat mesajul WM_WMLBUTTONDOWN fiind creata functia OnLButtonDown().Similar, functia care raspunde apasarii butonului drept va fi OnRButtonDown().

3. Linia Invalidate() a fost introdusa pentru ca la fiecare miscare fereastra sa fie redesenata.

4. Clasa CDC defineste obiecte dependente de contextul dispozitivului utilizat. Functia LoadStandardIcon() primeste un pointer la pictograma standard, pe care o afiseaza.

7. Pentru determinarea coordonatelor absolute ale prompterului mouse-lui se utilizeaza functia GetCursorPos(). Ca parametru, aceasta functie primeste un pointer la obiectul CPoint in care va fi inscrisa pozitia cursorului. Pozitia absoluta este pozitia relativa la originea ecranului si nu la originea ferestrei active. In cazul utilizarii acestor coordonate in functiile de tratare a apasarii butoanelor, in locul celor relative la originea ferestrei active,, pictogramele vor fi afisate la o oarecare distanta de pozitia prompterului, deoarece functia de desenare asteapta pozitii relative la fereastra.

Exemplul 2. Sa se construiasca proiectul Proj2 a carui fereastra de dialog contine doi ochi care urmaresc pozitia prompterului mouse-ului.

a.       Utilizand Add Member Variable din meniul contextual al clasei CProj2Dlg se adauga variabila m_ptMouse de tip Cpoint.

b.      Se intercepteaza miscarea prompterului si se implementeaza functia OnMouseMove() astfel:

void CPr2Dlg::OnMouseMove(UINT nFlags, CPoint point)

c.       Se modifica ramura else a functiei OnPaint(), astfel:

void CPr2Dlg::OnPaint()

else

CDialog::OnPaint();

}

Observatii:

1. Pentru desenarea ochilor se construieste un obiect context dispozitiv, care se refera la fereastra curenta, de tip CPointDC. Metoda GetClientRect() determina dimensiunea casetei de dialog si o memoreaza in obiectul CRect rcDlg, care specifica colturile unui dreptunghi. Clasa CRect contine doua obiecte CPoint, unul pentru coordonatele coltului stanga sus si celalalt pentru coordonatele coltului dreapta jos, astfel:

public final class CRect

Se executa apoi secventa care va desena cei doi ochi. Se determina centrul ferestrei active, prin metoda CenterPoint(). Daca este primul ochi, ordonata se deplaseaza cu 80 de pixeli la stanga, iar daca este al doilea, cu 80 de pixeli la dreapta. Apoi, se creeaza un dreptunghi de incadrare pe centrul ochiului curent. Acest dreptunghi este apoi umflat cu 20 pixeli pe axa x si cu 40 pe axa y. Acest dreptunghi va constitui noul context dispozitiv referitor la care se vor face urmatoarele operatii. Desenarea ochiului alb se face prin selectarea unui obiect de tip BRUSH de culoare alba si desenarea unei elipse tangente la laturile dreptunghiului ce constituie noul dispozitiv context. Elipsa va avea interiorul de culoare alba. Se revine apoi la contextul initial. Se calculeaza pozitia relativa a pupilei in cadrul ochiului, dependenta de pozitia mouse-lui si scalata respectiv la dimensiunile ferestrei programului. Metoda OffsetRect() deplaseaza dreptunghiul la care se refera (contextul dispozitiv in cazul nostru) pe axa x si y. Valorile negative pentru parametri semnifica deplasare la stanga sau respectiv in sus. Este desenata apoi o elipsa de culoare neagra, tangenta la noul context dispozitiv.

Exemplul 3. Sa se modifice proiectul anterior astfel incat daca se va apasa si se va tine apasat butonul drept cand prompterul este in interiorul programului ochii sa urmareasca prompterul si in afara acesteia.

a.       Se adauga functiile care intercepteaza apasarea si eliberarea butonului drept, astfel:

void CPr2Dlg::OnRButtonDown(UINT nFlags, CPoint point)

void CPr2Dlg::OnLButtonDown(UINT nFlags, CPoint point)

Observatii:

a. Prin apasarea butonului drept in exteriorul ferestrei de dialog va fi activata fereastra in interiorul careia este prompterul. Tratarea apasarii se face de catre fereastra in care s-a facut apasarea pentru ca spre acea fereastra este transmis mesajul de apasare.

b. Coordonatele relative pot deveni negative, pentru ca acestea sunt calculate tot timpul referitor la coltul stinga sus al ferestrei care a capturat prompterul.

Exemplul 4. Sa se modifice proiectul anterior astfel incat la apasarea butonului drept in interiorul unui ochi sa se coloreze interiorul ochiului in culoarea gri iar la apasare in exterior sa se coloreze ochii in alb.

a.       Se adauga variabila membru m_ptPozButton de tip Cpoint utilizand Add Member Variable din meniul contextual.

b.      Se modifica functia OnRButtonDown() astfel:

void CPr2Dlg::OnRButtonDown(UINT nFlags, CPoint point)

c.       Se face urmatoarae modificare in functia OnPaint():

// se desenaza un ochi alb

if(rcEye.PtInRect(m_ptPozButton))

dc.SelectStockObject(GRAY_BRUSH);

else

dc.SelectStockObject(WHITE_BRUSH);

Observatii

Metoda PtInRet() intoarce valoarea TRUE daca punctul primit ca parametru se afla in interiorul dreptunghiului de test, adica in contextul dispozitiv curent in acest caz.

Exemplul 5. Sa se modifice proiectul de mai sus astfel incit cu ajutorul butonului stang sa fie posibila incadrarea elastica a fiecarui ochi intr-un dreptunghi. Daca ochiul se afla in deptunghiul selectat ochiul este desenat gri, altfel el este desenat alb.

a.       Se adauga variabila membru m_RectTracker de tip CRectTracker() utilizand Add Member Variable.

b.      Se modifica constructorul clasei CPr2Dlg astfel:

CPr2Dlg::CPr2Dlg(CWnd* pParent /*=NULL*/)

: CDialog(CPr2Dlg::IDD, pParent),m_RectTracker(CRect(0,0,0,0), CRectTracker::hatchedBorder+CRectTracker::resizeOutside)

}AFX_DATA_INIT

// Note that LoadIcon does not require a subsequent DestroyIcon in Win32

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

c.       In functia OnLButtonDown() se adauga o noua linie, astfel:

void CPr2Dlg::OnLButtonDown(UINT nFlags, CPoint point)

d.      Functia OnLButtonUp() va fi functia implicita

void CPr2Dlg::OnLButtonUp(UINT nFlags, CPoint point)

e.       Se modifica in functia OnPaint():

// se desenaza un ochi alb

if(rcEye.PtInRect(m_ptPozButton) || m_RectTracker.HitTest(rcEye.CenterPoint())!=CRectTracker::hitNothing)

dc.SelectStockObject(GRAY_BRUSH);

else

dc.SelectStockObject(WHITE_BRUSH);

Observatii:

Codul adaugat in contructorul clasei are ca scop initializarea variabilei m_RectTracker cu un dreptunghi nul, astfel incat initial nu este selectat nimic. La selectie este trasat un dreptunghi cu margini groase hasurate, care include marginile in suprafata de selectie.

Operatia de incadrare incepe prin apasarea butonului stang, de aceea metoda TrackRubberBand() se adauga in functia OnLbuttonDown().

Modificarea introdusa in OnPaint() are ca scop verificarea incadrarii. Functiei HitTest() ii este transmis ca parametru centrul contextului dispozitiv care incadreaza ochiul.





Politica de confidentialitate





Copyright © 2024 - Toate drepturile rezervate