Sunteți pe pagina 1din 39

LUCRARE DE LABORATOR NR.

1
TEMA: Aplicaii Windows
Scopul lucrrii: Studierea bazelor i principiilor de creare a aplicaiilor
Windows
Noiuni teoretice
Windows este o interfa grafic cu utilizatorul (GUI - graphical user
interface), numit uneori i interfa vizual" sau mediu grafic cu ferestre"
(graphical windowing environment"). Toate tipurile de interfee grafice cu
utilizatorul folosesc elemente grafice afiate ntr-o imagine de tip bitmap.
Elementele grafice asigur o utilizare mai eficient a spaiului de afiare, un
mediu bogat din punct de vedere vizual pentru transferul de informaii i
posibilitatea de afiare a rezultatelor aa cum vor arta n realitate pe hrtie
(WYSIWYG - what you see is what you get).
Toate programele pentru Windows au un aspect asemntor i se
comport fundamental la fel. Programele ocup o fereastr - o suprafa
dreptunghiular de pe ecran. Fereastra poate fi identificat datorit unei bare
de titlu. Majoritatea funciilor oferite de program sunt apelate cu ajutorul
unui meniu. Informaiile afiate care nu ncap pe un singur ecran pot fi
vizualizate cu ajutorul barelor de derulare. Unele articole de meniu apeleaz
casete de dialog n care utilizatorul introduce informaii suplimentare. n
majoritatea programelor mai mari pentru Windows exist o caset de dialog
care deschide un fiier. Aceast caset de dialog arat la fel (sau foarte
asemntor) n mai multe programe Windows i este apelat aproape
ntotdeauna cu aceeai opiune de meniu.
Apelurile de funcii
Windows asigur suportul pentru mai mult de o mie de apeluri de funcii
pe care le pot folosi aplicaiile. Fiecare funcie Windows are un nume
sugestiv, scris att cu majuscule, ct i cu minuscule, cum ar fi
CreateWindow. Aceast funcie, aa cum probabil v-ai dat seama, creeaz o
fereastr.
Toate funciile Windows importante sunt declarate n fiiere antet.
Principalul fiier antet se numete WINDOWS.H i include multe alte fiiere
antet. Aceste fiiere antet sunt furnizate de orice mediu de programare pentru

Windows, aa cum este, de exemplu, C. Fiierele antet sunt o parte


important a documentaiei Windows.
n programele pentru Windows folosii apelurile de funcii la fel cum
folosii funciile de bibiotec C, cum ar fi strlen. Principala diferen este
faptul c n cazul funciilor C codul funciilor este legat direct de codul
programului, pe cnd codul funciilor Windows este stocat n fiiere din afara
programului, numite biblioteci cu legturi dinamice (DLL - dynamic link
libraries).Mai jos sunt prezentate careva funcii Windows pentru a simplifica
crearea unei aplicaii Windows:
LoadIcon - ncarc o pictogram care urmeaz s fie folosit de un
program.
LoadCursor - ncarc un indicator pentru mouse, care urmeaz s fie
folosit de un program.
GetStockObject - obine un obiect grafic (n acest caz o pensul folosit
pentru desenarea fondului ferestrei).
RegisterClassEx - nregistreaz o clas de fereastr pentru fereastra
programului.
CreateWindow - creeaz o fereastr pe baza unei clase de fereastr.
ShowWindow - afieaz o fereastr pe ecran.
UpdateWindow - cere unei ferestre s se redeseneze.
GetMessage - preia un mesaj din coada de mesaje.
TranslateMessage - convertete unele dintre mesajele de la tastatur.
DispatchMessage - trimite un mesaj ctre o procedur de fereastr.
PlaySound - red un fiier de sunet.
BeginPaint - iniiaz o operaie de desenare a ferestrei.
GetClientRect - obine dimensiunile zonei client a ferestrei.
DrawText - afieaz un text.
EndPaint - ncheie o operaie de desenare.
PostQuitMessage - insereaz un mesaj de ncheiere n coada de ateptare.
DefWindowProc - execut operaiile prestabilite de prelucrare a
mesajelor.
Aceste funcii sunt documentate n cri i n sursele incluse de
compilator i sunt declarate n diferite fiiere antet incluse n fiierul
WINDOWS.H.
Programarea n Windows este un tip de programare orientat pe obiecte
(OOP -object-oriented programming). Acest lucru devine evident dac v
2

gndii la obiectul pe care l vei folosi cel mai mult n Windows - obiectul
care d numele sistemului de operare, obsedanta fereastr".
Aa cum am menionat mai devreme, ferestrele sunt nite suprafee
dreptunghiulare de pe ecran. O fereastr primete intrri de la tastatur sau de
la mouse i afieaz rezultate n zona proprie de pe suprafaa ecranului.
Fereastra unei aplicaii conine, de obicei, bara de titlu a programului,
meniul, chenarul de dimensionare i, eventual, barele de derulare. Casetele
de dialog sunt ferestre adiionale. Mai mult, suprafaa unei casete de dialog
conine ntotdeauna cteva ferestre suplimentare, numite ferestre
descendent" (child windows"). Ferestrele descendent apar sub forma
butoanelor de apsare, a butoanelor radio, a casetelor de validare, a
cmpurilor pentru introducerea textului, casetelor-list i a barelor de
derulare.
Utilizatorul vede ferestrele ca obiecte pe ecran i poate aciona direct
asupra lor, apsnd un buton sau manipulnd o bar de derulare. Fereastra
recepioneaz inteniile utilizatorului sub forma unor mesaje". De asemenea,
ferestrele folosesc mesaje pentru comunicarea cu alte ferestre.
Atunci cnd se spune c sistemul de operare trimite programului un
mesaj" se are n vedere c Windows apeleaz o funcie din program.
Parametrii acestei funcii descriu mesajul respectiv. Aceast funcie din
programul Windows este cunoscut sub numele de procedur de fereastr"
(window procedure").
Orice fereastr creat de un program are asociat o procedur de
fereastr. Procedura de fereastr este e funcie care se poate afla chiar n
program sau ntr-o bibliotec cu legturi dinamice (DLL). Windows trimite
un mesaj ctre o fereastr prin apelarea procedurii de fereastr. Procedura de
fereastr prelucreaz anumite informaii pe baza mesajului primit, apoi
returneaz controlul sistemului de operare.
Atunci cnd un program este lansat n execuie, Windows creeaz o
coad de mesaje" (message queue") pentru programul respectiv, n aceast
coad de mesaje sunt pstrate mesajele trimise ctre toate ferestrele pe care le
creeaz programul. Programul conine o mic secven de cod numit ciclu
de mesaje" (message loop") care preia mesajele din coada de ateptare i le
distribuie procedurilor de fereastr corespunztoare. Alte mesaje sunt trimise
direct procedurii de fereastr, fr s mai fie plasate n coada de mesaje.
O fereastr este creat ntotdeauna pe baza unei clase de fereastr".
Clasa specific procedura de fereastr care prelucreaz mesajele trimise ctre
fereastr. Folosirea unei clase de fereastr permite ca pe baza aceleiai clase
3

s se creeze mai multe ferestre care, ca urmare, folosesc aceeai procedur de


fereastr. De exemplu, toate butoanele din toate programele pentru Windows
sunt create pe baza aceleiai clase de fereastr. Aceast clas are o procedur
de fereastr (aflat ntr-una dintre bibliotecile cu legturi dinamice ale
sistemului de operare) care prelucreaz mesajele trimise ctre ferestrele
butoanelor.
nregistrarea clasei de fereastr
Clasa de fereastr identific procedura de fereastr care prelucreaz toate
mesajele trimise ctre fereastr. Atunci cnd creai o fereastr, definii i
atributele suplimentare ale acesteia, care sunt unice pentru fereastra
respectiv.
Cele mai importante cmpuri ale clasei de fereastr sunt al treilea i
penultimul. Penultimul cmp conine numele clasei de fereastr (i n
programele care creeaz o singur fereastr are, de obicei, acelai nume ca i
programul). Al treilea cmp (lpfnWndProc) este adresa procedurii de
fereastr folosit pentru toate ferestrele create pe baza acestei clase. Celelalte
cmpuri descriu caracteristicile tuturor ferestrelor create pe baza acestei
clase.
Cmpul cbSize reprezint dimensiunea structurii. Instruciunea:
wndclass.style = CS_HREDRAW | CS_VREDRAW; combin doi
identificatori pentru stilul de clas" (class style") folosind operatorul SAU
orientat pe bii din limbajul C. n fiierele antet din Windows sunt definii
mai muli identificatori cu prefixul CS_. Acestea sunt constante pe 32 de bii
n care un singur bit are valoarea 1. Identificatorii definii n acest fel sunt
numii uneori identificatori pe bii". Acetia pot fi combinai cu ajutorul
operatorului SAU orientat pe bii din limbajul C.
Cei doi identificatori pentru stilul clasei indic faptul c toate ferestrele
create pe baza acestei clase sunt redesenate complet, ori de cte ori se
modific dimensiunea pe orizontal (CS_HREDRAW) sau cea pe vertical
(CS_VREDRAW) a ferestrei.
Al treilea cmp al structurii WNDCLASSEX este iniializat prin
instruciunea:
wndclass.lpfnWndProc = WndProc;
Aceast instruciune stabilete ca procedur de fereastr funcia
WndProc. Aceast procedur va prelucra toate mesajele trimise ctre toate
ferestrele create pe baza acestei clase de fereastr. Aa cum am artat mai

sus, prefixul lpfn nseamn, n notaia ungar, pointer de tip long la o


funcie".
Urmtoarele dou instruciuni:
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
rezerv un spaiu suplimentar n structura clasei i n structura ferestrei,
pstrat n interiorul sistemului de Windows. Un program poate s utilizeze
spaiul suplimentar n scopuri proprii.
Urmtorul cmp este variabila handle a instanei (care este chiar unul
dintre parametrii funciei WinMain):
wndclass.hInstance = hinstance;
Instruciunile:
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
definesc o pictogram pentru ferestrele create pe baza acestei clase.
Pictograma este o mic imagine de tip bitmap care apare n bara de taskuri a
sistemului de operare i n bara de titlu a ferestrei. Pentru obinerea unei
variabile handle a unei pictograme predefinite apelai funcia LoadIcon cu
primul parametru avnd valoarea NULL. (Atunci cnd ncrcai o pictogram
proprie, acest parametru va conine variabila handle a instanei programului.)
Al doilea parametru este un identificator cu prefixul IDI_ definit n fiierele
antet din Windows. Pictograma IDI_APPLICATION este o mic imagine a
unei ferestre. Funcia LoadIcon returneaz o variabil handle a acestei
pictograme. Nu ne intereseaz valoarea real a acestei variabile, ci doar o
stocm n cmpurile hIcon i hIconSm. Aceste cmpuri sunt definite n
structura WNDCLASSEX de tipul HICON (handle to an icon").
Instruciunea:
wndclass.hCursor = LoadCursor (NULL, IDC_ ARROW);
este foarte asemntoare cu cele dou instruciuni anterioare. Funcia
LoadCursor ncarc un cursor predefinit pentru mouse, numit IDC_ARROW,
i returneaz o variabil handle a acestui cursor. Atunci cnd este deplasat
deasupra zonei client a ferestrei create pe baza acestei clase, indicatorul
mouse-ului este afiat sub forma unei sgei.
Urmtorul cmp precizeaz culoarea fondului zonei client a ferestrelor
create pe baza acestei clase. Prefixul hbr al numelui hbrBackground vine de
la handle to a brush" (variabil handle a unei pensule"). O pensul este un
termen grafic care se refer la un model colorat de pixeli folosit pentru
umplerea unei suprafee. Windows are mai multe pensule standard (sau
5

pensule de stoc"). Funcia GetStockObject returneaz o variabil handle a


unei pensule albe:
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
Aceasta nseamn c fondul zonei client a ferestrei va fi colorat cu alb,
ceea ce este un lucru obinuit.
Urmtorul cmp specific meniul ferestrei. Dac programul nu are nici
un meniu, valoarea acestui cmp este NULL:
wndclass.lpszMenuName = NULL;
n sfrit, clasei trebuie s i se dea un nume. Pentru programele mai mici,
acesta poate fi chiar numele programului, deci n variabila szAppName este
stocat irul de caractere HelloWin":
wndclass.IpszClassName = szAppName;
nainte de a crea fereastra programului trebuie s nregistrai o clas de
fereastr, apelnd funcia RegisterClassEx. Funcia RegisterClassEx accept
un singur parametru: un pointer la o structur de tipul WNDCLASSEX.
Structura WNDCLASSEX este definit n fiierele antet din Windows i
declarat n program n felul urmtor:
WNDCLASSEX wndclass ;
Dup ce ai definit cele 12 cmpuri ale structurii WNDCLASSEX apelai
funcia RegisterClassEx:
RegisterClassEx (&wndclass) ;
Crearea terestrei
Atunci cnd creai o fereastr apelnd funcia Create Window, putei s
specificai mai multe detalii despre fereastra respectiv. n loc s foloseasc o
structur de date, aa cum face funcia RegisterClassEx, funcia
CreateWindow cere ca toate informaiile s fie transmise ca parametri. Iat
un exemplu de apel al funciei CreateWindow:
hwnd =CreateWindow (szAppName, // numele clasei de fereastra
"The Hello Program",
// titlul ferestrei
WS_OVERLAPPEDWINDOW, // stilul ferestrei
CW_USEDEFAULT,
// poziia iniiala pe axa x
CW_USEDEFAULT,
// poziia iniiala pe axa y
CW_USE DEFAULT,
// dimensiunea iniiala pe axa x
CW_USEDEFAULT,
// dimensiunea iniiala pe axa y
NULL,
// variabila handle a ferestrei
printe
NULL,
// variabila handle a meniului
6

hlnstance,

// variabila handle a instanei


programului
NULL) ;
// parametri de creare
Parametrul notat cu numele clasei de fereastr" este szAppName, care
conine irul de caractere HelloWin" - numele clasei de fereastr pe care
tocmai am nregistrat-o. n acest fel, fereastra este asociat unei clase de
fereastr.
Fereastra creat de acest program este o fereastr normal suprapus, cu
o bar de titlu; n partea stng a barei de titlu se afl caseta cu meniul
sistem; n partea dreapt se afl butoanele de mrire, de micorare i de
nchidere; fereastra are un chenar ngroat, care permite redimensionarea.
Acesta
este
stilul
standard
al
ferestre
lor,
numit
WS_OVERLAPPEDWINDOW; n funcia CreateWindow i corespunde
comentariul stilul ferestrei". Titlul ferestrei" este textul afiat n bara de
titlu.
Parametrii notai cu poziia iniial pe axa x" i poziia iniial pe axa
y" specific poziia iniial a colului din stnga-sus al ferestrei, relativ la
colul din stnga-sus al ecranului. Prin folosirea identificatorului
CW_USEDEFAULT pentru aceti para metri indicm sistemului de operare
s foloseasc valorile prestabilite pentru o fereastr suprapus. n mod
prestabilit, Windows poziioneaz mai multe ferestre suprapuse succesive la
o distan cresctoare pe vertical i pe orizontal fa de colul din stngasus al ecranului. La fel, parametrii dimensiunea iniial pe axa x" i
dimensiunea iniial pe axa y" specific dimensiunile iniiale ale ferestrei.
Identificatorul CW_USEDEFAULT indic sistemului de operare s
foloseasc valorile prestabilite.
Parametrul indicat ca variabil handle a ferestrei printe" are valoarea
NULL, deoarece aceast fereastr nu are nici o fereastr printe. Atunci cnd
ntre dou ferestre exist o relaie printe-descendent, fereastra descendent
este afiat ntotdeauna pe suprafaa ferestrei printe. Parametrul indicat ca
variabil handle a meniului" are tot valoarea NULL, deoarece fereastra nu
are meniu. Parametrul indicat ca variabil handle a instanei programului"
are ca valoare variabila handle transmis programului ca parametru la
apelarea funciei WinMain. n sfrit, parametrul de creare" are valoarea
NULL. Putei s folosii acest parametru pentru adresarea unor date folosite
ulterior n program.
Funcia Create Window returneaz o variabil handle a ferestrei create.
Aceasta este salvat n variabila hwnd, definit ca fiind de tipul HWND
7

(variabil handle a unei ferestre). Orice fereastr din Windows are o variabil
handle. Programul folosete variabila handle pentru indicarea ferestrei. Multe
funcii Windows au un parametru hwnd, care specific fereastra la care se
refer funcia respectiv. Dac un program creeaz mai multe ferestre,
fiecare are o variabil handle diferit. Variabila handle a unei ferestre este
una dintre cele mai importante variabile folosite n Windows.
Afiarea ferestrei
Dup executarea funciei CreateWindow, fereastra a fost creat de
Windows, dar nc nu este afiat pe ecran. Pentru aceasta mai sunt necesare
nc dou apeluri de funcii. Primul este:
ShowWindow (hwnd, iCmdShow) ;
Primul parametru este o variabil handle a ferestrei create de funcia
CreateWindow. Al doilea parametru este variabila iCmdShow, transmis
funciei WinMain. Dac iCmdShow este SW_SHOWNORMAL (egal cu 1),
fereastra
este
afiat
normal.
Dac
iCmdShow
este
SW_SHOWMINNOACTIVE (egal cu 7), atunci fereastra nu este afiat, dar
numele i pictograma acesteia apar pe bara de taskuri.
Apelul:
UpdateWindow (hwnd);
determin redesenarea zonei client. Acest lucru se face prin trimiterea
ctre procedura de fereastr a unui mesaj WM_PAINT.
Ciclul de mesaje
Dup apelarea funciei UpdateWindow, fereastra devine vizibil pe ecran.
Programul trebuie s fie acum pregtit s citeasc intrrile de la mouse i de
la tastatur. Windows formeaz o coad de mesaje" pentru fiecare program
rulat concurenial. Atunci cnd apare un eveniment exterior, Windows
convertete acest eveniment ntr-un mesaj pe care l plaseaz n coada de
ateptare.
Un program preia mesajele din coada de ateptare prin executarea unei
secvene de cod numit ciclu de mesaje" (message loop"):
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam;
8

Variabila msg este o structur de tip MSG.


Funcia GetMessage apelat la nceputul ciclului de mesaje preia un
mesaj din coada de ateptare:
GetMessage (&msg, NULL, 0, 0)
Acest apel transmite sistemului de operare un pointer, numit msg, la o
structur de tip MSG. Al doilea, al treilea i al patrulea parametru au valoarea
NULL sau 0, ceea ce indic faptul c programul vrea s preia toate mesajele,
pentru toate ferestrele create de program.
Instruciunea:
TranslateMessage (&msg);
retransmite structura msg sistemului de operare, pentru convertirea unor
mesaje de la tastatur.
Instruciunea:
DispatchMessage (&msg);
ca i funcia TranslateMessage, retransmite structura msg sistemului de
operare. Windows trimite apoi mesajul ctre procedura de fereastr
corespunztoare, n vederea prelucrrii - cu alte cuvinte, Windows apeleaz
procedura de fereastr.
Procedura de fereastr
O procedur de fereastr poate avea orice nume (cu condiia ca numele
respectiv s nu existe deja). Un program pentru Windows poate conine mai
multe proceduri de fereastr. O procedur de fereastr este ntotdeauna
asociat unei clase de fereastr, nregistrat cu ajutorul funciei
RegisterClassEx. Procedura de fereastr este definit ntotdeauna astfel:
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM
wParam. LPARAM lParam)
Primul parametru este hwnd, variabila handle a ferestrei care
recepioneaz mesajul. Aceasta este aceeai variabil cu cea returnat de
funcia CreateWindow. Pentru un program care creeaz o singur fereastr
aceasta este singura variabil handle cunoscut de program. Dac programul
creeaz mai multe ferestre pe baza aceleiai clase (i deci folosete aceeai
procedur de fereastr), atunci hwnd identific fereastra care primete
mesajul.
Al doilea parametru este un numr (mai precis, un ntreg fr semn UINT - pe 32 de bii) care identific mesajul. Ultimii doi parametri
(wParam, de tipul WPARAM si lParam, de tipul LPARAM) furnizeaz mai

multe informaii despre mesaj. Acetia sunt numii parametri de mesaj".


Coninutul acestor parametri este specific fiecrui tip de mesaj.
Prelucrarea mesajelor
Fiecare mesaj recepionat de o procedur de fereastr este identificat
printr-un numr, acesta fiind parametrul iMsg al procedurii de fereastr. n
fiierele antet din Windows sunt definii identificatori, cu prefixul WM
(window message"), pentru fiecare parametru de mesaje.
n general, programatorii Windows folosesc o construcie switch sau case
ca s determine ce mesaje a primit fereastra i s stabileasc modul de
prelucrare a fiecrui mesaj. Atunci cnd prelucreaz un mesaj, procedura de
fereastr trebuie s returneze valoarea 0. Orice mesaj pe care procedura de
fereastr nu-l prelucreaz este transmis unei funcii Windows numit
DefWindowProc. Valoarea returnat de funcia DefWindowProc trebuie s fie
returnat i de procedura de fereastr.
Mai jos sunt descrise dou mesaje cele mai des ntlnite n programele
scrise pentru Windows.
Mesajul WM_PAINT
Unul din mesaje prelucrat de funcia WndProc este WM_PAINT. Acest
mesaj este foarte important n programarea n Windows, deoarece informeaz
fereastra privind faptul c o parte sau ntreaga zon client a acesteia este
invalid" i trebuie s fie redesenat.
Cum poate s devin invalid o zon client? Atunci cnd fereastra este
creat, ntreaga zon client a ferestrei este invalid, deoarece programul nu a
desenat nc nimic n fereastr. Primul mesaj WM_PAINT (care apare, n
mod normal, atunci cnd programul apeleaz funcia UpdateWindow din
WinMain) cere procedurii de fereastr s deseneze ceva n zona client.
Zona client devine invalid i atunci cnd redimensionai fereastra creat
de program. V amintii c parametrul de stil al structurii wndclass conine
identificatorii CS_VREDRAW i CS_HREDRAW. Aceti identificatori
determin sistemul de operare Windows s invalideze ntreaga fereastr
atunci cnd aceasta i schimb dimensiunea i apoi s trimit un mesaj
WM_PAINT ctre procedura de fereastr.
Dac micorai la o pictogram fereastra programului i apoi i refacei
dimensiunea iniial, Windows nu salveaz coninutul zonei client. ntr-un
mediu grafic ar fi mult prea multe date de salvat. De aceea Windows

10

invalideaz fereastra. Procedura de fereastr primete mesajul WM_PAINT i


reface coninutul acesteia.
Atunci cnd mutai ferestrele astfel nct s se suprapun. Windows nu
salveaz poriunea unei ferestre care a fost acoperit de o alt fereastr. n
schimb, atunci cnd fereastra respectiv este readus la suprafa, poriunea
anterior acoperit este invalidat. Procedura de fereastr primete un mesaj
WM_PAINT pentru redesenarea poriunii respective.
De fiecare dat cnd zona client devine invalid (aa cum se ntmpl
atunci cnd modificai dimensiunea ferestrei), funcia WndProc
recepioneaz un mesaj WM_PAINT. WndProc obine noua dimensiune a
ferestrei i afieaz din nou textul n centrul acesteia.
Mesajul WM_DESTROY
Un alt mesaj important este WM_DESTROY. Acest mesaj indic faptul
c sistemul de operare desfoar un proces de distrugere a ferestrei pe baza
unei comenzi de la utilizator. Mesajul este trimis atunci cnd utilizatorul
execut clic pe butonul Close, selecteaz opiunea Close din meniul sistem
sau apas fastele Alt+F4.
Programul rspunde la acest mesaj printr-o metod standard, apelnd
funcia PostQuitMessage:
PostQuitMessage (0) ;
Aceast funcie insereaz n coada de ateptare a programului un mesaj
WM_QUIT. Am spus anterior c funcia GetMessage returneaz o valoare
diferit de zero n cazul prelurii oricrui mesaj n afar de WM_QUIT.
Atunci cnd preia din coada de ateptare un mesaj WM_QUIT, funcia
GetMessage returneaz valoarea 0, ceea ce determin ieirea din ciclul de
tratare a mesajelor din funcia WinMain i nchiderea programului.
Sarcina lucrrii: Creai o aplicaie Windows, n centrul zonei client al creia
este afiat un mesaj Lucrarea de laborator a studentului .... La
redimensionarea ferestrei, mesajul trebuie sa fie afiat n centrul zonei client.
ntrebri de control:
1. Care este sarcina principal a procedurii de fereastr?
2. Pe baza la ce se creeaz o fereastr?
3. Descriei cmpurile clasei de fereastr.
4. Ce este o variabil handle?

11

5. Ce se ntmpl cu mesajele nedescrise n procedura de fereastr, dar


plasate n coada de mesaje?
6. Descriei funciile utilizate n program.

12

LUCRAREA DE LABORATOR NR. 2


TEMA: Interfaa GDI
Scopul lucrrii: de a studia primitivele oferite de interfaa GDI
Noiuni teoretice
Interfaa pentru dispozitive grafice (GDI - Graphics Device
Interface) este o component a sistemului de operare Windows i
are ca sarcin afiarea elementelor grafice (inclusiv a textului) pe
ecran i la imprimant.
De asemenea, trebuie s tii c interfa Windows GDI i are
limitele ei. Cel puin n acest moment, interfa GDI nu poate s
fac tot ce v-ai putea dori de la o interfa grafic. Dei putei s
mutai pe ecran obiecte grafice, GDI este, n general, un sistem de
afiare static, ce permite numai animaii limitate. Aa cum este
implementat n Windows 95, interfa GDI nu asigur un suport
direct pentru afiarea tridimensional sau pentru rotirea obiectelor.
De exemplu, atunci cnd desenai o elips, axele acesteia trebuie
s fie paralele cu axele sistemului de coordonate. Dei unele
limbaje grafice folosesc numere n virgul mobil pentru
coordonatele virtuale. Windows 95 - din motive legate de
performan - folosete numai numere ntregi pe 16 bii aceasta
este una dintre deficienele sistemului de operare Windows 95.
Windows NT permite folosirea coordonatelor pe 32 de bii.
Din punctul de vedere al programatorului, interfaa GDI este
format din cteva sute de apeluri de funcii i unele tipuri de date,
macroinstruciuni i structuri asociate acestor funcii, nainte de a
studia n detaliu cteva dintre aceste funcii, haidei s vedem care
este structura general a interfeei GDI.
Tipuri de apeluri de funcii
n general, apelurile de funcii GDI pot fi clasificate n mai
multe categorii. Chiar dac nu sunt foarte stricte i exist unele
suprapuneri, aceste categorii pot fi enunate astfel:
13

Funcii care obin (sau creeaz) i elibereaz (sau distrug) un


context de dispozitiv.
Funcii care obin informaii despre contextul de dispozitiv.
Funcii care deseneaz ceva.
Funcii care stabilesc sau obin atribute ale contextului de
dispozitiv.
Funcii care lucreaz cu obiecte GDI.
Elementele grafice pe care le afiai pe ecran sau le tiprii la
imprimant pot fi mprite n mai multe categorii, numite
primitive". Iat care sunt aceste categorii:
Linii i curbe. Liniile reprezint baza oricrui sistem de
desenare vectorial. GDI permite folosirea liniilor drepte, a
dreptunghiurilor, a elipselor (inclusiv subsetul de elipse
cunoscute sub numele de cercuri), a arcelor - care sunt curbe
reprezentnd poriuni din circumferina unei elipse sau a
curbelor Bezier. Liniile sunt desenate folosind penia curent
selectat n contextul de dispozitiv.
Suprafee pline. Dac o serie de linii sau de curbe nchid o
suprafa, aceasta poate fi umplut" folosind pensula GDI
curent. Aceast pensul poate fi o culoare compact, un
model (hauri orizontale, verticale sau pe diagonal) sau o
imagine bitmap repetat pe vertical sau pe orizontal.
Imagini bitmap. Imaginile bitmap sunt matrice dreptunghiulare
de bii, care corespund pixelilor unui dispozitiv de afiare. n
general, acestea sunt folosite pentru afiarea imaginilor
complexe (deseori preluate din lumea real) pe ecran sau
pentru tiprirea acestora la imprimant. De asemenea,
imaginile bitmap sunt folosite pentru afiarea unor mici
imagini (cum ar fi pictograme, indicatoare de mouse i
butoane de pe barele cu instrumente de lucru ale aplicaiilor)
care trebuie afiate foarte rapid.
Text. Textul este mai puin matematic" dect alte aspecte ale
graficii pe calculator. Structurile create pentru definirea
fonturilor i pentru obinerea informaiilor despre fonturi sunt
printre cele mai mari din Windows. ncepnd cu versiunea
Windows 3.1, interfaa GDI accept fonturile TrueType, bazate
14

pe contururi umplute, care pot fi manipulate de alte funcii


GDI. Windows 95 accept n continuare i fonturile mai vechi,
de tip bitmap (cum este fontul sistem prestabilit) pentru
compatibilitate i pentru economisirea spaiului de memorie.
Alte aspecte ale interfeei GDI nu sunt la fel de uor de
clasificat. Printre acestea se numr:
Moduri de mapare i transformri. Modurile de mapare GDI
v permit s desenai folosind ca unitate de msur inci (sau
fraciuni de inci), milimetri sau orice alt unitate de msur.
De asemenea. Windows 95 asigur suportul pentru o
transformare real" exprimat printr-o matrice 3x3. Aceast
transformare permite deformarea i rotirea obiectelor grafice.
Din pcate, aceast transformare nu este acceptat sub
Windows 95.
Metafiiere (metafiles). Un metafiier este o colecie de
comenzi GDI stocate ntr-o form binar. Metafiierele sunt
folosite pentru transferarea reprezentrilor unor elemente
grafice vectoriale prin intermediul memoriei temporare
(clipboard).
Regiuni (regions). O regiune este o suprafa complex de
orice form, definit ca o combinaie boolean de regiuni mai
simple. n general, regiunile sunt stocate intern de GDI ca o
serie de linii de scanare, diferite de combinaia de linii folosit
iniial pentru definirea regiunii. Putei s folosii regiunile
pentru contururi, pentru umplere sau pentru decupare.
Ci (paths). O cale este o colecie de linii drepte i curbe
stocate intern de GDI. Cile pot fi folosite pentru desenare,
pentru umplere sau pentru decupare. De asemenea, cile pot fi
transformate n regiuni.
Decupare (clipping). Desenarea poate fi limitat la o anumit
seciune a zonei client, numit zon de decupare, care poate fi
dreptunghiular sau poate avea o alt form, definit printr-o
serie de linii. Zona de decupare este definit, n general, de o
cale sau de o regiune.
Palete (palettes). Folosirea paletelor proprii este limitat, n
general, numai la monitoarele care pot reda 256 de culori.
15

Windows rezerv 20 dintre aceste culori pentru sistemul de


operare. Celelalte 236 de culori pot fi modificate pentru
afiarea corespunztoare a imaginilor din lumea real, stocate
ca imagini bitmap.
Tiprire (printing). Dei discuiile din acest capitol sunt
limitate doar la afiarea pe ecran, tot ceea ce nvai n acest
capitol poate fi aplicat i operaiilor de tiprire. (Vezi Capitolul
15 pentru alte informaii despre tiprire.)

Contextul de dispozitiv
Atunci cnd vrei s desenai la un dispozitiv de ieire grafic
(cum ar fi ecranul sau imprimanta) trebuie s obinei mai nti o
variabil handle a contextului de dispozitiv (DC - device context).
Variabila handle este apoi inclus ca parametru n apelul unei
funcii GDI, identificnd dispozitivul Ia care vrei s desenai.
Contextul de dispozitiv conine mai multe atribute curente, care
specific modul de lucru al funciilor GDI pentru dispozitivul
respectiv. Aceste atribute permit ca la apelarea funciilor GDI s
fie specificate numai coordonatele de nceput sau dimensiunea, nu
i toate celelalte informaii de care sistemul de operare are nevoie
pentru desenarea obiectelor pe dispozitivul folosit. Atunci cnd
dorii s modificai unul dintre aceste atribute ale contextului de
dispozitiv, apelai o funcie specializat.
Obinerea variabilei handle a contextului de dispozitiv
Sistemul de operare Windows v pune la dispoziie mai multe
metode pentru obinerea variabilei handle a contextului de
dispozitiv. Dac obinei o variabil handle a contextului de
dispozitiv n timpul prelucrrii unui mesaj, ar trebui s tergei
aceast variabil nainte de ieirea din procedura de fereastr.
Dup ce este tears, variabila handle nu mai poate fi folosit (nu
mai este valid).
Cea mai cunoscut metod de obinere i de tergere a
variabilei handle a contextului de dispozitiv implic folosirea
funciilor BeginPaint i EndPaint n timpul prelucrrii mesajului
WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
16

[alte linii de program]


EndPaint (hwnd, &ps);
Variabila ps este o structur de tip PAINTSTRUCT. Cmpul
hdc al acestei structuri conine variabila handle a contextului de
dispozitiv. Folosind variabila handle a contextului de dispozitiv,
obinut prin apelarea funciei BeginPaint, nu putei s desenai
dect n regiunea invalid a ferestrei. Funcia BeginPaint valideaz
regiunea invalid.
Programele Windows pot s obin variabila handle a
contextului de dispozitiv i n timpul prelucrrii altor mesaje dect
WM_PAINT:
hdc = GetDC (hwnd);
(alte linii de program]
ReleaseDC (hwnd, hdc);
Acest context de dispozitiv se aplic zonei client a ferestrei
care are variabila handle hwnd. Principala diferen ntre apelul de
mai sus i metoda folosirii funciilor BeginPaint i EndPaint este
c variabila handle returnat de funcia GetDC v permite s
desenai n toat zona client a ferestrei. n plus, funciile GetDC i
ReleaseDC nu valideaz eventualele regiuni invalide ale zonei
client.
Un program Windows poate s obin i o variabil handle a
unui context de dispozitiv care se aplic ntregii ferestre, nu numai
zonei client a ferestrei:
hdc = GetWindowDC (hwnd);
[alte linii de program]
ReleaseDC (hwnd, hdc);
[alte linii de program]
DeleteDC (hdc);
Obinerea informaiilor despre culori
Funcia GetDeviceCaps v permite s determinai modul de
organizare a memoriei n adaptoarele video i numrul de culori
care pot fi reprezentate. Apelul de mai jos returneaz numrul de
planuri de culoare:
iPlanes = GetDeviceCaps (hdc, PLANES);
17

Apelul urmtor returneaz numrul de bii de culoare folosii


pentru fiecare pixel:
iBitsPixel = GetDeviceCaps (hdc, BITSPIXEL);
Majoritatea adaptoarelor video care pot afia culori folosesc
fie mai multe planuri de culoare, fie mai muli bii de culoare
pentru fiecare pixel, dar nu pe amndou; cu alte cuvinte, unul
dintre cele dou apeluri de mai sus va returna valoarea 1. Numrul
de culori care pot fi redate de o plac video se poate calcula cu
formula urmtoare:
iColors = 1<<(iPlanes * iBitsPixel);
Aceast valoare poate s nu fie identic cu numrul de culori
obinut prin apelarea funciei GetDeviceCaps cu parametrul
NUMCOLORS:
iColors = GetDeviceCaps (hdc, NUMCOLORS);
Windows folosete pentru reprezentarea culorilor o valoare
ntreag fr semn, pe 32 de bii. Tipul de date folosit pentru culori
se numete COLORREF. Ultimii trei octei ai numrului (cei mai
puin semnificativi) specific valorile pentru culorile rou, verde i
albastru, de la O la 255, aa cum se poate vedea n Figura 4-3.
Rezult o palet potenial de 224 culori (aproximativ 16 milioane
de culori).

Valoarea pe 32 de bii de mai sus e numit deseori culoare


RGB". n fisierele antet din Windows sunt definite mai multe
macroinstruciuni
pentru
lucrul
cu
valorile
RGB.
Macroinstructiunea RGB accept trei argumente, care reprezint
valorile pentru culorile rou, verde i albastru i le combin ntr-o
valoarea ntreag pe 32 de bii, fr semn.
Astfel, valoarea
RGB (255, 0, 255)
este de fapt 0x00FF00FF, valoarea RGB pentru magenta. Dac
toate cele trei argumente au valoarea 0, se obine negrul, iar dac
au valoarea 255, se obine albul. Macroinstruciunile GetRValue,
GetGValue i GetBValue extrag valorile pentru culorile primare,
sub forma unor octei fr semn, din valoarea RGB a culorii.
18

Aceste macroinstructiuni sunt utile atunci cnd apelai funcii


Windows care returneaz culori RGB.
Salvarea contextului de dispozitiv
n mod normal, Windows creeaz un nou context de dispozitiv
cu valori prestabilite atunci cnd apelai una dintre funciile
GetDC sau BeginPaint. Toate modificrile fcute n atributele
contextului de dispozitiv se pierd atunci cnd contextul de
dispozitiv este ters din memorie prin apelarea funciei ReleaseDC
sau a funciei EndPaint. Dac programul trebuie s foloseasc un
atribut cu o valoarea diferit de cea prestabilit va trebui s
iniializai contextul de dispozitiv de fiecare dat cnd obinei o
variabil handle:
caseWM_Paint:
hdc = BeginPaint (hwnd, &ps);
[iniializeaz atributele contextului de dispozitiv]
[deseneaz zona client a ferestrei]
EndPaint (hwnd, &ps);
return 0;
Dei aceast abordare este n general satisfctoare, s-ar putea
s preferai s salvai modificrile fcute asupra contextului de
dispozitiv ia distrugerea acestuia, astfel nct valorile salvate s
redevin active la apelarea funciilor GetDC sau BeginPaint.
Desenarea liniilor
Interfaa Windows GDI conine i funciile SetPixel i
GetPixel. Dei vom folosi funcia SetPixel n programul
CONNECT din Capitolul 7, n programele de grafic propriu-zis
aceste funcii sunt rareori folosite. n majoritatea cazurilor, cea mai
simpl primitiv grafic vectorial trebuie s fie considerat linia.
Windows poate s deseneze linii drepte, linii eliptice (linii
curbe, pe circumferina unei elipse) i curbe Bezier. Cele apte
funcii acceptate de Windows 95 pentru desenarea liniilor sunt
LineTo (linii drepte), Polyline i PolylineTo (o serie de linii drepte
conectate), PolyPolyline (mai multe linii poligonale), Arc (linii
eliptice), PolyBezier i PolyBezierTo. (Interfaa GDI din Windows
NT accept nc trei funcii pentru desenarea liniilor: ArcTo,
19

AngleArc i PolyDraw. Aceste funcii nu sunt ns acceptate n


Windows 95.) Aspectul liniilor desenate cu aceste funcii poate fi
influenat de cinci atribute ale contextului de dispozitiv: poziia
curent a peniei (numai pentru funciile LineTo, PolylineTo i
PolyBezierTo), penia selectat, modul de afiare a fondului
(numai pentru peniele care nu deseneaz cu o culoare compact),
culoarea fondului (pentru modul OPAQUE de afiare a fondului)
i modul de desenare.
Funcia LineTo este una dintre puinele funcii GDI care nu are
nevoie de dimensiunile complete ale obiectului ce urmeaz s fie
desenat. Funcia LineTo deseneaz o linie de la poziia curent"
definit n contextul de dispozitiv pan la punctul specificat la
apelarea funciei (exclusiv acest punct). Poziia curent este
folosit ca punct de plecare i de alte funcii GDI. n contextul de
dispozitiv prestabilit, poziia curent are iniial valoarea (0,0).
Dac apelai funcia LineTo fr s stabilii mai nti poziia
curent, funcia deseneaz o linie pornind din colul din stnga-sus
al zonei client.
Dac dorii s desenai o linie din punctul (xStart, yStart) pan
n punctul (xEnd, yEnd) trebuie s apelai mai nti funcia
MoveToEx ca s stabilii ca poziie curent punctul (xStart, ySfart):
MoveToEx (hdc, xStart, yStart, &pt) ;
unde pt este o structur de tip POINT, definit n fiierele antet.
Funcia MoveToEx nu deseneaz nimic, ci doar schimb
poziia curent. Poziia curent anterioar este stocat n structura
de tip POINT. Putei apoi s folosii funcia LineTo ca s desenai
linia:
LineTo (hdc, xEnd, yEnd);
Apelul de mai sus deseneaz o linie pn n punctul (xEnd,
yEnd), exclusiv acest punct. Dup apelul funciei LineTo, poziia
curent devine (xEnd, yEnd).
Putei s obinei poziia curent a peniei apelnd funcia
GetCurrentPosition astfel:
GetCurrentPositionEx (hdc, &pt) ;
Atunci cnd avei o matrice de puncte pe care vrei s le
conectai prin linii, putei s desenai mai uor liniile folosind
20

funcia Polyline. Instruciunea de mai jos deseneaz acelai


dreptunghi ca i secvena de cod din exemplul anterior:
Polyline (hdc, pt, 5);
Ultimul parametru reprezint numrul de puncte. Aceast
valoare putea fi reprezentat i prin expresia (sizeof(pt) /
sizeof(POINT)). Funcia Polyline are acelai efect ca i o funcie
MoveToEx urmat de mai multe funcii LineTo, exceptnd faptul
c funcia Polyline nu schimb poziia curent. Funcia PolylineTo
este puin diferit. Aceasta folosete ca punct de plecare poziia
curent i stabilete ca poziie curent sfritul ultimei linii
desenate. Codul de mai jos deseneaz acelai dreptunghi folosit ca
exemplu i mai sus:
MoveToEx (hdc, pt[0].x, pt[0].y, NULL) ;
PolylineTo (hdc, pt + 1,4) ;
Dei putei s folosii funciile Polyline i PolylineTo i pentru un
numr mic de funcii, acestea sunt mai utile atunci cnd desenai o
curb complex format din sute sau chiar mii de linii.
n continuare a vrea s discutm despre funcia Arc, funcie
care deseneaz o curb eliptic. Dar funcia Arc nu prea are sens
dac nu discutm mai nti despre funcia Ellipse, care, la rndul
ei, nu are sens fr o discuie despre funcia Rectangle. Si dac
discutm despre funciile Rectangle i Ellipse, putem la fel de bine
s discutm i despre funciile RoundRect, Chord i Pie.
Problema este c funciile Rectangle, Ellipse, RoundRect,
Chord i Pie nu sunt tocmai nite funcii de desenare a liniilor.
Desigur, ele deseneaz i linii, dar i coloreaz zona nchis, cu
pensula curent de colorare a suprafeelor. n mod prestabilit,
aceast pensul are culoarea alb, aa c s-ar putea ca operaia s
nu fie att de evident atunci cnd ncercai pentru prima dat s
utilizai aceste funcii. Dei, n sens strict, funciile aparin unei
alte seciuni din capitolul de fa, Desenarea suprafeelor pline",
vom discuta acum despre fiecare.
Funciile de mai sus sunt asemntoare prin faptul c sunt
construite pe baza unui dreptunghi de ncadrare" (bounding
box"). Dumneavoastr definii o caset care ncadreaz obiectul dreptunghiul de ncadrare - i Windows deseneaz obiectul n
acest dreptunghi.
21

Cea mai simpl dintre aceste funcii deseneaz un dreptunghi:


Rectangle (hdc, xLeft, yTop, xRight, yBottom) ;
Punctu cu coordonatele (xLeft, yTop) este punctul din stnga
sus, iar punctul cu coordonatele (xRight, yBottom) este punctul din
dreapta jos.
Dup ce ai aflat cum se deseneaz un dreptunghi, folosind
aceiai parametri, vei putea, la fel de simplu, s desenai i o
elips:
Ellipse (hdc, xLeft, yTop, xRight, yBottom) ;
Funcia pentru desenarea unui dreptunghi cu colurile rotunjite
folosete acelai dreptunghi de ncadrare ca i funciile Rectangle
i Ellipse, dar are nc doi parametri:
RoundRect (hdc, xLeft, yTop, xRight, yBottom,
xCornerEllipse, yCornerEllipse);
Pentru desenarea colurilor rotunjite, Windows folosete o
mic elips. Limea elipsei este xCornerEllipse iar nlimea
acesteia este yCornerEllipse. Colurile dreptunghiului sunt cu att
mai rotunjite cu ct valorile parametrilor xCornerEllipse i
yCornerEllipse sunt mai mari. Dac xCornerEllipse este egal cu
jumtate din diferena dintre xLeft i xRight iar yCornerEllipse
este egal cu jumtate din diferena dintre yTop i yBottom, atunci
funcia RoundRect va desena o elips.
Funciile Arc, Chord i Pie primesc aceiai parametri:
Arc (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd,
yEnd);
Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd,
yEnd);
Pie (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd,
yEnd);
n cazul funciei Arc, Windows i-a terminat treaba, deoarece
arcul este o linie eliptic, nu o suprafa plin. n cazul funciei
Chord, Windows unete capetele arcului, iar n cazul funciei Pie,
unete capetele arcului cu centrul elipsei. Interioarele suprafeelor
nchise obinute astfel sunt colorate cu pensula curent.
Folosirea penielor de stoc
22

Atunci cnd apelai oricare dintre funciile de desenare a


liniilor, Windows folosete pentru desenarea liniilor penia" (pen)
curent selectat n contextul de dispozitiv. Penia selectat
determin culoarea, limea i tipul de linie (acestea pot fi
continue, punctate sau ntrerupte). Penia din contextul prestabilit
de dispozitiv se numete BLACK_PEN. Aceasta deseneaz o linie
compact, de culoare neagr, cu grosimea de un pixel, indiferent
de modul de mapare. BLACK_PEN este una dintre cele trei penie
de stoc" (stock pen) furnizate de Windows. Celelalte dou penie
de stoc sunt WHITE_PEN i NULL_PEN. NULL_PEN este o
peni care nu deseneaz nimic. n plus, putei s creai penie
proprii.
Penie sunt determinate de propriile variabile handle. n
fiierele antet din Windows este definit tipul de date HPEN, care
reprezint o variabil handle a unei penie. Putei s definii o
variabil (de exemplu, hPen) folosind aceast definiie de tip:
HPEN hPen ;
Putei s obinei variabila handle a uneia dintre peniele de
stoc apelnd funcia GetStockObject. De exemplu, s presupunem
c vrei s folosii penia de stoc numit WHITE_PEN. Obinei
variabila handle a acesteia astfel:
hPen = GetStockObject (WHITE_PEN);
Apoi trebuie s selectai n contextul de dispozitiv penia a
crei variabil ai obinut-o, apelnd funcia SelectObject:
SelectObject (hdc, hPen) ;
Dup acest apel toate liniile pe care le desenai vor folosi
penia WHITE_PEN, pn cnd selectai o alt peni n contextul
de dispozitiv sau tergei contextul de dispozitiv.
n loc s definii explicit variabila hPen, putei s combinai
funciile GetStockObject i SelectObject ntr-o singur
instruciune:
SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
Dac apoi vrei s revenii la penia BLACK_PEN, putei s
obinei o variabil handle a acesteia i s o selectai n contextul
de dispozitiv tot cu o singur instruciune:
SelectObject (hdc, GetStockObject (WHITE_PEN));
23

Funcia SelectObject returneaz variabila handle a peniei


selectate anterior n contextul de dispozitiv. Dac deschidei un
nou context de dispozitiv i executai instruciunea:
hPen
=
SelectObject
(hdc,
GetStockObject
(WHITE_PEN)) ;
atunci penia curent selectat n contextul de dispozitiv va fi
WHITE_PEN i hPen va fi variabila handle a peniei
BLACK_PEN. Putei apoi s selectai penia BLACK_PEN n
contextul de dispozitiv cu urmtoarea instruciune:
SelectObject (hdc, hPen) ;
Pentru a crea o peni proprie apelai funcia:
hPen = CreatePen (iPenStyle, iWidth, rgbColor) ;
Parametrul iPenStyle precizeaz dac se deseneaz o linie
continu, o linie punctat sau una ntrerupt. Parametrul iPenStyle
poate fi unul dintre identificatorii definii n fiierele antet din
Windows.
Parametrul rgbColor din funcia CreatePen este un numr
ntreg fr semn reprezentnd culoarea peniei. Pentru toate
stilurile de penie, exceptnd PS_INSIDEFRAME, atunci cnd
selectai penia n contextul de dispozitiv, Windows convertete
acest parametru la cea mai apropiat culoare pur pe care o poate
reprezenta dispozitivul de afiare. PS_INSIDEFRAME este
singurul stil care poate folosi culori amestecate, dar numai pentru
grosimi mai mari de un pixel.
Desenarea suprafeelor pline
Cele apte funcii Windows pentru desenarea figurilor sunt
prezentate n tabelul urmtor:
Funcia
Rectangle
Ellipse
RoundRect
Chord
Pie

Figura
Dreptunghi cu coluri drepte
Elips
Dreptunghi cu coluri rotunjite
Arc pe circumferina unei elipse, avnd
capetele unite printr-o coard
Suprafa de forma unei felii de plcint,
reprezentnd un segment de elips.
24

Polygon
PolyPolygon

Figur geometric avnd mai multe laturi


Mai multe figuri geometrice cu mai
multe laturi
Windows deseneaz conturul figurilor folosind penia curent
selectat n contextul de dispozitiv. Pentru acest contur sunt
folosite atributele stabilite pentru modul de desenare a fondului,
culoarea fondului i modul de desenare, ca i n cazul desenrii
unei linii simple. Tot ceea ce ai nvat despre linii se aplic i n
cazul contururilor.
Figurile sunt umplute folosind pensula selectat n contextul
de dispozitiv. n mod prestabilit, aceasta este pensula de stoc
WHITE_BRUSH, ceea ce nseamn c interiorul figurilor va fi
umplut cu alb. Windows definete ase pensule de stoc: WHITE_BRUSH,
LTGRAY_BRUSH,
GRAY_BRUSH,
DKGRAY_BRUSH, BLACK_BRUSH i NULL_BRUSH (sau
HOLLOW_BRUSH).
Putei s selectai una dintre aceste pensule n contextul de
dispozitiv la fel cum selectai o peni de stoc. Windows definete
tipul HBRUSH ca variabil handle a unei pensule, aa c putei s
definii mai nti o variabil de acest tip:
HBRUSH hBrush ;
Putei s obinei variabila handle a pensulei de stoc
GRAY_BRUSH apelnd funcia GetStockObject:.
hBrush = Get&toCkObject (GBAY_BRUSH) ;
Putei s o selectai apoi n contextul de dispozitiv folosind
funcia SelectObject:
SelectObject (hdc, hBrush) ;
Din acest moment, figurile desenate vor avea interiorul gri.
Dac vrei s desenai o figur fr contur, selectai n
contextul de dispozitiv penia NULL_PEN:
SelectObject (hdc, GetStockObject (NULL_PEN)) ;
Dac vrei s desenai o figur fr s i umplei interiorul,
selectai n contextul de dispozitiv pensula NULL_BRUSH:
SelectObject (hdc, GetStockObject (NULL_BRUSH)) ;
Aa cum putei s creai penie proprii, putei s creai i
pensule proprii.
25

Sistemele de coordonate ale dispozitivului


Windows mapeaz coordonatele logice specificate n funciile
GDI la coordonatele dispozitivului. nainte de a discuta despre
sistemele de coordonate logice folosite de diferitele moduri de
mapare, vom discuta despre diferitele sisteme de coordonate de
dispozitiv definite n Windows pentru zona de afiare. Dei n
general am lucrat doar n zona client a ferestrei, n anumite situaii
Windows folosete alte dou sisteme de coordonate de dispozitiv.
n toate sistemele de coordonate de dispozitiv sunt folosii pixelii
ca unitate de msur. Valorile de pe axa orizontal (x) cresc de la
stnga la dreapta iar valorile de pe axa vertical (y) cresc de sus n
jos.
Atunci cnd folosim ntregul ecran, spunem c lucrm n
coordonate ecran". Colul din stnga-sus este punctul de
coordonate (0, 0). Coordonatele ecran sunt folosite n mesajul
WM_MOVE (pentru alte ferestre dect ferestrele descendent) i n
urmtoarele funcii Windows: CreateWinriow i MoveWindow
(ambele pentru alte ferestre dect ferestrele descendent),
GetMessagePos, GetCursorPos, SetCursorPos, GetWindowRect,
WindowFromPoint i SetBrushOrgEx. Acestea sunt funcii care fie
nu au o fereastr asociat (cum ar fi cele dou funcii pentru
cursor), fie trebuie s mute (sau s gseasc) o fereastr pe baza
unui punct de pe ecran. Dac folosii funcia CreateDC cu
parametrul DISPLAY ca s obinei un context de dispozitiv
pentru ntregul ecran, atunci coordonatele logice specificate la
apelarea funciilor GDI vor fi mapate la coordonatele ecranului.
Coordonatele de fereastr" se refer la ntreaga fereastr a
ecranului, inclusiv bara de titlu, meniu, barele de derulare i
chenarul ferestrei. Pentru o fereastr normal, punctul (0, 0) este
colul din stnga-sus al chenarului de redimensionare.
Coordonatele de fereastr sunt folosite mai rar n Windows, dar
dac obinei un context de dispozitiv cu ajutorul funciei
GetWindowDC, atunci coordonatele logice specificate la apelarea
funciilor GDI vor fi mapate la coordonatele ferestrei.
Al treilea sistem de coordonate de dispozitiv - cu care vom
lucra cel mai des -folosete coordonatele zonei client". Punctul
(0,0) este colul din stnga-sus al zonei client. Dac obinei un
26

context de dispozitiv cu ajutorul funciei GetDC sau al funciei


BeginPaint, atunci coordonatele logice specificate Ia apelarea
funciilor GDI vor fi mapate la coordonatele zonei client.
Putei s transformai coordonatele zonei client n coordonatele
ecranului i invers folosind funciile ClientToScreen i
ScreenToClient. De asemenea, putei obinei poziia i
dimensiunea ntregii ferestre n coordonate ecran folosind funcia
GetWindowRect.
Sarcina lucrrii: Scriei un program care afieaz n zona client
un desen animat, utiliznd toate primitivele GDI.
ntrebri de control:
1. Descriei principalele primitive ale interfeei grafice.
2. Enumerai metodele de obinere a variabilei handle a
dispozitivului de context.
3. Ce sisteme de coordonate ale dispozitivului de context
cunoatei?

27

LUCRARE DE LABORATOR NR. 3


Tema: Curbe Bezier
Scopul lucrrii: De a studia primitivele grafice ce permit afiarea
curbelor Bezier i afiarea acestor curbe cu ajutorul formulelor.
Noiuni teoretice
Termenul spline" se referea odat la o rigl flexibil din lemn,
metal sau cauciuc (florar), folosit pentru desenarea curbelor. De
exemplu, dac aveai un numr de puncte aparinnd unui grafic i
doreai s desenai o curb ntre acestea (prin interpolare sau
extrapolare) trebuia s marcai mai nti punctele pe hrtie.
Ancornd apoi rigla n punctele respective, nu v rmnea dect s
trasai curba de-a lungul riglei. n prezent, spline" se refer la o
funcie matematic. Aceste funcii au diferite forme. Curbele
Bezier sunt unele dintre cele mai cunoscute pentru programarea
grafic. n anii '60, compania de automobile Renault trecea de la
proiectarea manual a caroseriilor (care implica folosirea argilei)
la o proiectare asistat de calculator. Erau necesare instrumente
matematice, iar Pierre Bezier a pus la punct un set de formule care
s-au dovedit foarte utile pentru rezolvarea acestei probleme.
De atunci, datorit formei bidimensionale, curba Bezier s-a
dovedit a fi cea mai util curb pentru grafica pe calculator. De
exemplu, n limbajul PostScript funciile Bezier sunt folosite
pentru toate curbele - elipsele sunt aproximare prin curbe Bezier
De asemenea, funciile Bezier sunt folosite pentru definirea
contururilor caracterelor din fonturile PostScript. (Fonturile
TrueType folosesc o form simplificat, mai rapida, a curbelor.)
O curb Bezier este definit prin patru puncte - dou capete i
dou puncte de control. Capetele curbei sunt ancorate n cele dou
puncte finale. Punctele de control acioneaz ca nite magnei"
care deformeaz linia dreapt dintre cele dou puncte finale.
Funciile Bezier sunt considerate utile pentru proiectarea
asistat de calculator, datorit ctorva caracteristici:
28

n primul rnd, cu puin practic, de obicei putei s


manipulai curba pn ajunge la o form apropiat de cea
dorit.
n al doilea rnd, curbele Bezier sunt foarte uor de controlat.
n unele variante ale funciilor spline, curba nu trece prin nici
unul din punctele care o definesc. Curbele Bezier, ns, sunt
ntotdeauna ancorate n cele dou puncte finale. (Aceasta este
una dintre ipotezele de la care pornete calculul formulei
Bezier.) De asemenea, unele forme ale funciilor spline au
puncte de singularitate, din care curba se ntinde la infinit. n
proiectarea asistat de calculator acest lucru este de cele mai
multe ori evitat. Ca urmare, curbele Bezier sunt ntotdeauna
limitate de un patrulater (numit carcas convex" - convex
hull") format prin unirea punctelor finale i a punctelor de
control.
n al treilea rnd, o alt caracteristic a curbelor Bezier
implic relaiile dintre punctele finale i punctele de control.
Curba este ntotdeauna tangent la linia trasat de la primul
punct final la primul punct de control i are ntotdeauna
aceeai direcie cu aceast linie. (Aceast caracteristic este
ilustrat vizual de programul BEZIER.) De asemenea, curba
este ntotdeauna tangent la linia trasat de la al doilea punct
final la al doilea punct de control i are ntotdeauna aceeai
direcie cu aceast linie. (Acestea sunt alte dou ipoteze de la
care este derivat formula Bezier.)
n al patrulea rnd, curbele Bezier sunt satisfctoare i din
punct de vedere estetic. tiu c acesta este un criteriu
subiectiv, dar nu este numai prerea mea.
nainte de apariia sistemului de operare Windows 95, trebuia
s creai propriile curbe Bezier folosind funcia Polyline. De
asemenea, trebuia s cunoatei urmtoarele ecuaii parametrice
ale curbelor Bezier:
x(t) = (1-t)3x0 + 3t(1-t)2x1 + 3t2(1-t)x2 + t3x3
y(t) = (1-t)3y0 + 3t(1-t)2y1 + 3t2(1-t)y2 + t3y3
unde (x0, y0) este punctul de nceput al curbei, (x3, y3) este punctul
de sfrit al curbei, iar cele dou puncte de control sunt (x1, y1) i
(x2, y2). Curba este trasat pentru t avnd valori de la 0 la 1.
29

n Windows 95 nu mai este nevoie s tii aceste formule.


Pentru trasarea uneia sau a mai multor curbe Bezier conexe, putei
s folosii instruciunea:
PolyBezier (hdc, pt, iCount) ;

sau instruciunea:
PolyBezierTo (hide, pt, iCount) ;

n ambele cazuri, pt este o matrice de structuri POINT. Pentru


funcia PolyBezier primele patru puncte specific (n aceast
ordine) punctul de nceput, primul punct de control, al doilea
punct de control i punctul final al curbei Bezier. Urmtoarele
curbe Bezier au nevoie doar de trei puncte, deoarece punctul de
nceput al urmtoarei curbe Bezier este punctul de sfrit al primei
curbe, i aa mai departe. Parametrul iCount reprezint numrul de
puncte din matrice, adic unu plus de trei ori numrul curbelor pe
care vrei s le desenai.
Funcia PolyBezierTo folosete poziia curent ca punct de
nceput pentru prima curb Bezier. Fiecare curb desenat are
nevoie doar de trei puncte. La returnarea funciei, poziia curent
este punctul final al ultimei curbe desenate.
Atenie: atunci cnd trasai o serie de curbe Bezier conectate
ntre ele, legtura va fi lin numai dac al doilea punct de control
al primei curbe, punctul de sfrit al primei curbe (care este i
punctul de nceput al celei de-a doua curbe) i primul punct de
control al celei de-a doua curbe sunt coliniare, adic se afl pe
aceeai linie dreapt.
Sarcina lucrrii: Scriei un programi care afiaz curba Bezier,
utiliznd funciile GDI standarde i o curb Bezier, afiat dup
calcule prin formule.
ngrebri de control:
1. Pentru ce se utilizeaz curbele Bezier?
2. Cte puncte sunt necesare pentru a afia o curb Bezier?
3. Care sunt metodele de afiare a curbelor Bezier?
4. Care sunt caracteristicile curbelor Bezier?

30

LUCRAREA DE LABORATOR NR. 4


TEMA: Principiile de lucru cu tastatura
Scopul lucrrii: de a studia metodele i principiile de lucru cu
tastatura. nsuirea modului de prelucrare a mesajelor parvenite de
la tastatura.
Noiuni teoretice
Arhitectura bazat pe mesaje a sistemului de operare Windows
este ideal pentru lucrul cu tastatur. Programul afl" despre
apsarea unor taste prin intermediul mesajelor care ajung la
procedura de fereastr.
De fapt, lucrurile sunt puin mai complicate: atunci cnd
utilizatorul apas i elibereaz tastele, driverul de tastatur
transmite sistemului de operare informaiile legate de aciunile
asupra tastelor. Windows salveaz aceste aciuni (sub form de
mesaje) n coada de ateptare a sistemului. Mesajele de la tastatur
sunt apoi transferate, unul cte unul, n coada de mesaje a
programului cruia i aparine fereastra ce deine cursorul de
intrare" (despre care vom discuta imediat). Programul distribuie
mesajele procedurii de fereastr corespunztoare.
Motivul acestui proces n dou etape - stocarea mesajelor mai
nti n coada de mesaje a sistemului i apoi transferarea acestora
n coada de mesaje a aplicaiilor - este legat de sincronizare.
Atunci cnd utilizatorul apas pe taste ntr-un ritm mai rapid dect
cel n care programul prelucreaz mesajele primite, Windows
stocheaz aciunile neprelucrate n coada de ateptare a sistemului,
deoarece una dintre aciunile asupra tastaturii poate avea ca efect
comutarea cursorului de intrare (input focus) ctre un alt program.
n consecin, urmtoarele taste trebuie transmise celui de-al
doilea program.
Dei tastatura este principala surs de intrri de la utilizatori a
unui program pentru Windows, programele nu trebuie s
reacioneze la toate mesajele pe care le primete de la tastatur.
Multe funcii ale tastaturii sunt tratate chiar de Windows. De
31

exemplu, putei s ignorai apsrile de taste legate de funcii


sistem. Acestea sunt, n general, combinaii cu tasta Alt.
Programul nu este obligat s monitorizeze aceste taste,
deoarece Windows i comunic efectul acestora. (Totui, dac este
nevoie, programul poate face i acest lucru.) De exemplu, dac
utilizatorul selecteaz un articol dintr-un meniu cu ajutorul
tastaturii. Windows trimite programului un mesaj prin care i
comunic articolul de meniu selectat, indiferent dac utilizatorul a
folosit mouse-ul sau tastatura.
Unele programe pentru Windows folosesc acceleratori" (sau
taste de accelerare") pentru opiunile de meniu folosite mai
frecvent. Acceleratorii sunt, de obicei, combinaii de taste
funcionale - sau alte taste corespunztoare unor caractere - cu
tasta Ctrl. Tastele de accelerare sunt definite n fiierul de resurse
al programului.
Tastatura trebuie s fie partajat de toate aplicaiile rulate
simultan sub Windows. Unele aplicaii pot avea mai multe
ferestre, iar tastatura trebuie s fie partajat de toate ferestrele din
cadrul aceleiai aplicaii. Atunci cnd este apsat o tast, o
singur fereastr trebuie s primeasc mesajul privind apsarea
tastei respective. Fereastra care primete acest mesaj este fereastra
care deine cursorul de intrare" (input focus").
Dac fereastra activ a fost redus la o pictogram, atunci nici
o fereastr nu deine cursorul de intrare. Windows continu s
trimit programului mesaje de la tastatur, dar acestea sunt trimise
ntr-o alt form dect mesajele trimise unei ferestre active
normale.
O procedur de fereastr poate s afle cnd are cursorul de
intrare prin interceptarea mesajelor WM_SETFOCUS i
WM_KILLFOCUS. Mesajul WM_SETFOCUS indic faptul c
fereastra primete cursorul de intrare (input focus), iar mesajul
WM_KILLFOCUS indic faptul c fereastra pierde cursorul de
intrare.
Atunci cnd apsai o tast, Windows insereaz n coada de
ateptare a ferestrei care deine cursorul de intrare un mesaj
WM_KEYDOWN sau un mesaj WM_SYSKEYDOWN. Atunci
32

cnd eliberai fasta, Windows insereaz n coada de ateptare a


ferestrei un mesaj WM_KEYUP sau un mesaj WM_SYSKEYUP.
Tast obinuit
Tast de sistem

Tasta a fost apsat


WM_KEYDOWN
WM_SYSKEYDOWN

Tasta a fost eliberat


WM_KEYUP
WM_SYSKEYUP

De obicei, mesajele de apsare i de eliberare a tastei sunt


trimise n pereche. Totui, dac inei apsat o tast pan cnd
aceasta se autorepet, Windows trimite procedurii de fereastr o
serie de mesaje WM_KEYDOWN (sau WM_SYSKEYDOWN) i
un singur mesaj WM_KEYUP sau (WM_SYSKEYUP) dup
eliberarea tastei. Ca toate mesajele trimise prin coada de ateptare,
mesajele pentru acionri de taste conin informaii de timp. Putei
s obinei momentul relativ n care a fost apsat sau eliberat o
tast apelnd funcia GetMessageTime.
Taste obinuite i taste de sistem
Particula SYS" din mesajele WM_SYSKEYDOWN i
WM_SYSKEYUP provin de la cuvntul system" i se refer la
acionrile de taste care prezint mai mult importan pentru
Windows dect pentru aplicaiile Windows. Mesajele
WM_SYSKEYDOWN i WM_SYSKEYUP sunt generate, de
obicei, pentru taste apsate n combinaie cu tasta Alt. Aceste
acionari de taste apeleaz opiuni din meniul programului ori din
meniul sistem, sunt folosite pentru funcii ale sistemului, cum ar fi
comutarea ferestrei active (Alt+Tab sau Alt+Esc) sau sunt folosite
pentru acceleratori de meniu (Alt n combinaie cu o tast
funcional).
De
obicei,
programul
ignor
mesajele
WM_SYSKEYDOWN i WM_SYSKEYUP i le retransmite
funciei DefWindowProc. Deoarece Windows manipuleaz
combinaiile Alt+tast, nu este nevoie s interceptai aceste
mesaje. Procedura de fereastr va primi alte mesaje, legate de
rezultatul acestor acionri de taste (cum ar fi selectarea unei
opiuni de meniu). Chiar dac dorii s includei n program codul
pentru interceptarea acestor mesaje (aa cum vom face n
programul KEYLOCK din acest capitol), retransmitei mesajele
33

funciei DefWindowProc dup ce le prelucrai, astfel nct


Windows s le poat folosi n scopurile obinuite.
Mesajele WM_KEYDOWN i WM_KEYUP sunt generate, de
obicei, pentru tastele apsate i eliberate fr tasta Alt. Programul
poate s foloseasc sau s ignore aceste mesaje. Sistemul de
operare le ignor.
Pentru toate mesajele legate de acionrile de taste variabila
lParam (pe 32 de bii) transmis procedurii de fereastr este
mprit n ase cmpuri: contorul de repetare, codul de scanare
OEM, indicatorul flag pentru taste extinse, codul de context, starea
anterioar a tastei i starea de tranziie.
Contorul de repetare (Repeat Count) specific numrul de
acionari de taste reprezentat de un mesaj. n majoritatea cazurilor,
contorul de repetare are valoarea 1. Totui, dac procedura de
fereastr nu reuete s prelucreze mesajele de apsare a unei taste
n ritmul de autorepetare (n mod prestabilit aproximativ 10
caractere pe secund). Windows combin mai multe mesaje
WM_KEYDOWN sau WM_SYSKEYDOWN ntr-un singur
mesaj i incrementeaz corespunztor contorul de repetare.
Contorul de repetare are ntotdeauna valoarea 1 pentru mesajele
WM_KEYUP i WM_SYSKEYUP.
Codul de scanare OEM (OEM Scan Code) este codul de
scanare al tastaturii, generat de componentele hardware. (Dac ai
scris programe n limbaj de asamblare, acest cod este identic cu
cel transmis n registrul AH, n timpul ntreruperii apelului BIOS
16H.) n general, aplicaiile Windows ignor acest cod, deoarece
exist metode mai bune de decodificare a informaiilor de la
tastatur.
Indicatorul flag pentru taste extinse (Extended Key Flag) are
valoarea 1 dac mesajul este generat de una dintre tastele
suplimentare de pe tastatura IBM extins. (Tastatura IBM extins
are tastele funcionale n partea de sus i un bloc separat sau
combinat de taste pentru tastele de deplasare i tastele numerice.)
Acest indicator are valoarea 1 pentru tastele Alt i Ctrl din partea
dreapt a tastaturii, pentru tastele de deplasare (inclusiv tastele
Insert i Delete) care nu fac parte din blocul de taste numerice,
pentru tastele Slash (/) i Enter din blocul de taste numerice i
34

pentru tasta Num Lock. n general, programele Windows ignor


acest indicator.
Codul de context (Context Code) are valoarea 1 dac este
apsat tasta Alt. Acest bit va avea ntotdeauna valoarea 1 pentru
mesajele WM_SYSKEYUP i WM_SYSKEYDOWN i valoarea
0 pentru mesajele WM_KEYUP si WM_KEYDOWN, cu dou
excepii:
1. O fereastr activ redus la o pictogram nu deine
cursorul de intrare. Toate acionrile de taste genereaz
mesaje WM_SYSKEYUP i WM_SYSKEYDOWN. Dac
tasta Alt nu este apsat, bitul pentru codul de context are
valoarea 0. (Windows folosete aceste mesaje astfel nct
fereastra activ redus la o pictogram s nu prelucreze
mesajele de la tastatur.)
2. n cazul folosirii unui driver de tastatur pentru alte limbi
dect limba englez, unele caractere sunt generate prin
combinarea tastelor Shift, Ctrl sau Alt cu alte taste. n
aceast situaie, bitul pentru codul de context din variabila
IParam care nsoete mesajele WM_KEYUP i
WM_KEYDOWN are valoarea 1, dar mesajele nu
reprezint acionri de taste de sistem.
Starea anterioar a tastei (Previous Key State) are valoarea 0
dac tasta nu a fost anterior apsat, i valoarea 1 dac tasta a fost
apsat. Are ntotdeauna valoarea 1 pentru mesajele WM_KEYUP
i WM_SYSKEYUP, dar poate fi 0 sau 1 pentru mesajele
WM_KEYDOWN i WM_SYSKEYDOWN. Valoarea 1 indic
faptul c s-a primit un mesaj generat de autorepetarea unei taste.
Starea de tranziie (Transition State) are valoarea 0 dac tasta
este apsat i valoarea 1 dac tasta este eliberat. Acest bit are
valoarea 1 pentru mesajele WM_KEYUP si WM_SYSKEYUP si
valoarea
0
pentru
mesajele
WM_KEYDOWN
i
WM_SYSKEYDOWN.
Coduri virtuale de taste
Dei unele informaii din parametrul lParam pot fi utile pentru
prelucrarea
mesajelor
WM_KEYUP,
WM_SYSKEYUP,
WM_KEYDOWN i WM_SYSKEYDOWN, parametrul wParam
35

este mult mai important. Acest parametru conine codul virtual


care identific tasta apsat sau eliberat. Codurile virtuale pe care
le vei folosi cel mai des au nume definite n fiierele antet din
Windows.
Parametrii lParam i wParam care nsoesc mesajele
WM_KEYUP,
WM_SYSKEYUP,
WM_KEYDOWN
i
WM_SYSKEYDOWN nu spun nimic programului despre starea
tastelor de modificare. Putei s obinei starea oricrei taste
virtuale folosind funcia GetKeyState. Aceast funcie este folosit,
de obicei, pentru obinerea strii tastelor de modificare (Shift, Alt
i Ctrl) i a tastelor de comutare (Caps Lock, Num Lock i Scroll
Lock). De exemplu:
GetKeyState (VK_SHIFT);

returneaz o valoare negativ (adic un numr n care primul bit


are valoarea 1) dac tasta Shift este apsat. Valoarea returnat de
apelul:
GetKeyState (VK_CAPITAL);

are un 1 n bitul cel mai puin semnificativ dac tasta Caps Lock
este activ.
Dac ntr-adevr avei nevoie de starea curent a unei taste,
putei s folosii funcia GetAsyncKeyState.
Utilizarea mesajelor de acionare a tastelor
Ideea unui program care s obin informaii despre toate
aciunile exercitate asupra tastelor este bun. Cu toate acestea,
majoritatea programelor Windows ignor cea mai mare parte a
acestor
mesaje.
Mesajele
WM_SYSKEYUP
i
WM_SYSKEYDOWN sunt folosite pentru funciile sistemului,
aa c nu este nevoie s le interceptai. De asemenea, dac
prelucrai mesajele WM_KEYDOWN, de obicei putei s ignorai
mesajele WM_KEYUP.
n general, programele pentru Windows folosesc mesajele
WM_KEYDOWN pentru tastele care nu genereaz caractere. Dei
s-ar putea s v vin ideea s folosii mesajele pentru acionri de
taste n combinaie cu informaiile despre tastele de modificare
(furnizate de funcia GetKeyState) ca s transformai mesajele
pentru acionri de taste n mesaje pentru caractere, nu facei acest
lucru. Vei avea probleme datorit diferenelor ntre tastaturile
36

internaionale. De exemplu, dac primii un mesaj


WM_KEYDOWN pentru care parametrul wParam are valoarea
33H, tii c utilizatorul a apsat tasta 3. Pn aici totul este bine.
Dac apelai funcia GetKeyState vei afla c tasta Shift este
apsat i s-ar putea s presupunei c utilizatorul a introdus un
caracter diez (#), lucru care poate s nu fie adevrat. Un utilizator
britanic ar fi introdus caracterul . Mesajele WM_KEYDOWN
sunt utile pentru tastele de deplasare, tastele funcionale i tastele
speciale, precum Insert, Delete. Uneori tastele Insert, Delete si
tastele funcionale sunt folosite ca acceleratori pentru comenzi de
meniu. Deoarece Windows transform acceleratorii n comenzi de
meniu, nu este nevoie s prelucrai n program mesajele pentru
acionarea tastelor de accelerare. Unele programe non-Windows
folosesc foarte des tastele funcionale n combinaie cu tastele Alt,
Ctrl i Shift. Putei face acest lucru i n programele pentru
Windows, dar nu este recomandat. Dac vrei s folosii tastele
funcionale, acestea trebuie s dubleze comenzi din meniuri. Unul
dintre obiectivele sistemului de operare Windows este s nu oblige
utilizatorii s memoreze sau s foloseasc liste complicate de
comenzi.
Am reuit s eliminm aproape totul, cu excepia unui singur
lucru: de cele mai multe ori vei prelucra mesajele
WM_KEYDOWN numai pentru tastele de deplasare a cursorului.
Atunci cnd prelucrai mesajele trimise de tastele de deplasare
putei s verificai i starea tastelor Shift i Ctrl, folosind funcia
GetKeyState. Unele funcii Windows folosesc de multe ori tastele
de deplasare n combinaie cu tasta Shift pentru extinderea unei
selecii - de exemplu ntr-un procesor de texte. Tasta Ctrl este
folosit deseori pentru a schimba semnificaia unei taste de
deplasare. De exemplu, tasta Ctrl n combinaie cu sgeata spre
dreapta mut cursorul cu un cuvnt Ia dreapta.
Am discutat mai devreme despre ideea transformrii mesajelor
generate de aciona rea tastelor n mesaje caracter innd cont de
starea tastelor de modificare i v-am avertizat c acest lucru nu
este suficient: trebuie s inei seama i de configuraia diferit a
tastaturii de la o ar la alta. Din acest motiv, nu trebuie s
ncercai s transformai dumneavoastr mesajele generate de
37

acionarea tastelor n mesaje caracter. Windows o poate face n


locul dumneavoastr. Ai mai vzut aceast secven de cod:
while (GetMessage (&msg, NULL, 0, 0))
{ TranslateMessage (&msg);
DispatchMessage (&msg);
}

Acesta este un ciclu tipic de tratare a mesajelor din funcia


WinMain. Funcia GetMessage preia urmtorul mesaj din coada de
ateptare i completeaz cmpurile structurii msg. Funcia
DispatchMessage transmite mesajul procedurii de fereastr
corespunztoare. ntre cele dou funcii este apelat funcia
TranslateMessage, care transform mesajele generate de
acionarea tastelor n mesaje caracter. Dac mesajul este
WM_KEYDOWN sau WM_SYSKEYDOWN i dac tasta
apsat, n funcie de starea tastelor de modificare, genereaz un
caracter, atunci funcia TranslateMessage insereaz un mesaj
caracter n coada de ateptare. Acesta va fi urmtorul mesaj pe
care l va prelua funcia GetMessage dup mesajul generat de
acionarea tastei. Exist patru mesaje caracter:

Caractere non-sistem
Caractere sistem

Caractere

Caractere
moarte"

WM_CHAR
WM_SYSCHAR

WM_DEADCHAR
WM_SYSDEADCHAR

Mesajele WM_CHAR i WM_DEADCHAR sunt obinute din


mesaje WM_KEYDOWN. Mesajele WM_SYSCHAR i
WM_SYSDEADCHAR
sunt
obinute
din
mesaje
WM_SYSKEYDOWN. n majoritatea cazurilor programul poate
s ignore toate celelalte mesaje n afar de WM_CHAR.
Parametrul lParam transmis procedurii de fereastr are acelai
coninut ca i parametrul lParam al mesajului generat de
acionarea tastei din care a fost obinut mesajul caracter.
Parametrul wParam conine codul ASCII al caracterului.
O metod cea mai simpl de a crea o interfa a tastaturii este
utilizarea logicii prelucrrii mesajelui WM_KEYDOWN n procedura
de fereastr. De exemplu:
...
38

case WM_KEYDOWN:
switch(wParam)
{
case x:
// x
//
[ ]
break;
...
}
return 0;
...

Acest fragment de program este asemntor cu secvenele de


cod pentru tratarea caracterelor dintr-un program MS-DOS
obinuit.
Sarcina lucrrii: de scris un program care n zona client afiaz
un desen, care poate fi micat cu ajutorul tastelor (la stnga),
(n sus), (la dreapta), (n jos). De asemenea, trebuie s fie
prevzute taste pentru rotirea figurii.
ntrebri de control:

39

S-ar putea să vă placă și