Sunteți pe pagina 1din 94

Lista ntrebrilor la disciplina PW

1.ISTORIA WINDOWS. CE ADUCE NOU WINDOWS. Conceptele i fundamentele GUI. Consecvena


privind interfa cu utilizatorul. Avantajul oferit de multitasking. Gestionarea memoriei. Interfaa
grafic independent de dispozitiv.
WINDOWS. WINDOWS.
GUI. .
multitasking-. .
.

UN SCURT ISTORIC AL SISTEMULUI DE OPERARE WINDOWS


Crearea sistemului de operare Windows a fost anunat de Microsoft Corporation n
noiembrie 1983 (dup Lisa, dar nainte de Macintosh) i doi ani mai trziu, n noiembrie 1985, a
fost lansat versiunea Windows 1.0. Versiunile lansate n urmtorii doi ani au fost actualizate i
adaptate pentru piaa internaional, furniznd noi drivere pentru alte plci video i inprimante.
Versiunea Windows 2.0 a fost lansat n noiembrie 1987. Aceast versiune include cteva
modificri asupra interfeei cu utilizatorul. Cea mai semnificativ dintre acestea este folosirea
ferestrelor suprapuse n locul ferestrelor alturate din versiunile Windows 1.x. De asemenea.
Windows 2.0 include unele mbuntiri ale interfeei cu mouse-ul i cu tastatura, n special
legate de meniuri i de casetele de dialog.
n orice istoric Windows ar trebui s fie menionat i sistemul de operare OS/2, o alternativ
la MS-DOS i Windows, dezvoltat iniial de Microsoft n colaborare cu IBM. Versiunea OS/2 1.0
(numai n mod caracter) a fost lansat la sfritul anului 1987 i rula pe microprocesoarele Intel
80286 sau mai noi. Mediul grafic Presentation Manager (PM) a aprut odat cu versiunea OS/2
1.1 n octombrie 1988. PM a fost proiectat iniial ca o variant n mod protejat a mediului
Windows, dar interfaa API s-a modificat att de mult nct productorii software nu au putut s
susin ambele platforme.
Windows 95 (care a purtat anterior numele de cod Chicago i este numit uneori Windows
4.0) a fost lansat n august 1995. Ca i Windows NT, Windows 95 accept modelul de
programare pe 32 de bii (i, ca urmare, are nevoie de un microprocesor 80386 sau mai nou).
Dei Windows 95 nu egaleaz performanele sistemului de operare Windows NT n anumite
aspecte cum ar fi securitatea sau portabilitatea pe calculatoarele RISC, Windows 95 are avantajul
c poate fi rulat pe calculatoarele cu cel puin 4 megaoctei de memorie.
Evident, programele scrise pentru versiunile pe 16 bii ale sistemului de operare Windows
(aprute nainte de Windows 95 i Windows NT) nu sunt direct portabile ctre versiunile mai
noi, pe 32 de bii; n capitolele urmtoare vom discuta unele dintre modificrile care sunt
necesare pentru a realiza acest lucru.
Microsoft a ncercat s diferenieze platformele prin definirea unor seturi de interfee API.
Interfaa Win16 API este acceptat de versiunea Windows 3.1. Interfaa Win32 API este
acceptat de versiunile Windows 95 i Windows NT. Dar ateptai - mai este ceva. Microsoft
permite programatorilor s scrie programe pe 32 de bii pentru Windows 3.1; apelurile de funcii
pe 32 de bii au fost convertite n apeluri pe 16 bii de o bibliotec cu legturi dinamice (DLL).
Aceast interfaa API a fost numit Win32s (s" de la subset", deoarece aceast interfaa accept
numai funciile din Win16). Pentru o perioad, interfaa API din Windows 95 a fost numit
Win32c (c" de la compatibil") dar acest nume a fost abandonat mai trziu.
n acest moment se consider c att Windows NT ct i Windows 95 accept interfaa
Win32 API. Cu toate acestea, fiecare dintre cele dou sisteme de operare are unele caracteristici
pe care cellalt sistem de operare nu le are. Partea comun fiind considerabil, scrierea
programelor care ruleaz sub ambele sisteme este totui posibil. De asemenea, o prere larg
rspndit susine c cele dou produse vor fi nglobate ntr-unul singur, n viitor.
CE ADUCE NOU SISTEMUL DE OPERARE WINDOWS
Sistemul de operare Windows ofer avantaje semnificative fa de mediul MS-DOS, att
pentru utilizatori, ct i pentru programatori. Multe dintre aceste avantaje sunt comune pentru
1

utilizatori i pentru programatori, deoarece sarcina dezvoltatorilor unui program este s ofere
utilizatorilor lucruri de care acetia au nevoie.
CONCEPTELE I FUNDAMENTELE GUI
La nceput, ecranul era folosit numai pentru afiarea informaiilor pe care utilizatorul le
introducea de la tastatur. ntr-o interfa grafic, ecranul devine chiar o surs pentru celelalte
intrri ale utilizatorului. Pe ecran sunt afiate diferite obiecte grafice sub forma pictogramelor i
a unor dispozitive de intrare, precum butoanele i barele de derulare. Folosind tastatura (sau, mai
direct, un dispozitiv de indicare precum mouse-ul) utilizatorul poate s manipuleze direct aceste
obiecte de pe ecran. Obiectele grafice pot fi deplasate, butoanele pot fi apsate i barele de
derulare pot fi derulate.
Interaciunea dintre program i utilizator devine mult mai direct. n locul unui ciclu
unidirectional al informaiilor de la tastatur la program i de la program la ecran, utilizatorul
interacioneaz direct cu obiectele de pe ecran.

Consecvena privind interfa cu utilizatorul


Dup ce nvai s folosii un program Windows, vei fi capabil deja s utilizai orice alt
program pentru Windows. Meniurile i casetele de dialog permit utilizatorului s
experimenteze diferite funcii ale programului i s i exploreze posibilitile. Majoritatea
programelor Windows au interfa att cu mouse-ul, ct i cu tastatura. Dei majoritatea
funciilor unui program pentru Windows pot fi controlate i cu ajutorul tastaturii, mouse-ul
este deseori mai convenabil pentru diferite sarcini.
Din punctul de vedere al programatorului, consecvena n realizarea interfeei cu utilizatorul
este rezultatul folosirii procedurilor integrate n Windows pentru construirea meniurilor i a
casetelor de dialog. Toate meniurile au aceeai interfa cu tastatura i cu mouse-ul deoarece
aceste operaii sunt manipulate mai degrab de Windows, dect de programul respectiv.

AVANTAJUL OFERIT DE MULTITASKING


Versiunile anterioare ale sistemului de operare Windows foloseau un tip de multitasking
numit necontrolat". Aceasta nseamn c Windows nu folosea ceasul sistemului ca s aloce
timpi de procesare diferitelor programe care ruleaz n sistem. Programele trebuie s cedeze
voluntar controlul, astfel nct alte programe s-i poat continua execuia . n Windows 95
multitaskingul este controlat i programele se pot mpri n mai multe fire de execuie, care par
s ruleze n acelai timp.
Gestionarea memoriei
Un sistem de operare nu poate s implementeze multitaskingul fr o gestionare adecvat a
memoriei. Pe msur ce noi programe sunt ncrcate n memorie i altele vechi i ncheie
execuia, memoria se poate fragmenta. Sistemul de operare trebuie s aib posibilitatea s
consolideze memoria liber. Pentru aceasta, sistemul trebuie s poat muta blocuri de cod i de
date n memorie.
Programele rulate sub Windows pot s depeasc memoria existent; un program poate
conine mai mult cod dect ncape n memorie la un moment dat. Windows poate s elimine din
memorie o parte din cod i ulterior s rencarce codul respectiv din fiierul executabil de pe harddisc. Un utilizator poate rula simultan mai multe copii ale aceluiai program, numite instane";
toate aceste instane folosesc acelai cod din memorie. Programele rulate sub Windows pot s
partajeze rutine stocate n alte fiiere numite biblioteci cu legturi dinamice" (dynamic link
libraries). Windows conine un mecanism de editare a legturilor dintre program i rutinele din
bibliotecile cu legturi dinamice, n timpul execuiei. Chiar sistemul de operare este, n esen, o
colecie de biblioteci cu legturi dinamice.

Interfaa grafic independent de dispozitiv


Windows este o interfa grafic i programele pentru Windows pot folosi toate avantajele oferite
de elementele grafice i de textul formatat att pentru ecran, ct i pentru imprimant. O interfa
grafic nu are numai avantajul de a fi mai atractiv, ci i pe acela de a furniza utilizatorului o
cantitate mai mare de informaii.
Programele scrise pentru Windows nu au acces direct la componentele hardware ale
dispozitivelor de afiare, cum ar fi ecranul sau imprimanta. n schimb, Windows folosete un
limbaj de programare pentru grafic (numit GDI - Graphics Device Interface) care simplific
afiarea textului formatat i a elementelor grafice. Windows transform componentele hardware
de afiare n dispozitive virtuale. Un program scris pentru Windows va rula cu orice plac video
i cu orice imprimanta pentru care Windows are un driver de dispozitiv. Programul nu trebuie s
determine ce tip de dispozitiv fizic este ataat la calculator.
2Apelurile de funcii. Arhitectura bazat pe mesaje. Procedura de fereastr. WinMain i WndProc.
. , . . WinMain i WndProc.

Apelurile de funcii
Windows 95 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.
Un alt exemplu: funcia IsClipboardFormatAvailable determin dac n memoria temporar
(clipboard) sunt stocate date ntr-un anumit format.
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 95, aa cum este, de pild, C. Fiierele antet sunt o
parte important a documentaiei Windows. Putei s tiprii o copie a fiierelor antet sau s
folosii un browser pentru o cutare rapid.
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).
Arhitectura bazat pe mesaje
n Windows, atunci cnd utilizatorul redimensioneaz o fereastr, sistemul de operare trimite
programului un mesaj prin care i comunic noile dimensiuni ale ferestrei. Programul poate apoi
s modifice coninutul ferestrei, astfel nct acesta s se adapteze la noile dimensiuni.
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").
Procedura de fereastr
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.
Mai precis, 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 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
3

procedur de fereastr (aflat ntr-una dintre bibliotecile cu legturi dinamice ale sistemului de
operare) care prelucreaz mesajele trimise ctre ferestrele butoanelor.
O procedur de fereastr prelucreaz mesajele trimise ferestrei respective. Deseori, aceste
mesaje informeaz fereastra cu privire la aciunile executate de utilizator cu ajutorul mouse-ului
sau al tastaturii. Aceasta este calea prin care o fereastr afl", de exemplu, c un buton a fost
apsat. Alte mesaje comunic ferestrei c a fost redimensionat sau c trebuie s fie refcut.
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.
WinMain si WinProc
Fiierul conine numai dou funcii: WinMain i WndProc. Funcia WinMain reprezint
punctul de intrare n program. Aceasta este echivalentul funciei main din programele scrise n
limbajul C. Orice program pentru Windows trebuie s aib o funcie WinMain.
WndProc este procedura de fereastr" a ferestrei create de programu. Orice fereastr indiferent dac este fereastra principal a aplicaiei sau fereastra unui mic buton de apsare - are
o procedur de fereastr. Procedura de fereastr este un mod de ncapsulare a codului care
rspunde intrrilor (n general de la tastatur i de la mouse) i afieaz elementele grafice pe
ecran. Aa cum vei vedea, procedura de fereastr face acest lucru prin prelucrarea mesajelor"
trimise ctre fereastr
Nici o instruciune din fiierul HELLOWIN.C nu apeleaz direct funcia WndProc: WndProc
este apelat de sistemul de operare Windows. Totui, n funcia WinMain apare o referire la
funcia WndProc, acesta fiind motivul pentru care WndProc este declarat n partea de nceput a
programului, nainte de WinMain
1.

Atributele contextului de dispozitiv. Salvarea contextului de dispozitiv. Funciile LineTo, Polyline i


PolylineTo, PolyPolyline, Arc, PolyBezier i PolyBezierTo, Rectangle, Ellipse, RoundRect, Chord i Pie.
DC. DC. LineTo, Polyline PolylineTo, PolyPolyline, Arc,
PolyBezier PolyBezierTo, Rectangle, Ellipse, RoundRect, Chord Pie.

Atributele contextului de dispozitiv

Windows folosete contextul de dispozitiv ca s stocheze atributele care specific modul de


lucru al funciilor GDI pentru afiare. De exemplu, atunci cnd afiai un text folosind funcia
TextOut nu trebuie s specificai culoarea textului sau fontul folosit. Windows folosete contextul
de dispozitiv ca s obin aceste informaii.
Atunci cnd un program obine o variabil handle a unui context de dispozitiv, Windows creeaz un context de
dispozitiv cu valorile prestabilite pentru toate atributele
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:
hd = BeginPaint (hwnd, &ps);
[iniializeaz atributele contextului de dispozitiv] [deseneaz zona client a ferestrei]
EndPaint (hwnd, &ps);
return 0;

Un atribut al DC specifica modul de lucru al functiilor de desenare; SetTextColor,... Toate atributele DC au


valori prestabilite care devin active la obtinerea DC. Pentru fiecare functie de tip Set exista si o functie de tip
Get,
folosita pt. obtinerea valorilor curente ale atributelor DC.
Functii care obtin (sau creaza) si elibereaza (sau distrug) un context de dispozitiv; (in API: BeginPaint ...
EndPaint, GetDc, ReleaseDC;
Funcia LineTo trage o linie de la poziia curent pn la, dar fr a include, un punct specificat
BOOL LineTo(
HDC hdc,
//
int nXEnd, // x
int nYEnd
// y
);
Funcia Polyline atrage o serie de segmente de dreapt, punctele de conectare specificate n matrice.
BOOL Polyline(HDC hdc,
//
CONST POINT *lppt, //
int cPoints
//
);
Funcia PolylineTo trage una sau mai multe linii drepte.
BOOL PolylineTo(
HDC hdc,
//
CONST POINT *lppt, //
DWORD cCount
//
);
Funcia PolyPolyline atrage mai multe segmente de linie de serie conectat.
BOOL PolyPolyline(
HDC hdc,
//
CONST POINT *lppt,
//
CONST DWORD *lpdwPolyPoints, //
DWORD cCount
//
);

Funcia Arc atrage un arc eliptic.


BOOL Arc (
_In_ HDC HDC,
_In_
Int nLeftRect,
_In_
Int nTopRect,
_In_
Int nRightRect,
_In_
Int nBottomRect,
_In_
int nXStartArc,
_In_
int nYStartArc,
_In_
int nXEndArc,
_In_
Int nYEndArc
);
Funcia PolyBezier atrage una sau mai multe curbe Bezier.
BOOL PolyBezier (
_In_ HDC HDC,
_In_
const POINT * LPPT,
_In_ CPoints DWORD
);
Funcia PolyBezierTo atrage una sau mai multe curbe Bezier.
BOOL PolyBezierTo (
_In_ HDC HDC,
_In_
const POINT * LPPT,
_In_ DWORD cCount
5

);
Functia Rectangle deseneaza un dreptunghi cu penula selectata si il umple cu culoare cu periuta selectata
Rectangle(hdc, 25, 30, 100, 50)

Funcia Ellipse atrage o elips. Centrul a elipsei este centrul dreptunghiului de


ncadrare specificat. Elipsa este conturat cu ajutorul stiloului curent i este umplut
cu ajutorul periei curent.
BOOL Ellipse (
_In_ HDC HDC,
_In_
Int nLeftRect,
_In_
Int nTopRect,
_In_
Int nRightRect,
_In_
Int nBottomRect
);
Funcia RoundRect atrage un dreptunghi cu coluri rotunjite. Dreptunghiul este
subliniat cu ajutorul pen-ului curent i este completat, cu ajutorul periei curent.
BOOL RoundRect (
_In_ HDC HDC,
_In_
Int nLeftRect,
_In_
Int nTopRect,
_In_
Int nRightRect,
_In_
Int nBottomRect,
_In_
Int nWidth,
_In_
Int nHeight
);
Funcia Chord atrage o coard (o regiune delimitat de intersecia de elips i un
segment de linie, numit secant). Coard este conturat de utilizare a stiloului
curent i umplut folosind pensula curent.
BOOL Chord (
_In_ HDC HDC,
_In_
Int nLeftRect,
_In_
Int nTopRect,
_In_
Int nRightRect,
_In_
Int nBottomRect,
_In_
Int nXRadial1,
_In_
Int nYRadial1,
_In_
Int nXRadial2,
_In_
Int nYRadial2
);
Functia Pie trage un sector de elipsa
2.

Bazele utilizrii cronometrului.

Cronometrul Windows este un dispozitiv de intrare, ce comunic periodic unei aplicaii trecerea unui
anumit interval de timp. Programul specific sistemului de operare acest interval de timp, spunndu-i
ceva de genul: F-mi un semn la fiecare 10 secunde". Windows trimite periodic programului, mesaje
WM_TIMER prin care i semnaleaz trecerea intervalului de timp respectiv.
Iat cteva alte utilizri sub Windows ale cronometrului, dei s-ar putea ca unele s nu fie att de
evidente:

Multitaskingul - Dei Windows 95 este un mediu cu multitasking controlat, uneori este mult mai
eficient ca un program s returneze controlul sistemului de operare, imediat ce este posibil.
Dac programul trebuie s execute o operaie de durat, o poate mpri n operaii mai mici, pe
care s le prelucreze la primirea unui mesaj WM_TIMER.
6

3.

Actualizarea unui raport de stare - Un program poate s utilizeze cronometrul pentru afiarea
n timp real" a unor informaii care se schimb continuu, n funcie de resursele sistemului sau
de evoluia unei anumite operaii.

Implementarea unei caracteristici de autosalvare" - Cronometrul poate s aminteasc" unui


program Windows s salveze pe hard-disc documentul la care lucreaz utilizatorul, dup trecerea
unui anumit interval de timp.

nchiderea versiunilor demonstrative ale unui program - Unele versiuni demonstrative ale
programelor sunt proiectate astfel nct s-i ncheie execuia, de exemplu, dup trecerea a 30 de
minute de la lansare. Cronometrul poate s semnaleze unei astfel de aplicaii terminarea timpului
permis de rulare.

Deplasri succesive - Obiectele grafice dintr-un joc sau imaginile afiate succesiv de un
program de instruire asistat de calculator trebuie s fie prelucrate la anumite intervale de
timp. Folosirea cronometrului elimin inconsecvenele care pot aprea datorit diferenelor
dintre viteza de lucru a microprocesoarelor.
Care este punctul de intrare ntr-un program Windows? W?

Funcia WinMain reprezint punctul de intrare n program. Aceasta este echivalentul funciei
main din programele scrise n limbajul C. Orice program pentru Windows trebuie s aib o
funcie WinMain.
Totui, n funcia WinMain apare o referire la funcia WndProc, acesta fiind motivul pentru
care WndProc este declarat n partea de nceput a programului, nainte de WinMain.
Funcia WinMain este de tipul WINAPI. Punctul de intrare ntr-un program Windows este
o funcie numit WinMain. Funcia WinMain este ntotdeauna definit astfel:
int WINAPI WinMain (HINSTANCE hinstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

Aceast funcie folosete secvena de apelare WINAPI i la terminare returneaz sistemului


de operare o valoare ntreag. Numele funciei trebuie s fie WinMain. Aceast funcie are patru
parametri:
Parametrul hlnstance este numit variabil handle a instanei" (instance handle"). Acesta
este un numr care identific n mod unic toate programele rulate n Windows. Utilizatorul poate
rula simultan mai multe copii ale aceluiai program. Aceste copii se numesc instane" i fiecare
are o valoare diferit pentru parametrul hlnstance. Variabila handle a instanei este asemntoare
cu identificatorul de operaie" (task ID") sau identificatorul de proces" (process ID") din alte
sisteme de operare multitasking.
hPrevInstance (previous instance" - instana anterioar) este un parametru nvechit. n
versiunile Windows anterioare acest parametru coninea variabila handle a celei mai recente
instane nc activ a aceluiai program. Dac nu erau ncrcate alte instane ale programului,
hPrevInstance avea valoarea 0 sau NULL. n Windows 95, parametrul hPrevInstance are
ntotdeauna valoarea NULL.
Parametrul szCmdLine este un pointer la un ir de caractere terminat cu zero care conine
eventualii parametri transmii programului n linia de comand. Putei s rulai un program
Windows cu parametri incluznd parametrii respectivi dup numele programului n linia de
comand MS-DOS sau specificndu-i n caseta de dialog Run apelat din meniul Start.
Parametrul iCmdShow este un numr care indic modul iniial de afiare a ferestrei n
Windows. Acest numr este atribuit de programul care lanseaz n execuie programul aflat n
discuie. Programele verific rareori valoarea acestui parametru, dar o pot face dac este nevoie.
n majoritatea cazurilor, iCmdShow are valoarea 1 sau 7. Dar cel mai bine este s nu v gndii la
aceste valori numerice. Mai sugestivi sunt identificatorii SW_SHOWNORMAL (definit n
Windows ca 1) i SW_SHOWMINNOACTIVE (definit cu valoarea 7). Prefixul SW vine de la
show window" (afiare fereastr). Acest parametru specific dac fereastra programului este
afiat normal sau dac este afiat iniial doar ca o pictogram.
7

4.

Ce aduce nou SO Windows? Windows?

Sistemul de operare Windows ofer avantaje semnificative fa de mediul MS-DOS, att


pentru utilizatori, ct i pentru programatori. Multe dintre aceste avantaje sunt comune
pentru utilizatori i pentru programatori, deoarece sarcina dezvoltatorilor unui program
este s ofere utilizatorilor lucruri de care acetia au nevoie. Windows 95 face posibil acest
lucru.
5.

Ce este notaia ungar? Exemplificai. ? .

Muli programatori Windows folosesc notaia ungar", o convenie de denumire a


variabilelor intitulat astfel n onoarea legendarului programator de la Microsoft, Charles
Simonyi. Convenia este foarte simpl - fiecare nume de variabil ncepe cu una sau mai multe
litere mici care specific tipul de date al variabilei. De exemplu, prefixul sz al variabilei
szCmdLine semnific ir de caractere terminat cu zero". Prefixul h al variabilelor hInstance i
hPrevInstance nseamn variabil handle"; prefixul i al variabilei iCmdShow nseamn ntreg".
i ultimii doi parametri ai funciei WndProc respect notaia ungar, dei, aa cum am artat mai
devreme, wParam ar fi trebuit s se numeasc uiParam (de la unsigned integer"). Totui,
deoarece aceti doi parametri se definesc folosind tipurile de date WPARAM i LPARAM, am
pstrat denumirile originale.
Atunci cnd denumii variabilele de tip structur, putei s folosii numele de tip al structurii
(sau o abreviere a acestuia) ca prefix al numelui variabilei sau chiar ca nume al variabilei. De
exemplu, n funcia WinMain din programul HELLOWIN.C, variabila msg este o structur de tip
MSG iar wndclass este o variabil de tip WNDCLASSEX. n funcia WndProc, ps este o
structur de tip PAINTSTRUCT iar rect este o structur de tip RECT.
Notaia ungar v ajut s descoperii erorile nainte ca acestea s ajung n programele
finale. Deoarece numele unei variabile descrie att modul de folosire a acesteia, ct i tipul
de date, este mai puin probabil s facei erori de programare care implic amestecarea unor
tipuri de date incompatibile.
Prefixele folosite pentru variabilele din aceast carte sunt prezentate n tabelul urmtor:
Prefix Tip de date

c
by
n
i
x, y
cx, cy
b sau f
w
l
dw
fn
s
sz
h
p
6.

char
BYTE (unsigned char)
short
int
int (folosit pentru coordonate)
int (folosit pentru dimensiuni pe axele x si y, c vine de la contor")
BOOL (int); f vine de la flag" (indicator)
WORD (unsigned short)
LONG (long)
DWORD (unsigned long)
funcie
ir de caractere
sir de caractere terminat cu zero
variabil handle
pointer

Ce este o variabil handle i care este destinaia ei? handle


?
Variabila handle este un numar pe care Windows il foloseste la indicarea unui obiect.

7.

Ce este programare controlat de evenimente?


?

Programarea orientat eveniment este o paradigm a programrii calculatoarelor. Spre deosebire de programele
tradiionale, care-i urmeaz propria execuie, schimbndu-i cteodata doar cursul n puncte
de ramificaie (instruciuni test, etc), cursul execuiei unui program orientat eveniment este condus n mare parte de
evenimente externe.
Programele orientate eveniment sunt formate de obicei dintr-un numr de programe mici numite handlere de
eveniment, care sunt apelate ca rspuns la evenimente externe i dintr-un coordonator (dispatcher), care apeleaz
handlerele de evenimente, folosind de obicei o coad a evenimentelor, care s rein evenimentele care nu au fost
procesate.
n multe cazuri, handlerele de evenimente pot declana ele nsele evenimente, ducnd la o cascad de evenimente.
Programarea orientat eveniment accentueaz ca virtui flexibilitatea i asincronicitatea.
Programele cu interfee grafice sunt de obicei programate ntr-o modalitate gestionat de evenimente. Sistemele de
operare sunt un alt exemplu clasic de programe dirijate de evenimente pe cel puin dou nivele. La cel mai de jos
nivel, handlerele de ntreruperi se comport ca handlere de evenimente hardware, cu procesorul n rol de
coordonator (dispatcher). Sistemele de operare, de asemenea se comport ca i coordonatori pentru procese,
transmind datele i ntreruperile soft ctre procese user, care de multe ori sunt programate ca i handlere de
eveniment.

8.

Ce este un device context? device context

Contextul de dispozitiv (prescurtat DC - device context) este o structur de date ntreinut intern de interfaa GDI.
Fiecare context de dispozitiv este asociat unui anumit dispozitiv de afiare, cum ar fi imprimanta, plotterul sau
monitorul video. n cazul monitoarelor video, un context de dispozitiv este de obicei asociat unei anumite ferestre de
pe ecran
9.

Ce este un multitasking controlat?

Programele trebuie s cedeze voluntar controlul, astfel nct alte programe s-i poat
continua execuia. n Windows 95 multitaskingul este controlat i programele se pot mpri n
mai multe fire de execuie, care par s ruleze n acelai timp.
10.

Ce facem dac cronometrul nu este ccesibil? ,

Secvena de cod din exemplul urmtor afieaz o caset de mesaje atunci cnd funcia SetTimer nu
poate aloca programului un cronometru:

if (!SetTimer (hwnd, 1, 1000, NULL))


{
MessageBox (hwnd, "Too many clocks or timers!", "Program Name",
MB_ICONEXCLAMATION ] MB_OK);
return FALSE ;
}
11.

Ce prezint procedura unei ferestre?

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

Acest tip de multitasking se mai numete i multitasking cooperativ", (n.t)

fereastr. Procedura de fereastr prelucreaz anumite informaii pe baza mesajului primit, apoi
returneaz controlul sistemului de operare.
Mai precis, 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 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.
12.

Clasa butoanelor.

13.

Coduri virtuale de taste. Starea tastelor de modificare. Utilizarea mesajelor de acionare a tastelor.
. -.
.

Coduri virtuale de taste


Zecimal Hexa

Identificator
WINDOWS.H

1
2
3
4
8
9
12

01
02
03
04
08
09
0C

VK_BUTTON

13
16
17
18

0D
10
11
12

VK_RETURN
VK_SHIFT
VK_CONTROL
VK_MENU

VK_RBUTTON
VK_CANCEL
VK_MBUTTON
VK_BACK
VK_TAB
VK_CLEAR

Necesar

Tastatur IBM

Ctrl-Break

Backspace
Tab
Tasta numeric 5 cu
tasta
Num Lock inactiv
Enter
Shift
Ctrl
Alt

Starea tastelor de modificare


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. De asemenea, putei
s obinei starea butoanelor mouse-ului folosind codurile virtuale VK_LBUTTON,
VK_MBUTTON i VK_RBUTTON. Totui, majoritatea programelor pentru Windows care
trebuie s monitorizeze combinaiile ntre taste i butoanele mouse-ului utilizeaz calea invers verificnd starea tastelor atunci cnd primesc un mesaj de la mouse. De fapt, starea tastelor de
10

modificare este inclus n mesajele primite de la mouse (aa cum vei vedea n capitolul
urmtor).
Utilizarea mesajelor de acionare a tastelor
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 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.
14.

Crearea ferestrelor child.

Programul BTNLOOK definete o structur numit button care conine stilurile de fereastr ale
butoanelor i iruri de caractere descriptive pentru fiecare dintre cele 10 tipuri de butoane. Stilurile de
fereastr ale butoanelor ncep cu literele BS_ care sunt o prescurtare de la button style".
Cele 10 ferestre descendent sunt create ntr-un ciclu for n cadrul procedurii WndProc, n timpul
prelucrrii mesajului WM_CREATE. Apelul funciei CreateWindow folosete urmtorii parametri:
Class name (numele clasei)
"button"
Window text (textul ferestrei)
button[i].text
Window style (stilul ferestrei)
WS_CHILD|WS_VISIBLE|button[i].style
x position (poziia x)
cxChar
y position (poziia y)
cyChar * (1 + 2 * i)
Width (lime)
20 * cxChar
Height (nlime)
7*cyChar/4
Parent window (fereastra printe)
hwnd
Child window ID (identificatorul ferestrei descendent)
(HMENU) i
Instance handle (variabila handle a instanei)
((LPCREATESTRUCT) lParam) -> hlnstance
Extra parameters (ali parametri)
NULL
Parametrul care reprezint numele clasei este numele predefinit. Pentru stilul ferestrei sunt
folosite valorile WS_CHILD, WS_VISIBLE sau unul dintre cele zece stiluri de butoane
(BS_PUSHBUTTON, BS_DEFPUSHBUTTON i aa mai departe), definite n structura button. Textul
ferestrei (care pentru o fereastr normal apare n bara de titlu) este textul care va fi afiat pe fiecare
buton. n acest exemplu am folosit textul care identific stilul butonului.
Parametrii x i y indic poziia colului din stnga-sus al ferestrei descendent, raportat la colul
din stnga-sus al zonei client a ferestrei printe. Parametrii width i height specific limea i nlimea
fiecrei ferestre descendent.
Identificatorul ferestrei descendent (ID) trebuie s fie unic pentru fiecare fereastr descendent.
Acest identificator permite procedurii ferestrei printe s identifice fereastra descendent atunci cnd
11

prelucreaz mesajele WM_COMMAND primite de la aceasta. Remarcai faptul c identificatorul


ferestrei descendent este transmis prin parametrul funciei CreateWindow folosit n mod normal pentru
specificarea meniului n program, aa c trebuie s fie convertit la o valoare de tip HMENU.
Parametrul variabilei handle a instanei din apelul funciei CreateWindow pare puin ciudat, dar am
profitat de faptul c n mesajul WM_CREATE lParam este de fapt un pointer la o structur de tipul
CREATESTRUCT (structur de creare") care are un membru hlnstance. Ca urmare, am convertit
parametrul lParam la un pointer la o structur CREATESTRUCT i am obinut variabila membru
hlnstance.
Dup apelarea funciei CreateWindow nu mai trebuie s facem nimic n legtur cu aceste ferestre
descendent. Procedura ferestrei buton din Windows execut ntreinerea acestor butoane i toate
operaiile de redesenare. (Singura excepie este butonul de tipul BS_OWNERDRAW; aa cum vom
arta mai trziu, sarcina de desenare a butoanelor de acest tip revine programului.) La terminarea
programului, Windows distruge toate ferestrele descendent odat cu distrugerea ferestrei printe.
15.

Cum poate fi obinut variabila handle a unui device context?


handle device context-?
Functii care obtin (sau creaza) si elibereaza (sau distrug) un context de dispozitivI: BeginPaint ... EndPaint, si
GetDc, ReleaseDC;

16.

Curbe Bezier. Funcia PolyBezierTo. Bezier. PolyBezierTo.

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
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
17.

Cursorul de editare (CARET). Funcii pentru cursorul de editare. Soluia Unicode pentru Windows.
(CARET). . Unicode
Windows.

18.

Desenarea suprafeelor pline. Funcia Polygon i modul de umplere a poligoanelor. Funcia


SetPolyFillMode. Umplerea suprafeelor interioare. .
Polygon . SetPolyFillMode.
.

Cele apte funcii Windows pentru desenarea figurilor sunt prezentate n tabelul urmtor:
Funcie

Figura

Rectangle
Ellipse
RoundRect
Chord

Dreptunghi cu coluri drepte


Elips

Pie
Polygon
PolyPolygon

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.
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
12

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 (GB*Y_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)) ;

Funcia Polygon i modul de umplere a poligoanelor


Am discutat deja despre primele cinci funcii de desenare a suprafeelor pline. Polygon este
cea de-a asea funcie de desenare a unei figuri colorate n interior, cu contur. Apelul funciei
Polygon este asemntor cu cel al funciei Polyline:
Polygon (hdc, pt, iCount) ;

Parametrul pt este un pointer la o matrice de structuri POINT, iar iCount reprezint numrul
de puncte din matrice. Dac ultimul punct din matrice este diferit de primul punct, Windows mai
deseneaz o linie care conecteaz ultimul i primul punct. (Acest lucru nu se ntmpl i n cazul
funciei Polyline.)
Suprafaa nchis de poligon este colorat folosind pensula curent n dou moduri, n funcie
de modul de umplere a poligoanelor, definit n contextul de dispozitiv. Modul prestabilit de
umplere a poligoanelor este ALTERNATE, ceea ce nseamn c Windows coloreaz numai
suprafeele nchise la care se poate ajunge din exteriorul poligonului prin traversarea unui numr
impar de laturi (1, 3, 5 i aa mai departe). Celelalte suprafee interioare nu sunt umplute. Dac
selectai WINDING ca mod de umplere, Windows coloreaz toate suprafeele nchise de poligon.
Putei s selectai modul de umplere cu ajutorul funciei SetPolyFillMode:
SetPolyFillMode (hdc, iMode) ;
Cele dou moduri de umplere a poligoanelor sunt ilustrate cel mai bine pe modelul unei stele
cu cinci coluri. n Figura 4-17 steaua din partea stng a fost desenat cu modul de umplere
ALTERNATE, iar steaua din partea dreapt a fost desenat cu modul de umplere WINDING.

13

Figura 4-17. Figuri desenate cu cele dou moduri de umplere a poligoanelor ALTERNATE
(stng) i WINDING
Umplerea suprafeelor interioare
Interiorul figurilor Rectangle, RoundRect, Ellipse, Chord, Pie, Polygon i PollyPolygon este
umplut cu pensula - numit uneori i model" (pattern") - selectat n contextul de dispozitiv. O
pensul este de fapt o imagine bitmap 8x8 repetat pe vertical i pe orizontal, pentru umplerea
unei suprafee.
19.

Dimensiunea unui caracter. Funcia GetTextMetrics. Tipul TEXTMETRIC. Dimensiunile textului.


. GetTextMetrics. TEXTMETRIC. .

Dimensiunea unui caracter


Dimensiunile caracterelor sunt obinute prin apelarea funciei GetTextMetrics. Funcia
GetTextMetrics are nevoie de o variabil handle a contextului de dispozitiv, deoarece returneaz
informaii despre fontul selectat n contextul de dispozitiv. Windows copiaz valorile referitoare
la dimensiunile caracterelor ntr-o structur de tip TEXTMETRIC. Valorile sunt exprimate n
uniti de msur care depind de modul de mapare selectat n contextul de dispozitiv. n
contextul prestabilit de dispozitiv, modul de mapare este MM_TEXT, aa c dimensiunile sunt
date n pixeli.
Pentru folosirea funciei GetTextMetrics trebuie s definii mai nti o variabil de tipul
TEXTMETRIC (numit, de obicei, tm):
TEXTMETRIC tm;
n continuare obinei o variabil handle a contextului de dispozitiv i apelai funcia
GetTextMetrics:
hdc = GetDC(hwnd);
GetTextMetrics(hdc, &tm) ;
ReleaseDC(hwnd, hdc);
Apoi putei s examinai valorile din structura de dimensiuni a textului i, dac dorii, s
salvai unele dintre aceste dimensiuni pentru utilizarea n viitor.

Dimensiunile textului: detalii


Structura TEXTMETRIC furnizeaz o mulime de informaii despre fontul curent selectat n
contextul de dispozitiv. Totui, aa cum putei vedea n Figura 3-3, dimensiunea vertical a unui
font este definit de numai cinci valori.

14

Figura 3-3. Cele cinci valori care definesc dimensiunea verticala a unui caracter.

Acestea sunt uor de neles. Valoarea tmInternalLeading se refer la spaiul pstrat deasupra
unui caracter pentru semnele de accentuare. Dac aceast valoare este zero, literele mari cu
accent sunt afiate ceva mai mici, astfel nct accentul s ncap n partea de sus a caracterului.
Valoarea tmExternalLeading se refer la spaiul recomandat de ctre proiectantul fontului a fi
lsat ntre rndurile de text. Putei s acceptai sau nu aceast recomandare atunci cnd stabilii
distana dintre rndurile de text.
Structura TEXTMETRIC conine dou cmpuri care descriu limea unui caracter:
tmAveCharWidth (limea medie a literelor mici) i tmMaxCharWidth (limea celui mai
mare caracter al fontului). Pentru fonturile cu dimensiune fix cele dou valori sunt egale.
Este important s reinei faptul c dimensiunile fontului sistem depind de rezoluia ecranului
pe care ruleaz sistemul de operare Windows. Windows furnizeaz o interfa grafic
independent de dispozitiv, dar este nevoie de un mic efort i din partea dumneavoastr. Nu
scriei programe Windows care se bazeaz pe ghicirea dimensiunilor unui caracter. Nu
introducei n cod valori fixe. Folosii funcia GetTextMetrics ca s obinei valorile de care avei
nevoie.
20.

DIMENSIUNEA ZONEI CLIENT. Macroinstruciunile LOWORD i HIWORD (LOWORD (lParam),


HIWORD (lParam)). Barele de derulare. Domeniul i poziia unei bare de derulare.
. LOWORD HIWORD. .
.

Dimensiunea zonei client


O metod obinuit de determinare a dimensiunilor zonei client a unei ferestre este
prelucrarea mesajului WM_SIZE n procedura de fereastr. Windows trimite un mesaj
WM_SIZE ctre procedura de fereastr, de fiecare dat cnd se modific dimensiunile ferestrei.
Parametrul lParam transmis procedurii de fereastr conine limea zonei client n cuvntul mai
puin semnificativ (LOWORD) i nlimea zonei client n cuvntul mai semnificativ
(HIWORD). Codul pentru prelucrarea acestui mesaj arat astfel:
static int cxClient, cyClient ;
[alte linii de program] case WM_SIZE :
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
Macroinstruciunile LOWORD i HIWORD sunt definite n fiierele antet din Windows. Ca
i variabilele cxChar i cyChar, variabilele cxClient i cyClient sunt definite ca statice n cadrul
procedurii de fereastr, deoarece vor fi folosite ulterior pentru prelucrarea altor mesaje.
Mesajul WM_SIZE este urmat de un mesaj WM_PAINT, deoarece la definirea clasei am
specificat urmtorul stil de fereastr:
CS_HREDRAW | CS_VREDRAW

15

Aflarea dimensiunilor zonei client a ferestrei este primul pas pentru furnizarea unei metode
de deplasare a textului n zona client atunci cnd aceasta nu este suficient de mare pentru a
cuprinde tot textul afiat.

Barele de derulare
Barele de derulare se numr printre cele mai reuite componente ale unei interfee grafice
pentru mouse; sunt uor de folosit i determin o reacie vizual foarte rapid. Putei s folosii
bare de derulare oriunde afiai ceva - text, imagini, foi de calcul tabelar, nregistrri din baze de
date - pentru care avei nevoie de mai mult spaiu dect este disponibil n zona client a ferestrei.
Barele de derulare sunt poziionale vertical (pentru deplasri n sus i n jos) sau orizontal
(pentru deplasri la stnga i la dreapta). Putei s executai clic pe sgeile de Ia capetele barei
de derulare sau pe zona dintre acestea. Bara de derulare este parcurs longitudinal de o caset
de derulare" care indic poziia aproximativ a prii afiate pe ecran fa de ntregul document.
De asemenea, putei s tragei caseta de derulare cu ajutorul mouse-ului, ca s o mutai ntr-o
anumit poziie. Figura 3-7 prezint modul recomandat de folosire a unei bare de derulare
verticale pentru text.
Programatorii au uneori probleme cu terminologia legat de barele de derulare, deoarece perspectiva lor este
diferit de cea a utilizatorilor: un utilizator care deruleaz un document n jos vrea s aduc pe ecran o parte a
documentului aflat mai jos; pentru aceasta, programul mut de fapt documentul mai sus n raport cu fereastra de pe
ecran. Documentaia Windows i identificatorii definii n fiierele antet se bazeaz, ns, pe perspectiva
utilizatorului: derularea n sus nseamn parcurgerea documentului ctre nceput; derularea n jos nseamn
parcurgerea documentului ctre sfrit.

Tragei caseta de derulare cu mouse-ul,


pentru a fixa o poziie aproximativ n
cadrul documentului.

Vizualizai urmtoarea linie n jos


executnd clic aici (coninutul ferestrei se
deplaseaz n sus)
documentului.

Figura 3-7. Bara de derulare vertical.

Este foarte uor s includei n fereastra aplicaiei o bar de derulare orizontal sau vertical.
Tot ce trebuie s facei este s includei identificatorul WS_VSCROLL (derulare vertical) i/sau
WS_HSCROLL (derulare orizontal) n stilul de fereastr din apelul funciei CreateWindow.
Barele de derulare sunt plasate ntotdeauna la marginea de jos sau la cea din dreapta a ferestrei i
se ntind pe toat limea, respectiv nlimea zonei client. Zona client nu include spaiul ocupat
de barele de derulare. Limea unei bare de derulare verticale i nlimea uneia orizontale sunt
constante pentru un driver de afiare dat. Dac avei nevoie de aceste valori, putei s le obinei
(aa cum ai vzut) prin apelarea funciei GetSystemMetrics.
Domeniul i poziia unei bare de derulare
Fiecare bar de derulare are asociate un domeniu" (definit printr-o pereche de numere ntregi care reprezint
valorile maxim i minim) i o poziie" (punctul n care se afl caseta de derulare n domeniul asociat barei de
derulare). Atunci cnd caseta de derulare se afl la captul de sus (sau la captul din partea stng) al barei de
derulare, poziia corespunde valorii minime. Captul de jos (sau captul din partea dreapt) al barei de derulare
reprezint valoarea maxim.
21.
Elemente de baz despre mouse. Funcia GetSystemMetrics (SM_MOUSEPRESENT); cButtons =
GetSystemMetrics (SM_CMOUSEBUTTONS). Parametrul SM_SWAPBUTTON. Zona senzitiv a
indicatorului. . GetSystemMetrics (SM_MOUSEPRESENT);
16
Vizualizai urmtoarea linie n sus
executnd clic aici (coninutul ferestrei se
deplaseaz n jos)

GetSystemMetrics (SM_CMOUSEBUTTONS). SM_SWAPBUTTON.


.

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, muli programatori
Windows au evitat mult vreme s foloseasc celelalte butoane ale mouse-ului. Totui, mouse-ul
cu trei butoane a devenit un standard de facto, aa c reticena tradiional 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 operaii speciale de tragere (despre care vom discuta n curnd). Putei s determinai dac
mouse-ul este prezent folosind funcia GetSystemMetrics:
fMouse = GetSystemMetrics (SM_MOUSEPRESENT) ;

Variabila fMouse va avea valoarea TRUE (diferit de zero) dac mouse-ul este instalat.
Pentru determinarea numrului de butoane ale mouse-ului instalat, folosii tot funcia
GetSystemMetrics:
cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS) ;

Aceast funcie returneaz valoarea 0 dac mouse-ul nu este instalat.


Utilizatorii care folosesc mna stng pot s inverseze butoanele mouse-ului folosind Panoul
de control din Windows. Dei o aplicaie poate s determine dac butoanele mouse-ului au fost
inversate apelnd funcia GetSystemMetrics cu para-metrul SM_SWAPBUTTON, de obicei
acest lucru nu este necesar. Butonul apsat cu indexul este considerat butonul din stng al
mouse-ului, chiar dac fizic se afl n partea dreapt a mouse-ului. Totui, dac scriei un
program de instruire n care desenai un mouse pe ecran, poate c vei avea nevoie s tii dac
butoanele au fost inversate.
Zona senzitiv a acestui indicator este vrful sgeii. Indicatorul IDC_CROSS (folosit n
programele BLOKOUT dm acest capitol) are zona senzitiv situat la intersecia unor linii
subiri. Indicatorul IDC_WAIT are forma unei clepsidre i, n general, indic faptul c programul
execut o operaie de durat. Programatorii pot s creeze indicatoare proprii (aa cum vom face
n Capitolul 9). Indicatorul predefinit al unei ferestre este specificat la definirea structurii clasei
de ferestre. De exemplu:
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

22.

Ferestre child de control i culoare.

Culorile de sistem
Windows pstreaz 25 de culori de sistem pentru afiarea diferitelor pri ale ecra nului. Putei s
obinei i s stabilii aceste culori cu ajutorul funciilor GetSysColor i SetSysColors. Identificatorii
definii n fiierele antet din Windows specific culorile de sistem. Stabilirea unei culori de sistem cu
ajutorul funciei SetSysColors afecteaz culoarea respectiv numai pe durata sesiunii Windows curente.
Putei s schimbai o parte dintre culorile de sistem folosind seciunea Display a Panoului de control
din Windows (Control Panel) sau modificnd seciunea [colors] din fiierul WIN.INI. Seciunea
[colors] folosete pentru cele 25 de culori de sistem cuvinte cheie (altele dect identificatorii folosii de
funciile GetSysColor i SetSysColors) urmai de valori pentru culorile rou, verde i albastru. Aceste
valori sunt cuprinse n intervalul 0 - 255. Tabelul urmtor prezint modul n care sunt identificate cele 25
de culori de sistem, cu ajutorul identificatorilor folosii de funciile GetSysColor i SetSysColors i al
cuvintelor cheie folosite n fiierul WIN.INI. Tabelul este ordonat cresctor, n funcie de valoarea
constantelor COLOR_ (de la 0 la 24):
17

GetSysColor i SetSysColors

WIN.INI

COLOR_SCROLLBAR
COLOR_BACKGROUND
COLOR_ACTIVECAPTION
COLOR_NACTIVECAPTION
COLOR_MENU
COLOR_WINDOW
COLOR_WINDOWFRAME
COLOR_MENUTEXT
COLOR_WINDOWTEXT
COLOR_CAPTIONTEXT
COLOR_ACTIVEBORDER
COLOR_NACTIVEBORDER
COLOR_APPWORKSPACE
COLOR_HIGHLIGHT
COLOR_HIGHLIGHTTEXT
COLOR_BTNFACE
COLOR_BTNSHADOW
COLOR_GRAYTEXT
COLOR_BTNTEXT
COLOR_NACTIVECAPTIONTEXT
COLOR_BTNHIGHLIGHT
COLOR_3DDKSHADOW
COLOR_3DLIGHT
COLOR_NFOTEXT
COLOR_INFOBK

Scrollbar
Background
ActiveTitle
InactiveTitle
Menu
Window
WindowFrame
MenuText
WindowText
TitleText
ActiveBorder
InactiveBorder
AppWorkspace
Hilight
HilightText
ButtonFace
ButtonShadow
GrayText
ButtonText
InactiveTitleText
ButtonHilight
ButtonDkShadow
ButtonLight
InfoText
InfoWindow

Valorile prestabilite pentru aceste culori sunt furnizate de driverul de afiare. Sistemul de operare
Windows folosete valorile prestabilite, dac acestea nu sunt suprascrise de valorile din seciunea
[colors] a fiierului WIN.INI, care poate fi modificat din Panoul de control.
23.

Ferestre child. Butoane definite de programator. . ,

Executarea unui clic pe aceste butoane determin generarea mesajelor WM_COM-MAND. Pentru
prelucrarea mesajului WM_COMMAND, OWNERDRW apeleaz funcia GetWindcrwRect ca s
stocheze poziia i dimensiunea ntregii ferestre (nu numai a zonei client) ntr-o structur de tip RECT
(dreptunghi). Aceast poziie este definit fa de ecran. OWNERDRW modific apoi cmpurile structurii
n funcie de butonul pe care s-a executat clic. Programul repoziioneaz i redimensioneaz fereas tra prin
apelarea funciei MoveWindow. Aceasta genereaz un nou mesaj WM_SIZE i butoanele sunt
repoziionate n centrul zonei client.
Dac nu ar mai face nimic altceva, programul ar fi complet funcional, dar butoanele nu ar fi vizibile.
Un buton creat cu stilul BS_OWNERDRAW trimite ferestrei printe un mesaj WM_DRAWITEM de
fiecare dat cnd butonul trebuie s fie redesenat. Aceasta se ntmpl la crearea butonului, de fiecare dat
cnd este apsat sau eliberat, cnd obine sau pierde cursorul de intrare i n orice alt situaie cnd trebuie
s fie redesenat.
n mesajul WM_DRAWITEM, parametrul IParam este un pointer ctre o structur de tip
DRAWITEMSTRUCT. Programul OWNERDRW stocheaz acest pointer ntr-o variabil numit pdis.
Aceast structur conine informaiile necesare programului pentru redesenarea butonului. (Aceeai
structur este folosit i pentru casetele list i articolele de meniu desenate de proprietar.) Cmpurile din
structur importante pentru lucrul cu butoane sunt hDC (contextul de dispozitiv al butonului), rcltem (o
structur RECT n care este stocat dimensiunea butonului), CtllD (identificatorul ferestrei controlului) i
UemState (care indic dac butonul este apsat sau dac deine cursorul de intrare).
Programul OWNERDRW ncepe prelucrarea mesajului WM_DRAWITEM prin apelarea funciei
FillRect, pentru a terge suprafaa butonului cu o pensul de culoare alb. Apoi este apelat funcia
FrameRed, care traseaz un chenar negru n jurul butonului. n continuare, OWNERDRW deseneaz cele
patru triunghiuri negre pe buton, prin apelarea funciei Potygon. Aceasta este situaia normal.
Dac butonul este apsat, unul dintre biii cmpului UemState din structura DRAWITEMSTRUCT are
valoarea 1. Putei s testai acest bit folosind constanta ODS_SELECTED. Dac bitul are valoarea 1,
OWNERDRW inverseaz culorile butonului, apelnd funcia InvertRect. Dac butonul deine cursorul
18

de intrare, atunci bitul ODS_FOCUS din cmpul UemState are valoarea 1. n acest caz, programul
OWNERDRW deseneaz o linie punctat n jurul textului afiat de buton, apelnd funcia
DrawFocusRect.
Un avertisment legat de folosirea butoanelor desenate de proprietar: Windows obine contextul de
dispozitiv i l include n structura DRAWITEMSTRUCT. Lsai contextul de dispozitiv n aceeai
stare n care l-ai gsit. Orice obiect GDI selectat n contextul de dispozitiv trebuie s fie deselectat. De
asemenea, avei grij s nu desenai n afara dreptunghiului care definete limitele butonului.
24.

Ferestre child. Butoane i input focus. .

Butoane i cursorul de intrare


Aa cum am menionat mai devreme n acest capitol, butoanele de apsare, butoanele radio i butoanele
desenate de proprietar primesc cursorul de intrare atunci cnd se execut clic pe acestea. Controlul
indic faptul c deine cursorul de intrare printr-o linie punctat care nconjoar textul. Atunci cnd o
fereastr descendent primete cursorul de intrare, fereastra printe l pierde; toate intrrile de la tastatur
sunt direcionate ctre control, nu ctre fereastra printe. Totui, controalele de tip fereastr descendent
rspund numai la apsarea barei de spaiu, care funcioneaz n acest caz ca i butonul mouse- ului.
Situaia prezint o problem serioas: programul a pierdut controlul asupra tastaturii. Haidei s vedem
ce putem s facem n acest caz.
Aa cum am discutat n Capitolul 5, atunci cnd sistemul de operare Windows mut cursorul de
intrare de la o fereastr (cum ar fi fereastra printe) la o alt fereastr (cum ar fi controlul de tip fereastr
descendent), trimite mai nti un mesaj WM_KILLFOCUS ctre fereastra care pierde cursorul de intrare.
Parametrul wParam al mesajului este variabila handle a ferestrei care primete cursorul de intrare.
Windows trimite apoi un mesaj WM_SETFOCUS ctre fereastra care primete cursorul de intrare.
Parametrul wParam al mesajului este variabila de manipulare a ferestrei care pierde cursorul de intrare. (n
ambele cazuri, wParam poate avea valoarea NULL, ceea ce arat c nici o fereastr nu primete sau nu
pierde cursorul de intrare.)
O fereastr printe poate mpiedica un control de tip fereastr descendent s primeasc cursorul de
intrare prelucrnd mesajul WM_KILLFOCUS. S presupunem c matricea hwndCmd conine variabilele
handle ale tuturor ferestrelor descendent. (Aceste variabile au fost salvate n matrice n timpul apelrii
funciei CreateWindow pentru crearea ferestrelor descendent.) NUM este numrul ferestrelor
descendent.
case WM_KILLFOCUS :

for (i = 0 ; i < NUM ; 1++)


if (hwndChild[i] == (HWND) wParam
SetFocus (hwnd) ;
break ;
return 0 ;

n aceast secven de cod, atunci cnd fereastra printe este avertizat c urmeaz s piard cursorul
de intrare n favoarea uneia dintre ferestrele descendent, apeleaz funcia SetFocus ca s rectige
cursorul de intrare.
Iat o cale mai simpl (dar mai puin evident) de a face acelai lucru:
case WM_KILLFOCUS ;
~ if (hwnd == GetParent ((HW ND) wParam))
SetFocus (hwnd) ;
return 0 ;

25.

Ferestre child. Butoane visibile i accesibile. .

Butoane vizibile i butoane activate


Pentru recepionarea intrrilor de la mouse i de la tastatur, o fereastr descendent trebuie s fie
vizibil (afiat), dar i activat. Atunci cnd o fereastr este vizibil, dar nu este activat, textul acesteia
este afiat cu gri, n loc de negru.
19

Dac nu includei parametrul WS_VISIBLE n clasa ferestrei la crearea ferestrei descendent, aceasta
nu va fi afiat pn cnd nu apelai funcia ShowWindow:
ShowWindow (hwndChild, SW_SHOWNORMAL) ;

Dac includei parametrul WS_VISIBLE n clasa ferestrei, nu este nevoie s apelai funcia
ShowWindow. Totui, prin apelarea funciei ShowWindow putei s mascai o fereastr descendent
afiat:
ShowWindow (hwndChild, SW_HIDE) ;

Putei s determinai dac o fereastr descendent este afiat:


IsWindowVisible (hwndChild) ;

De asemenea, putei s activai sau s dezactivai o fereastr descendent. n mod prestabilit,


ferestrele descendent sunt activate. Iat cum putei s le dezactivai:
EnableWindow (hwndChild, FALSE) ;

Pentru controalele de tip buton, aceast aciune are ca efect afiarea cu gri a textului din buton. Butonul
nu mai rspunde la intrrile de la mouse sau de la tastatur. Aceasta este cea mai bun metod de a
indica faptul c opiunea reprezentat de un anumit buton nu este disponibil.
Putei s reactivai o fereastr descendent prin urmtorul apel:
EnableWindow (hwndChild, TRUE) ;

Putei s determinai dac o fereastr descendent este activ sau nu prin urmtorul apel:
IsWindowEnabled (hwndChild) ;

26.

Ferestre child. Check box. .

Casetele de validare sunt dreptunghiuri etichetate cu un text; de obicei, textul apare n partea dreapt a
casetei de validare. (Dac la crearea butonului folosii stilul BS_LEFTTEXT, textul apare n stnga
casetei de validare.) De obicei, casetele de validare sunt incluse n aplicaii pentru a permite
utilizatorilor s selecteze diferite opiuni. Casetele de validare funcioneaz ca un comutator: executarea
unui clic ntr-o caset de validare determin apariia unui marcaj de validare; un al doilea clic face ca
marcajul de validare s dispar.
Cele mai cunoscute stiluri de casete de validare sunt BS_CHECKBOX i BS_AUTOCHECKBOX.
Atunci cnd folosii stilul BS_CHECKBOX, v revine dumneavoastr sarcina de aplicare a marcajului
de validare, prin trimiterea unui mesaj BS_SETCHECK. Parametrul wParam trebuie s aib valoarea 1
pentru afiarea marcajului de validare i valoarea 0 pentru tergerea acestuia. Putei s folosii urmtoarea
secven de cod pentru inversarea marcajului de validare la prelucrarea mesajului WM_COMMAND
primit de la control:
SendMessage ((HWND) 1Param, BM_SETCHECK, (WPARAM) SendMessage ((HWND) lParam, BM_GETCHECK, 0, 0), 0) ;

Remarcai folosirea operatorului .' naintea celui de-al doilea apel al funciei SendMessage. Valoarea
lParam este variabila handle a ferestrei descendent, transmis ctre procedura ferestrei prin mesajul
WM_COMMAND. Dac ulterior dorii s aflai starea butonului, trimitei un nou mesaj
BM_GETCHECK. Sau putei s stocai starea curent a casetei de validare ntr-o variabil static din
procedura ferestrei.
Putei s iniializai o caset de validare de tip BS_CHECKBOX cu un X, trimind mesajul
BM_SETCHECK:
SendMessage (hwndButton, BM_SETCHECK, 1, 0) ;

n cazul folosirii stilului BS_AUTOCHECKBOX, controlul este cel care actualizeaz afiarea
marcajului de validare. Procedura ferestrei printe poate s ignore mesajele WM_COMMAND.
Atunci cnd vrei s aflai starea butonului, trimitei ctre acesta mesajul BM_GETCHECK:
iCheck = (int) SendMessage (hwndButton, BM_GETCHECK, 0, 0) ;

iCheck are valoarea TRUE (sau o valoare diferit de 0) dac butonul este validat i valoarea FALSE
(sau 0) n caz contrar.
20

Celelalte dou stiluri de casete de validare sunt BS_3STATE i BS_AUTO3STATE. Aa cum indic i
numele lor, aceste stiluri permit afiarea unei stri tere - culoarea gri din caseta de validare - n cazul
n care trimitei ctre control un mesaj WM_SETCHECK cu parametrul wParam egal cu 2. Culoarea
gri indic utilizatorului c opiunea respectiv este nedeterminat sau irelevant. n acest caz, caseta nu
poate fi validat - cu alte cuvinte, este dezactivat. Totui, caseta de validare continu s trimit
mesaje ctre fereastra printe atunci cnd se execut clic. Vom descrie puin mai trziu metode mai
bune de dezactivare a unei casete de validare.
Caseta de validare este aliniat la partea stng a dreptunghiului i este centrat ntre marginile de
sus i de jos ale acestuia, conform dimensiunilor specificate la apelarea funciei CreateWindow.
Executarea unui clic oriunde n cadrul dreptunghiului determin trimiterea unui mesaj
WM_COMMAND ctre fereastra printe, nlimea minim a casetei de validare este egal cu nlimea
unui caracter. Limea minim este egal cu numrul de caractere din text, plus dou.
27.

Ferestre child. Clasa barelor de derulare. .

Spre deosebire de butoane ,barele de derulare nu trimit mesaje WM_COMMAND ctre fereastra
printe, n schimb, trimit mesaje WM_VSCROLL i WM_HSCROLL, ca i barele de derulare ale
ferestrelor. Atunci cnd prelucrai mesajele primite de la barele de derulare, putei s facei diferena
ntre barele de control ale ferestrelor i controalele de tip bare de derulare cu ajutorul parametrului
IParatn. Acesta va fi 0 pentru barele de derulare ale ferestrelor sau o variabil handle n cazul
controalelor de tip bar de derulare. Cele dou cuvinte care formeaz parametrul wParam au aceeai
semnificaie att pentru barele de derulare ale ferestrelor, ct i pentru controalele de tip bar de
derulare.
Dei barele de derulare ale ferestrelor au lime fix, n cazul controalelor de tip bare de derulare
Windows folosete dimensiunile dreptunghiului specificate la apelarea funciei CreateWindow sau a
funciei MoveWindow. Putei s creai bare de derulare lungi i subiri sau bare de derulare scurte i
late.
Dac vrei s creai controale de tip bare de derulare cu aceleai dimensiuni ca i barele de derulare
ale ferestrelor, putei s folosii funcia GetSystemMetrics ca s obinei nlimea unei bare de
derulare orizontale:
GetSystemMetrics (SH_CYHSCROLL) ;

sau limea unei bare de derulare verticale:


GetSystemMetrics (SM_CXVSCROLL) ;

(Conform documentaiei, identificatorii SBS_LEFTALIGN, SBS_RIGHTALIGN, SBS_TOPALIGN i


SBS_BOTTOMALIGN pentru barele de derulare ale ferestrelor stabilesc dimensiuni standard pentru
barele de derulare. Totui, acest lucru este valabil numai pentru casetele de dialog.)
Putei s stabilii intervalele i poziia unui control de tip bar de derulare cu aceleai apeluri pe
care le folosii i pentru barele de derulare ale ferestrelor:
SetScrollRange (hwndScroll , SB CTL, iMin, iMax, bRedraw) ; SetScrollPos (hwndScroll , SB CTL, iPos, bRedraw) ;
SetScrollInfo (hwndScroll , SB_CTL, &si, bRedraw) ;

Diferena const n faptul c barele de derulare ale ferestrelor folosesc o variabil ctre fereastra
principal ca prim parametru i SB_VERT sau SB_HORZ ca al doilea parametru.
Destul de surprinztor, culoarea de sistem COLOR_SCROLLBAR nu mai este folosit pentru
controalele de tip bar de derulare. Butoanele de la captul barei i caseta de derulare de pe bar
folosesc culorile COLOR_BTNFACE, COLOR_BTN-HIGHUGHT, COLOR_BTNSHADOW,
COLOR_BTNTEXT (pentru sgei) i COLOR J3TNLIGHT. Spaiul mai mare dintre cele' dou
butoane de la capete este o combinaie a culorilor COLOR_BTNFACE i COLOR_BTNHIGHLIGHT.
Dac interceptai mesajul WM_CTLCOLORSCROLLBAR, putei s returnai o pensul pentru
suprascrierea culorilor folosite pentru aceast zon. Haidei s facem acest lucru.
28.

Ferestre child. Clasa de redactare. .

21

Clasa de editare este, din unele puncte de vedere, cea mai simpla clasa de fereastra predefinita, iar
din alte puncte de vedere este cea mai complicate. Atunci cand creati o fereastra descendent folosind
numele de clasa ,,edit", definiti un dreptunghi pe baza coordonatelor x si y si a parametrilorinaltime si
latime - specificati la apelarea functiei CreateWindow. Acest dreptunghi contine text care poate fi editat.
Atunci cand fereastra descendent detine cursorul de intrare, puteti sa introduced text de la tastatura,
sa deplasati cursorul, sa selectati portiuni din text cu ajutorul mouse-ului sau al tastei Shift si al
tastelor de deplasare, sa stergeti textul selectat si sa 11 pastrati in memoria temporara (Clipboard) apasand
tastele Ctrl+X, sa il copiati cu ajutorul tastelor Ctrl+C sau sa inserati in controlul de editare textul din
memoria temporara apasand tastele Ctrl+V.
Unul dintre cele mai simple moduri de folosire a controalelor de editare este crearea rubricilor de
intrare cu o singura linie. Dar controalele de editare nu sunt limitate la o singura .
29.

Ferestre child. Clasa static. .

Putei s creai un control static de tip fereastr descendent folosind clasa static" n
funcia CreateWindow. Aceste ferestre sunt un tip destul de inofensiv" - nu accept
intrri de la mouse sau de la tastatur i nu trimit mesaje WM_COMMAND ctre
fereastra printe. (Atunci cnd executai clic pe o fereastr descendent static, aceasta
intercepteaz mesajul WM_NCHITTEST i returneaz o valoare HTTRANSPARENT
ctre Windows. Ca rezultat, Windows trimite acelai mesaj WM_NCHITTEST ctre
fereastra aflat dedesubt, care de obicei este fereastra printe. n general, fereastra
printe transmite mesajul primit ctre procedura DefWindowProc, unde acesta este
convertit ntr-un mesaj de mouse din zona client.)
Primele ase stiluri de ferestre descendent statice nu fac dect s deseneze un
dreptunghi sau un cadru n zona client a ferestrei descendent. n tabelul urmtor
stilurile statice RECT" (coloana din stnga) sunt dreptunghiuri pline, iar cele trei
stiluri FRAME" (coloana din dreapta) sunt chenare dreptunghiulare necolorate:
SS_BLACKRECT SS_BLACKFRAME SS_GRAYRECT SS_GRAYFRAME
SS_WHITERECT SS_WHITEFRAME
BLACK", GRAY" i WHITE" nu sunt, de fapt, culorile dreptunghiurilor res pective. Culorile reale folosite se bazeaz pe culori de sistem, aa cum se poate vedea n
tabelul urmtor:
Control static
Culoare de sistem
BLACK
COLOR_3DDKSHADOW
GRAY
COLOR_BTNSHADOW
WHITE
COLOR_BTNHIGHLIGHT
Parametrul pentru textul ferestrei din apelul funciei CreateWindow este ignorat n
cazul acestor stiluri de fereastr. Colul din stnga-sus al dreptunghiului ncepe la
poziia indicat de parametrii x i y, relativ la fereastra printe. (Putei s folosii i
stilurile SS_ETCHEDHORZ, SS_BTCHEDVERT sau SS_ETCHEDFRAME ca s creai
chenare umbrite cu culorile gray" i white".)
Clasele statice includ i trei stiluri de text: SS_LEFT, SS_RIGHT i SS_CENTER.
Acestea creeaz rubrici de text aliniate la stnga, la dreapta sau centrate. Textul este
furnizat ca parametru al funciei CreateWindow i poate fi modificat prin apelarea
funciei SetWindowText. Atunci cnd procedura ferestrei pentru controalele statice
afieaz acest text, folosete funcia DrawText cu parametrii DT_WORDBREAK,
DT_NOCLIP i DT_EXPANDTABS. Textul este ncadrat n dreptunghiul ferestrei
descendent.
Fondul ferestrelor descendent de tip text este, n mod normal, COLOR_BTNFACE,
iar textul este scris cu culoarea dat de COLOR_WINDOWTEXT. Putei s
interceptai mesajele WM_CTLCOLORSTATIC dac dorii s modificai culoarea
22

textului prin apelarea funciei SetTextColor sau a fondului prin apelarea funciei
SetBkColor i prin returnarea unei variabile handle a pensulei pentru fond. Acest lucru
va fi ilustrat n programul COLORS1, prezentat puin mai jos.
In sfrit, clasa static" include stilurile de fereastr SS_CON i SS_USERITEM. Acestea nu au ns
nici o semnificaie atunci cnd sunt folosite pe post de controale de tip fereastr descendent. Le vom
prezenta pe larg atunci cnd vom discuta despre casetele de dialog.
30.

Ferestre child. Coduri de ntiinare. .

Codurile de Instiintare sunt prezentate mai jos:


EN_SETFOCUS Controlul de editare a obfinut cursorul de intrare
EN_KILLFOCUS Controlul de editare a pierdut cursorul de intrare
EN_CHANGE
Confinutul controlului de editare se va modifica
EN_UPDATE
Confinutul controlului de editare s-a modificat
EN_ERRSPACE Controlul de editare nu mai are spafiu
EN_MAXTEXT Controlul de editare nu mai are spajiu pentru inserare
EN_HSCROLL
S-a executat clic pe bara de derulare orizontala a controlului de editare
EN_VSCROLL
S-a executat clic pe bara de derulare verticala a controlului de editare
Controalele de editare stocheaza textul in memoria programului ferestrei pa rinte. Asa cum am
menjionat mai sus, confinutul unui control de editare este limitat la 32 kilooctefi.
31.

Ferestre child. Colorarea barelor de derulare i a textului static. .


In programul COLORS1, interiorul celor trei bare de derulare si textul din cele sase rubrici de text
sunt colorate cu rosu, verde si albastru. Colorarea barelor de derulare se realizeaza prin prelucrarea
mesajelor WM_CTLCOLORSCROLLBAR.
In procedura WndProc definim o matrice statica ce contine trei variabile handle ale pensulelor:

static HBRUSH hBrush[3] ;


Cele trei pensule sunt create in timpul prelucrarii mesajului WM_CREATE:
for (i = 0 ; i < 3 ; i++)
hBrush[i] CreateSolidBrush (crPrim[i]) ;

unde matricea crPrim contine valorile RGB pentru cele trei culori primare. In timpul prelucrarii
mesajului WMlCTLCOLORSCROLLBAR, procedura ferestrei returneaza una dintre cele trei pensule:
case WM_CHX0LORSCR0LLBAR : i = GetWindowLong ((HWND) lParam, GWWJD) ; return (LR ESULT) hBrush[i] ;

Aceste pensule trebuie distruse in timpul prelucrarii mesajului WM_DESTROY:


for (i = 0 ; i < 3 ; DeleteObject (hBrush[i++])) ;

Textul din rubricile de text static este colorat mtr-un mod similar prin prelucrarea mesajului
WM_CTLCOLORSTATIC si prin apelarea functiei SetTextColor. Fondul textului este stabilit cu ajutorul
functiei SetBkColor, folosind culoarea de sistem COLOR_BTNHIGHLIGHT. In acest fel fondul
textului are aceeasi culoare ca si dreptunghiul static din spatele barelor de derulare si al textului. In
cazul controalelor de tip text static, culoarea de fond se aplica numai pentru dreptunghiul din spatele
caracterelor care formeaza textul, nu pentru tot spatiul ocupat de fereastra controlului. Pentru aceasta,
procedura ferestrei trebuie sa returneze o variabila handle la o pensula de culoarea
COLOR_BTNHIGHLIGHT. Aceasta pensula se numeste hBrushStatic, este creata in timpul prelucrarii
mesajului WM_CREATE si este distrusa in timpul prelucrarii mesajului WM_DESTROY.
Prin crearea unei pensule bazate pe culoarea COLOR_BTNHIGHLIGHT In timpul prelucrarii
mesajului WM_CREATE si folosirea acesteia pe toata durata programului, ne-am expus la aparitia unei
mici probleme. Daca in timpul rularii programului culoarea COLOR_BTNHIGHLIGHT este
modificata, culoarea dreptunghiului static se va modifica, la fel si culoarea de fond a textului, dar culoarea
de fond a controalelor de tip text va ramane tot vechea culoare COLOR_BTNHIGHLIGHT.
32.

Ferestre child. Colorarea fondului. .


23

Atunci cand defineste clasa de fereastra, programul COLORS1 stabileste pentru fondul zonei client o
pensula neagra plina:
wndclass.hbrBackground CreateSolidBrush (OL) ;

Atunci cand modificati valorile barelor de derulare, programul trebuie sa creeze o noua pensula si sa
puna variabila handle a acesteia in structura de clasa a ferestrei. Asa cum avem posibilitatea sa
obtinem si sa stabilim procedura barelor de derulare cu ajutorul funcfiilor GetWindowLong si
SetWindowLong, putem sa obtinem si sa stabilim si variabila handle a acestei pensule cu ajutorul
functiilor GetClassWord si SetClassWord.
Puteti sa aveti o noua pensula, sa inserati variabila handle a acesteia in structura de clasa a ferestrei,
apoi sa stergeti vechea pensula:
DeleteObject ((HBRUSH)
SetClassLong (hwnd, GCL HBRBACKGROUND, (LONG)
CreateSolidBrush TRGB (color[0], color[l], color[2])))) ;

La urmatoarea recolorare a fondului ferestrei, Windows va folosi noua pensula. Pentru a forja
stergerea fondului, invalidam partea dreapta a zonei client:
InvalidateRect (hwnd, ircColor, TRUE) ;

Valoarea TRUE (diferita de 0) folosita ca eel de-al treilea parametru indica faptul ca dorim ca fondul
sa fie sters Inainte de a fi redesenat.
Functia InvalidateRect forteaza sistemul de operare Windows sa puna un mesaj WM_PAINT in
coada de mesaje a ferestrei. Deoarece are prioritate scazuta, mesajul WMJPAINT nu va fi prelucrat
imediat daca inch mai miscati caseta de pe bara de derulare cu ajutorul mouse-ului sau al tastaturii.
Daca vreti ca fereastra sa fie actualizata imediat dupa modificarea culorii, puteti sa adaugati
instructiunea:

UpdateWindow (hwnd) ;
dupa apelarea functiei InvalidateRect. Dar aceasta instructiune va incetini prelucrarea mesajelor de la
mouse sau de la tastatura.
Functia WndProc din programul COLORS1 nu prelucreaza mesajele WM_PAINT, ci le trimite
functiei DefWindowProc. Codul prestabilit de prelucrare a mesajului WM_PAINT consta numai in
apelarea functiilor BeginPaint si EndPaint pentru validarea ferestrei. Deoarece am specificat in apelul
functiei InvalidateRect ca fondul ferestrei trebuie sters, functia BeginPaint forfeaza sistemul de
operare Windows sS genereze mesajul WM_ERASEBKGND (stergere fond). Functia WndProc ignora
acest mesaj. Mesajul este prelucrat de Windows, care sterge fondul zonei client, folosind pensula
specificata in clasa ferestrei.
Intotdeauna este bine sa faceti curatenie inainte de terminarea programului, asa c in timpul
prelucrarii mesajului WM_DESTROY este apelata din nou funcia DeleteObject:
DeleteObject ((HBRUSH)
SetClassLong (hwnd, GCL_HBRBACKGROUND,
(LONG) GetStockObject (WHITE_BRUSH))) ;

33.

Ferestre child. Culori de sistem. .

Windows pstreaz 25 de culori de sistem pentru afiarea diferitelor pri ale ecra nului. Putei s
obinei i s stabilii aceste culori cu ajutorul funciilor GetSysColor i SetSysColors. Identificatorii
definii n fiierele antet din Windows specific culorile de sistem. Stabilirea unei culori de sistem cu
ajutorul funciei SetSysColors afecteaz culoarea respectiv numai pe durata sesiunii Windows curente.
Putei s schimbai o parte dintre culorile de sistem folosind seciunea Display a Panoului de control
din Windows (Control Panel) sau modificnd seciunea [colors] din fiierul WIN.INI. Seciunea
[colors] folosete pentru cele 25 de culori de sistem cuvinte cheie (altele dect identificatorii folosii de
funciile GetSysColor i SetSysColors) urmai de valori pentru culorile rou, verde i albastru. Aceste
valori sunt cuprinse n intervalul 0 - 255. Tabelul urmtor prezint modul n care sunt identificate cele 25
de culori de sistem, cu ajutorul identificatorilor folosii de funciile GetSysColor i SetSysColors i al
cuvintelor cheie folosite n fiierul WIN.INI. Tabelul este ordonat cresctor, n funcie de valoarea
constantelor COLOR_ (de la 0 la 24):
24

GetSysColor i SetSysColors

WIN.INI

COLOR_SCROLLBAR
COLOR_BACKGROUND
COLOR_ACTIVECAPTION
COLOR_NACTIVECAPTION
COLOR_MENU
COLOR_WINDOW
COLOR_WINDOWFRAME
COLOR_MENUTEXT
COLOR_WINDOWTEXT
COLOR_CAPTIONTEXT
COLOR_ACTIVEBORDER
COLOR_NACTIVEBORDER
COLOR_APPWORKSPACE
COLOR_HIGHLIGHT
COLOR_HIGHLIGHTTEXT
COLOR_BTNFACE
COLOR_BTNSHADOW
COLOR_GRAYTEXT
COLOR_BTNTEXT
COLOR_NACTIVECAPTIONTEXT
COLOR_BTNHIGHLIGHT
COLOR_3DDKSHADOW
COLOR_3DLIGHT
COLOR_NFOTEXT
COLOR_INFOBK

Scrollbar
Background
ActiveTitle
InactiveTitle
Menu
Window
WindowFrame
MenuText
WindowText
TitleText
ActiveBorder
InactiveBorder
AppWorkspace
Hilight
HilightText
ButtonFace
ButtonShadow
GrayText
ButtonText
InactiveTitleText
ButtonHilight
ButtonDkShadow
ButtonLight
InfoText
InfoWindow

Valorile prestabilite pentru aceste culori sunt furnizate de driverul de afiare. Sistemul de operare
Windows folosete valorile prestabilite, dac acestea nu sunt suprascrise de valorile din seciunea
[colors] a fiierului WIN.INI, care poate fi modificat din Panoul de control.
34.

Ferestre child. Interfaa tastaturii. . ,

Interfaa automatizat cu tastatura


Controalele de tip bar de derulare pot interpreta i apsrile de taste, dar numai atunci cnd dein
cursorul de intrare. Tabelul urmtor prezint modul n care apsarea tastelor de deplasare este
transformat n mesaje:

Tasta de
deplasare
Valoarea
wParam din
mesajul barei
de derulare

25

Home
,
SB_TOP
End
SB_BOTTOM
Page Up
SB_PAGEUP
Page Down
SB_PAGEDOWN
Left sau Up
SB_LINEUP
Right sau Down
SB_LINEDOWN
De fapt, mesajele SB_TOP i SB_BOTTOM nu pot fi generate dect prin folosirea tastaturii. Dac dorii ca un
control de tip bar de derulare s obin cursorul de intrare atunci cnd se execut clic pe aceasta, trebuie s
includei identificatorul WS_TAB-STOP n parametrul de stil al ferestrei la apelarea funciei CreateWindow.
Atunci cnd o bar de derulare deine cursorul de intrare, pe caseta de derulare de pe ea este afiat un bloc gri care
clipete.
Totui, pentru a furniza barelor de derulare o interfa complet cu tastatura, este necesar ceva mai mult
munc. Mai nti, procedura WndProc trebuie s acorde explicit barei de derulare cursorul de intrare. Acest
lucru se face prin prelucrarea mesajului WM_SETFOCUS, pe care fereastra printe l primete atunci cnd
primete cursorul de intrare. WndProc cedeaz pur i simplu cursorul de intrare uneia dintre barele de derulare:

SetFocus (hwndScrol[iFocus]) ;
35.

Ferestre child. Introducerea unei proceduri de fereastr noi. .

Dei putei s creai propriile controale de tip fereastr descendent, putei s beneficiai i de avantajele
oferite de un set de clase de fereastr (i proceduri specifice) predefinite, clase pe care programele pot s le foloseasc
pentru crearea unor controale de tip fereastr descendent standard, pe care cu siguran le-ai mai vzut i n alte
programe pentru Windows. Aceste controale apar sub forma butoanelor, casetelor de validare, casetelor de
editare, casetelor list, casetelor combinate, a irurilor de caractere i a barelor de derulare. De exemplu, dac
dorii s punei un buton cu eticheta Recalculare" ntr-un col al unui program de calcul tabelar, putei s l creai
printr-un simplu apel al procedurii CreateWindow. Nu trebuie s v facei griji n privina logicii de interpretare
a clicurilor de mouse, a redesenrii butonului sau a modului n care butonul se mic atunci cnd este apsat. Tot
ce trebuie s facei este s interceptai mesajul WM_COMMAND - acesta este modul n care butonul
informeaz procedura ferestrei despre declanarea unui eveniment.
36.

Ferestre child. Mesajul WM_CTLCOLORBT. . WM_CTLCOLORBT

O abordare mai potrivit (din nou, teoretic) este prelucrarea mesajului WM_CTLCOLORBTN. Acesta
este un mesaj pe care controalele de tip buton l trimit ctre procedura ferestrei printe atunci cnd fereastra
descendent este pe cale de a executa o redesenare. Fereastra printe poate s foloseasc aceast ocazie ca s
modifice culorile pe care procedura ferestrei descendent urmeaz s le foloseasc pentru desenare. (In
versiunile pe 16 bii ale sistemului de operare Windows, un mesaj numit WM_CTLCOLOR era folosit pentru
toate controalele. Acesta a fost nlocuit cu mesaje separate pentru fiecare tip standard de control.)
Atunci cnd procedura printe recepioneaz mesajul WM_CTLCOLORBTN, parametrul wParam conine
variabila handle a contextului de dispozitiv al butonului, iar IParatn este variabila handle a ferestrei butonului.
Atunci cnd fereastra printe primete acest mesaj, controlul de tip buton a obinut deja contextul de
dispozitiv. n timpul prelucrrii mesajului WM_CTLCOLORBTN:
Stabilii (opional) o culoare de text cu ajutorul funciei SetTextColor.
Stabilii (opional) o culoare de fond cu ajutorul funciei SetBkColor.
Returnai ctre fereastra descendent o variabil de manipulare a pensulei
cu care se va desena.
Teoretic, fereastra descendent folosete pensula respectiv pentru colorarea fondului. Este sarcina
dumneavoastr s distrugei pensula atunci cnd aceasta nu mai este necesar.
Totui, n legtur cu mesajul WM_CTLCOLORBTN este o problem: acesta nu este trimis dect de
butoanele de apsare i de butoanele desenate de proprietar; de asemenea, numai butoanele desenate de

proprietar rspund la prelucrarea fcut mesajului de ctre fereastra printe, folosind pensula trimis pentru
colorarea fondului. Oricum, acest lucru este inutil, deoarece fereastra printe este rspunztoare de desenarea
acestor butoane.
37.

Ferestre child. Radio buttons. .

Butoanele radio seamn cu casetele de validare, cu excepia faptului c au form circular, nu


dreptunghiular. Un punct mare n interiorul cercului indic butonul radio care a fost selectat. Stilurile de
fereastr pentru butoanele radio sunt BS_RADIOBUTTON i BS_AUTORADIOBUTTON, dar cel de-al doilea
este folosit numai n casetele de dialog. n casetele de dialog, grupurile de butoane radio sunt folosite de
obicei pentru indicarea opiunilor care se exclud reciproc. Spre deosebire de casetele de validare, butoanele
radio nu funcioneaz precum comutatoarele - aceasta nseamn c atunci cnd executai un al doilea clic pe
un buton radio, starea acestuia rmne neschimbat.
Atunci cnd recepionai un mesaj WM_COMMAND de la un buton radio, trebuie s afiai marcajul de
validare al acestuia, trimind mesajul BM_SETCHECK cu parametrul wParam egal cu 1:
SendMessage (hwndButton, BM_SETCHECK, 1, 0) ;

Pentru toate celelalte butoane radio din acelai grup putei s tergei marcajul de validare trimindu-le
mesajul BM_SETCHECK cu parametrul wParam egal cu 0:
SendMessage (hwndButton, BM_SETCHECK, 0, 0) ;

38.

Ferestre child. Stilurile clasa de redactare. .

Stilurile clasei edit


Putem crea un control de editare folosind clasa de ferestre ,,edit" la apelarea funcjiei CreateWindow - stilul
ferestrei este WS_CHILD, plus cateva optiuni. Ca si in cazul controalelor statice de tip fereastra descendent,
textul din controalele de editare poate fi aliniat la dreapta, aliniat la stanga sau centrat. Modul de aliniere este
specificat prin stilurile de fereastra ES_LEFT, ES_RIGHT si ES_CENTER.
In mod prestabilit, un control de editare are o singura linie. Putefi sa creafi controale de editare
multilinie folosind stilul de fereastra ES_MULTILINE. In cazul unui control de editare cu o singura linie
puteti, In mod normal, sa introduce text numai pana la sfarsitul dreptunghiului care limiteaza controlul de
editare. Pentru crearea unui control care face automat derularea orizontala a textului, folosifi stilul
ES_AUTOHSCROLL. In cazul controalelor de derulare multilinie, textul este trecut automat pe o linie noua,
exceptand situatiile in care folositi stilul de fereastra ES_AUTOHSCROLL, caz in care trebuie sa apasafi
tasta Enter ca sa treceti la o linie noua. De asemenea, puteti sa included posibilitatea de derulare verticals
automata a textului intr-un control de editare multilinie, folosind stilul ES_AUTOVSCROLL.
Atunci cand include^ intr-un control de editare multilinie stiluri de derulare a textului, puteti sa adaugafi
si bare de derulare. Acest lucru se face cu ajutorul acelorasi identificatori ca si in cazul ferestrelor principale:
WS_HSCROLL si WS_VSCROLL.'
In mod prestabilit, controalele de editare nu sunt incadrate de un chenar. Putefi sa adaugafi un chenar
folosind stilul WS_BORDER.
Atunci cand selectafi un bloc de text intr-un control de editare, textul respectiv este afisat in mod video
invers. Totusi, atunci cand controlul pierde cursorul de intrare, textul selectat nu mai este marcat. Daca vreti
ca textul selectat sa fie marcat chiar si dupa ce controlul nu mai define cursorul de intrare, puteti sa folosifi
stilul ES_NO-HIDESEL.
Atunci cand programul POPAD1 creeaza controlul de editare, stilul folosit la apelarea funcfiei
CreateWindow este specificat astfel:

WS CHILD ! WSJISIBLE | WS_HSCROLL | WS VSCROLL | WS BORDER ! ES_LEFT | ES HULTILINE~|


ES~AUTOHSCROLL | ES_AUTOVSCROLL
In POPPAD1, dimensiunile controlului de editare sunt stabilite ulterior, la apelarea funcfiei MoveWindow,
dupa ce funcfia WndProc primeste mesajul WMJ5IZE. Dimen-siunea controlului de editare este stability initial
la dimensiunile ferestrei principale:
MoveWindow (hwndEdit, 0, 0, LOWORD (IParam),

HIWORD (IParam), TRUE) ;

Pentru controalele de editare pe o singura linie, inalfimea controlului trebuie sa corespunda inalfimii unui
caracter. In cazul in care controlul de editare are un chenar
(si majoritatea au), folosifi ca dimensiune de 1,5 ori inalfimea unui caracter (indusiv spatiul extern).
39.
40.

Ferestre child. Utilizarea ferestrelor de redactare de control. .



Ferestre. Culoarea butoanelor. .

O abordare mai potrivit (din nou, teoretic) este prelucrarea mesajului WM_CTLCOLORBTN. Acesta
este un mesaj pe care controalele de tip buton l trimit ctre procedura ferestrei printe atunci cnd fereastra
descendent este pe cale de a executa o redesenare. Fereastra printe poate s foloseasc aceast ocazie ca s
modifice culorile pe care procedura ferestrei descendent urmeaz s le foloseasc pentru desenare. (In
versiunile pe 16 bii ale sistemului de operare Windows, un mesaj numit WM_CTLCOLOR era folosit pentru
toate controalele. Acesta a fost nlocuit cu mesaje separate pentru fiecare tip standard de control.)
Atunci cnd procedura printe recepioneaz mesajul WM_CTLCOLORBTN, parametrul wParam conine
variabila handle a contextului de dispozitiv al butonului, iar IParatn este variabila handle a ferestrei butonului.
Atunci cnd fereastra printe primete acest mesaj, controlul de tip buton a obinut deja contextul de
dispozitiv. n timpul prelucrrii mesajului WM_CTLCOLORBTN:
Stabilii (opional) o culoare de text cu ajutorul funciei SetTextColor.
Stabilii (opional) o culoare de fond cu ajutorul funciei SetBkColor.
Returnai ctre fereastra descendent o variabil de manipulare a pensulei
cu care se va desena.
41.
42.

Ferestrele child de control.


Folosirea penielor de stoc. Crearea, selectarea i tergerea penielor. Funciile CreatePen, CreatePenIndirect,

Crearea, selectarea i tergerea penielor

Dei folosirea penielor definite ca obiecte de stoc este foarte convenabil, avei la dispoziie doar
un numr limitat de opiuni: o peni neagr, pentru linie continu, una alb pentru linie continu sau
una care nu deseneaz nimic. Dac dorii ceva diferit, trebuie s creai propriile dumneavoastr penie.
Iat procedura general: creai mai nti o peni logic" (logical pen) care este doar o descriere a unei
penie, folosind funciile CreatePen sau CreatePenIndirect. (De asemenea, putei s folosii i funcia
ExtCreatePen, despre care vom discuta atunci cnd vom ajunge la cile GDI.) Aceste funcii
returneaz o variabil handle a peniei logice. Selectai penia n contextul de dispozitiv apelnd funcia
SelectObject. Apoi putei s desenai linii cu penia selectat. La un moment dat nu poate fi selectat,
ntr-un context de dispozitiv, dect o peni. Dup ce tergei contextul de dispozitiv (sau dup ce
selectai o alt peni n contextul de dispozitiv) putei s tergei penia logic pe care ai creat-o
apelnd funcia DeleteObject. Dup ce facei acest lucru, variabila handle a peniei nu mai este valid.
O peni logic este un obiect GDI". Dumneavoastr creai i folosii penia, dar aceasta nu
aparine programului, ci modulului GDI. Penia este unul dintre cele ase obiecte GDI pe care putei s
le creai. Celelalte cinci sunt pensulele, imaginile bitmap, regiunile, fonturile i paletele. Exceptnd
paletele, toate celelalte obiecte pot fi selectate n contextul de dispozitiv folosind funcia SelectObject.
Pentru folosirea obiectelor GDI trebuie s respectai urmtoarele reguli:
La sfritul programului tergei toate obiectele GDI pe care le-ai creat.
Nu tergei obiectele GDI n timp ce sunt selectate ntr-un context de dispozitiv valid.
Nu tergei obiectele de stoc.
Chiar dac sunt nite reguli rezonabile, neplcerile pot exista. Voi prezenta cteva exemple ca s
nelegei cum funcioneaz aceste reguli i pentru a putea evita eventuale probleme.

Sintaxa generic a funciei CreatePen este:


hPen = CreatePen (iPenStyle, iWidth, rgbColor) ;

+Putei s creai o peni i cu ajutorul unei structuri de tip LOGPEN (logical pen"), apelnd
funcia CreatePenIndirect. Dac programul folosete un numr mai mare de penie diferite pe care Ie
iniializai n codul surs, aceast metod este mai eficient. Mai nti definii o variabil de tip
LOGPEN, cum ar fi logpen:
LOGPEN logpen ;

Aceast structur are trei membri: lopnStyle (UINT) este stilul peniei, lopn Width (POINT) este
grosimea peniei n uniti logice, iar lopnColor (COLORREF) este culoarea peniei. Membrul lopn
Width este o structur de tip POINT, dar Windows folosete numai membrul lopnWidth.x al acestei
structuri i ignor membrul lopnWidth.y. Apoi creai penia, transmind funciei CreatePenIndirect
adresa structurii logpen:
hPen = CreatePenIndirect (&logpen) ;

De asemenea, putei s obinei informaii despre o peni logic existent. Dac avei deja o
variabil handle a unei penie putei s copiai datele care definesc penia logic ntr-o structur de tip
LOGPEN folosind funcia GetObject:
GetObject (hPen, sizeof (LOGPEN), (LPVOID) &logpen) ;

Remarcai faptul c funciile CreatePen i CreatePenIndirect nu au nevoie de o variabil handle a


contextului de dispozitiv. Aceste funcii creeaz penie logice care nu au nici o legtur cu contextul de
dispozitiv pn cnd nu apelai funcia SelectObject. De exemplu, putei s folosii aceeai peni
logic pentru mai multe dispozitive, cum ar fi imprimanta i ecranul.
Iat o metod pentru crearea, selectarea i tergerea penielor. S presupunem c programul
folosete trei penie: una neagr cu grosimea de un pixel, una roie cu grosimea de trei pixeli i una
neagr cu linie punctat. Mai nti definii variabilele pentru stocarea variabilelor handle ale celor trei
stilouri:
static HPEN hPen1, hPen2, hPen3;

n timpul prelucrrii mesajului WM_CREATE, creai cele trei penie:


hPen1 = CreatePen (PS_SOLID, 1, 0);
hPen2 = CreatePen (PS_SOLID, 3, RGB (255, 0, 0));
hPen3 = CreatePen (PS_DOT, 0, 0);

n timpul prelucrrii mesajului WM_PAINT (sau n orice alt moment n care avei o variabil
handle valid a contextului de dispozitiv) putei s selectai oricare dintre aceste penie n contextul de
dispozitiv i s desenai:
SelectObject (hdc, hPen2) ;
[funcii de desenare a liniilor]
SelectObject (hdc, hPen1) ;
[alte funcii de desenare a liniilor]

n timpul prelucrrii mesajului WM_DESTROY putei s tergei cele trei penie create:
DeleteObject (hPen1) ;
DeleteObject (hPen2) ;
DeleteObject (hPen3) ;

Aceasta este metoda cea mai direct pentru crearea, selectarea i tergerea penielor, dar are
dezavantajul c peniele create ocup spaiu n memorie pe toat durata rulrii programului. O alt
soluie este s creai peniele necesare n timpul prelucrrii fiecrui mesaj WM_PAINT i s le tergei
dup apelarea funciei EndPaint. (Putei s le tergei i nainte de apelarea funciei EndPaint, dar
trebuie s avei grij s nu tergei penia curent selectat n contextul de dispozitiv.)
De asemenea, putei s creai peniele atunci cnd sunt necesare, combinnd funciile CreatePen i
SelectObject n aceeai instruciune:
SelectObject (hdc, CreatePen (PS_DASH, 0, RGB (255, 0, 0))) ;

Din acest moment, vei folosi o peni pentru linii ntrerupte de culoare roie. Dup ce terminai de
fcut desenele cu acest tip de linie, putei s tergei penia. Hopa! Cum putei s tergei penia dac
nu ai salvat variabila handle a acesteia? V amintii c funcia SelectObject returneaz variabila
handle a peniei selectate anterior n contextul de dispozitiv. Aa c putei s tergei penia selectnd n
contextul de dispozitiv penia de stoc BLACK_PEN i tergnd variabila handle returnat de funcia
SelectObject:
DeleteObject (SelectObject (hdc, GetStockObject (BLACK PEN))) ;

Exist i o alt metod. Atunci cnd selectai n contextul de dispozitiv o peni nou creat, salvai
variabila handle returnat de funcia SelectObject;
hPen = SelectObject (hdc, CreatePen (PS_DASH, 0, RGB (255, 0, 0))) ;

Ce este hPen? Dac aceasta este prima apelare a funciei SelectObject de la obinerea contextului
de dispozitiv, atunci hPen este variabila handle a obiectului de stoc BLACK_PEN. Putei acum s
selectai penia BLACK_PEN n contextul de dispozitiv i s o tergei pe cea creat (variabila handle
returnat la a doua apelare a funciei SelectObject) printr-o singur instruciune:
DeleteObject (SelectObject (hdc, hPen)) ;

43.

ExtCreatePen. Parametrii iPenStyle, iWidth, rgbColor. . ,


, . CreatePen, CreatePenIndirect, ExtCreatePen. 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. Figura 4-16 prezint stilul de linie produs de fiecare identificator.

Figura 4-16. Cele apte stiluri de penite.

Pentru stilurile PS_SOLID, PS_NULL i PS_INSIDEFRAME, parametrul iWidth reprezint


grosimea liniei. Dac iWidth are valoarea 0, liniile desenate de Windows vor avea grosimea de un
pixel. Liniile desenate cu peniele de stoc au grosimea de un pixel. Dac parametrul iWidth are o
valoare mai mare de 1, Windows va desena o linie continu.
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.
44.

Formatarea textului. Funcia wsprintf. Funcia GetSystemMetrics. .


wsprintf. GetSystemMetrics.

Fomatarea textului
Deoarece dimensiunile fontului sistem nu se modific n timpul unei sesiuni Windows, trebuie s
apelai funcia GetTextMetrics o singur dat dup lansarea n execuie a programului. Un loc potrivit
pentru acest apel este codul de prelucrare a mesajului WM_CREATE din procedura de fereastr.
Mesajul WM_CREATE este primul mesaj pe care l primete procedura de fereastr. Windows trimite
un mesaj WM_CREATE procedurii de fereastr atunci cnd apelai funcia CreateWindow din funcia
WinMain.
S presupunem c scriei un program Windows care afieaz mai multe linii de text una sub alta, n
zona client a ferestrei. Trebuie s obinei valorile pentru nlimea i limea caracterelor. n procedura
de fereastr putei s definii dou variabile n care s salvai limea medie (cxChar) i nlimea total
a caracterelor (cyChar):
static int cxChar, cyChar ;
Prefixul c adugat la numele variabilelor provine de la contor" i n combinaie cu x sau y se
refer la dimensiunea pe orizontal sau pe vertical a caracterelor. Aceste variabile sunt declarate ca
statice deoarece trebuie s fie valide atunci cnd procedura de fereastr prelucreaz alte mesaje (cum
ar fi WM_PAINT). Dac variabilele sunt declarate ca globale n alte funcii nu mai este necesar s fie
declarate statice. Iat codul de prelucrare a mesajului WM_CREATE:
case WH_CREATE:
hdc = GetDC (hwnd);
GetTextMetrics (hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC (hwnd, hdc);
return 0;
Dac nu vrei s folosii spaiul suplimentar extern pentru spaierea liniilor de text, putei s
utilizai instruciunea:
cyChar = tm.tmHeight;
Pentru afiarea mai multor linii de text aliniate la stnga, folosii valoarea cxChar pentru
parametrul care reprezint coordonata pe axa x n apelul funciei TextOut. Valoarea coordonatei pe axa
y la apelarea funciei TextOut este:
cyChar * (1 + i);
unde i reprezint numrul liniei, ncepnd de la 0.
Deseori este necesar s afiai att numere formatate, cat i iruri simple de caractere. Dac ai scris
programe DOS folosind funciile standard C de bibliotec, probabil ai folosit pentru formatarea
numerelor funcia printf. n Windows nu putei s folosii funcia printf, deoarece ea determin afiarea
la dispozitivul standard de ieire, acesta fiind un concept care n Windows nu are nici un sens.
n schimb, putei s folosii funcia sprintf. Funcia sprintf lucreaz la fel ca i funcia printf, cu
excepia faptului c irul de caractere formatat este stocat ntr-o matrice de caractere. Apoi putei
utiliza funcia TextOut pentru a scrie irul ce trebuie afiat. Funcia sprintf returneaz lungimea irului
de caractere, ceea ce este foarte convenabil - putei s transmitei valoarea returnat n locul
parametrului iLength din apelul funciei TextOut. Secvena de cod de mai jos prezint o combinaie
tipic a funciilor TextOut i sprintf:
int iLenght;
char szBuffer [40];
[alte Iinii de program]
iLenght = sprintf (szBuffer, "The sum of %d and %d is %d"), nA, nB, nA + nB);
TextOut (hdc, x, y, szBuffer, iLength);
Pentru operaiile simple de afiare precum cea de mai sus putei s renunai la definirea variabilei
iLength i s combinai cele dou instruciuni rmase ntr-una singur:
TextOut (hdc, x, y, szBuffer, sprintf (szBuffer, "The sum of %d and %d is %d", nA, nB,
nA + nB));
Nu arat prea frumos, dar funcioneaz.

Dac nu trebuie s afiai numere n virgul mobil, putei folosi funcia wsprintf n locul funciei
sprintf. Funcia wsprintf are aceeai sintax ca i funcia sprintf, dar este inclus n Windows, aa c nu
va mri dimensiunea fiierului executabil.
45.

Funcia GetDeviceCaps. Dimensiunea dispozitivului. Valorile HORZSIZE i VERTSIZE, HORZRES i


VERTRES, ASPECTX, ASPECTY i ASPECTXY, LOGPIXELSX i LOGPIXELSY.
GetDeviceCaps. . HORZSIZE VERTSIZE, HORZRES VERTRES,
ASPECTX, ASPECTY ASPECTXY, LOGPIXELSX LOGPIXELSY.

Un context de dispozitiv se refer, de obicei, la un dispozitiv fizic de ieire, cum ar fi un monitor


video sau o imprimant. Dac avei nevoie de anumite informaii despre acest dispozitiv, cum ar fi
dimensiunile ecranului (dimensiunile n pixeli i cele fizice) sau posibilitile de folosire a culorilor,
putei s le obinei prin apelarea funciei GetDeviceCaps (get device capabilities"):
iValue = GetDeviceCaps (hdc, iIndex) ;

Parametrul iIndex este unul dintre cei 28 de identificatori definii n fiierele antet din Windows.
De exemplu, dac iIndex are valoarea HORZRES funcia GetDeviceCaps returneaz limea
dispozitivului n pixeli; VERTRES returneaz nlimea dispozitivului n pixeli. Dac hdc este o
variabil handle a contextului de dispozitiv pentru un monitor video, informaiile obinute sunt aceleai
cu cele returnate de funcia GetSystemMetrics. Dac hdc este o variabil handle a contextului de
dispozitiv pentru o imprimant, funcia GetDeviceCaps returneaz nlimea i limea zonei pe care
imprimant o poate tipri.
Putei s folosii funcia GetDeviceCaps i ca s obinei informaii despre posibilitile unui
dispozitiv de prelucrare a anumitor tipuri de elemente grafice. Aceast posibilitate nu este important
pentru ecran, dar poate fi folosit n cazul imprimantelor. De exemplu, majoritatea plotterelor nu pot
tipri imagini bitmap - iar funcia GetDeviceCaps v poate comunica acest lucru.
46.

Funcia TextOut. Contextul de dispozitiv. Obinerea unei variabile handle a contextului de dispozitiv:
TextOut. . handle DC:

Funcia TextOut: detalii


Funcia GDI TextOut:
TextOut (hdc, x, y, psString, iLength) ;
Primul parametru este o variabil handle a contextului de dispozitiv - valoarea hdc returnat de
funcia GetDC sau valoarea hdc returnat de funcia BeginPaint n timpul prelucrrii mesajului
WM_PAINT.
Atributele contextului de dispozitiv controleaz caracteristicile textului afiat. De exemplu, unul
dintre atributele contextului de dispozitiv stabilete culoarea textului. Culoarea prestabilit este negru.
De asemenea, contextul prestabilit de dispozitiv stabilete ca fondul s fie alb. Atunci cnd un program
afieaz un text pe ecran, Windows folosete aceast culoare de fond ca s umple spaiul
dreptunghiular care nconjoar fiecare caracter, spaiu numit caset caracter" (character box").
Parametrul psString este un pointer la un ir de caractere, iar iLength este lungimea acestui ir de
caractere, adic numrul de caractere coninut de ir. irul de caractere nu poate conine caractere
Valorile x i y din apelul funciei TextOut definesc nceputul irului de caractere n zona client a
ferestrei. Valoarea x indic poziia pe orizontal, iar valoarea y indic poziia pe vertical. Colul din
stnga-sus al primului caracter se afl n poziia de coordonate (x,y).
O variabil handle, aa cum am mai spus, este pur i simplu un numr pe care Windows l folosete
pentru indicarea unui obiect. Putei s obinei aceast variabil din Windows i apoi s o folosii n
alte funcii. Variabila handle a contextului de dispozitiv este calea de acces a ferestrei
dumneavoastr la funciile GDI. Folosind aceast variabil suntei liber s desenai zona client a
ferestrei i s o facei aa cum dorii.

Contextul de dispozitiv (prescurtat DC - device context) este o structur de date ntreinut intern
de interfaa GDI. Fiecare context de dispozitiv este asociat unui anumit dispozitiv de afiare, cum ar fi
imprimanta, plotterul sau monitorul video. n cazul monitoarelor video, un context de dispozitiv este
de obicei asociat unei anumite ferestre de pe ecran.
O parte dintre valorile din contextul de dispozitiv sunt atribute grafice. Aceste atribute definesc
unele particulariti privind modul de lucru al unor funcii de desenare din interfaa GDI. n cazul
funciei TextOut, de exemplu, atributele contextului de dispozitiv determin culoarea textului, culoarea
fondului, modul de mapare a coordonatelor x i y n zona client a ferestrei i fontul folosit de Windows
pentru afiarea textului.
Atunci cnd vrea s deseneze, programul trebuie s obin mai nti o variabil handle a unui
context de dispozitiv. Dup terminarea operaiilor de desenare, programul ar trebui s elibereze
variabila. Dup eliberarea variabilei handle, aceasta nu mai este valid i, deci, nu mai poate fi folosit.
Programul trebuie s obin i s elibereze variabila handle n timpul prelucrrii unui singur mesaj. Cu
excepia contextelor de dispozitiv create cu funcia CreateDC (despre care nu vom discuta n acest
capitol) este recomandat s nu pstrai variabilele handle ale contextelor de dispozitiv de la un mesaj la
altul.
n general, aplicaiile Windows folosesc dou metode pentru obinerea variabilelor handle ale
contextelor de dispozitiv, atunci cnd se pregtesc pentru desenarea ecranului.

Obinerea unei variabile handle a contextului de dispozitiv:


prima metod
Aceast metod este folosit n timpul prelucrrii mesajelor WM_PAINT. Sunt implicate dou
funcii: BeginPaint i EndPaint. Aceste funcii au nevoie de variabila handle a ferestrei (transmis
procedurii de fereastr ca parametru) i de adresa unei variabile de tipul PAINTSTRUCT. De obicei,
programatorii Windows numesc aceast variabil ps i o definesc n procedura de fereastr astfel:
PAINTSTRUCT
ps;
n timpul prelucrrii mesajului WM_PAINT, procedura de fereastr apeleaz mai nti funcia
BeginPaint ca s completeze cmpurile structurii ps. Valoarea returnat de funcia BeginPaint este
variabila handle a contextului de dispozitiv. n general, aceasta este salvat ntr-o variabil numit hdc.
n prcedura de fereastr definii aceast variabil astfel:
HDC hdc;
Tipul de date HDC este definit ca un ntreg fr semn, pe 32 de bii. Programul poate apoi s
foloseasc funcii GDI, cum ar fi TextOut. Apelul funciei EndPaint elibereaz variabila handle a
contextului de dispozitiv.
n general, prelucrarea mesajului WM_PAINT se face astfel:
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
[apelarea unor funcii GDI]
EndPaint (hwnd, &ps) ;
return 0 ;
n timpul prelucrrii mesajului WM_PAINT, procedura de fereastr trebuie s apeleze funciile
BeginPaint i EndPaint. Dac o procedur de fereastr nu prelucreaz mesajele WM_PAINT, trebuie
s le retransmit procedurii DefWindowProc (procedura de fereastr prestabilit).
DefWindowProc prelucreaz mesajele WM_PAINT n urmtoarea secven de cod:
case WM_PAINT:
BeginPaint (hwnd, &ps) ;
EndPaint (hwnd, &ps) ;
return 0 ;
Apelarea n secven a funciilor BeginPaint i EndPaint fr nici o alt instruciune intermediar
nu face dect s valideze regiunea invalidat anterior. Aadar, nu procedai astfel:
case WM_PAINT:
return 0 ; // GREIT !!!

Windows plaseaz un mesaj WM_PAINT n coada de ateptare, deoarece o parte a zonei client este
invalid. Dac nu apelai funciile BeginPaint i EndPaint (sau ValidateRect) Windows nu valideaz
zona de fereastr respectiv, ci v trimite n continuare mesaje WM_PAINT.
47.

Funciile SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw), SetScrollPos (hwnd, iBar, iPos, bRedraw).

SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ;


Parametrul iBar poate avea una dintre valorile SB_VERT i SB_HORZ, iar iMin i iMax sunt
poziiile minim i maxim din domeniu, n timp ce bRedraw trebuie s aib valoarea TRUE dac vrei
ca Windows s redeseneze bara de derulare pe baza noului domeniu stabilit.
Poziia casetei de derulare este reprezentat ntotdeauna printr-o valoare ntreag. De exemplu, o
bar de derulare cu domeniul cuprins ntre 0 i 4 are cinci poziii ale casetei de derulare, aa cum se
poate vedea n Figura 3-8. Putei s folosii funcia SetScrollPos ca s stabilii o nou poziie a casetei
de derulare pe bara de derulare:
SetScrollPos (hwnd, iBar, iPos, bRedraw) ;

Pozii
a
Pozii
a
Pozii
a
Pozii
a
Poziia
4
Poziia 0 Poziia 1 Poziia 2 Poziia 3 Poziia
4
Figura
3-8. Bare de derulare cu cinci poziii ale casetei de derulare.
Parametrul iPos reprezint noua poziie, care trebuie s fie cuprins n domeniul delimitat de iMin
i iMax. Windows conine funcii asemntoare (GetScrollRange i GefScrollPos) pentru obinerea
domeniului i a poziiei unei bare de derulare.
Atunci cnd folosii bare de derulare ntr-un program Windows, rspunderea pentru ntreinerea i
actualizarea acestora este mprit ntre dumneavoastr i sistemul de operare. Sistemul de operare
Windows are urmtoarele sarcini:
Trateaz operaiile executate cu mouse-ul asupra barei de derulare. .Afieaz n video invers
zona pe care utilizatorul execut clic.
Mut caseta de derulare atunci cnd utilizatorul o trage cu ajutorul mouse-ului.
Trimite mesaje din partea barei de derulare ctre procedura de fereastr care o conine.
Funciile programului n aceast privin sunt:
Iniializarea domeniului barei de derulare.
Prelucrarea mesajului primit de la bara de derulare.

48.

Actualizarea poziiei casetei de derulare de pe bar.


Ignorarea tastaturii. Cursorul de intrare. Acionri de taste i caractere. .
. .

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 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.
Casetele de dialog au i ele o interfa cu tastatura, dar programele, n general, nu trebuie s
monitorizeze tastatura ct timp este activ o caset de dialog. Interfaa cu tastatura este manipulat de
Windows i acesta trimite programului mesaje prin care i comunic efectele tastelor apsate. Casetele
de dialog pot conine controale de editare pentru introducerea textului. Acestea sunt mici casete, n care
utilizatorul poate s scrie un ir de caractere. Windows asigur logica de funcionare a controlului de
editare i furnizeaz programului coninutul final al controlului, dup ce utilizatorul a terminat.
Cursorul, cursorul, cine a luat cursorul de intrare?
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").
Conceptul cursorului de intrare este strns legat de conceptul de fereastr activ". Fereastra care
deine cursorul de intrare este fie fereastra activ, fie o fereastr descendent a ferestrei active. De
obicei, fereastra activ este uor de identificat. Dac fereastra activ are o bar de titlu, Windows
evideniaz bara de titlu a acesteia. Dac fereastra activ are un cadru de dialog (o form des ntlnit
n casetele de dialog) n locul unei bare de titlu, Windows evideniaz acest cadru. Dac fereastra
activ a fost redus la o pictogram (minimizat), Windows evideniaz textul afiat sub pictogram.
Ferestrele descendent mai des ntlnite sunt controale, precum butoanele de apsare, butoanele
radio, casetele de validare, barele de derulare, casetele de editare i casetele list, care, de obicei, apar
n casete de dialog. Ferestrele descendent nu sunt niciodat ferestre active. Dac o fereastr descendent
deine cursorul de intrare, atunci fereastra activ este fereastra printe. Controalele de tip fereastr
descendent indic faptul c dein cursorul de intrare prin afiarea unui cursor care clipete sau a unui
cursor de editare.
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.

Acionri de taste i caractere


Mesajele privind tastatura pe care un program le recepioneaz de la sistemul de operare fac
diferena ntre acionrile de taste" (keystrokes") i caractere". Aceste noiuni sunt legate de cele
dou moduri n care putei s privii tastatura. n primul rnd, tastatura este o colecie de taste.
Tastatura are o singur tast A; apsarea tastei A este o acionare de tast, iar eliberarea tastei A este tot
o acionare de tast. Tastatura este, ns, n acelai timp, i un dispozitiv de intrare care genereaz

caractere afiabile. Tasta A poate s genereze mai multe caractere, n funcie de starea tastelor Ctrl,
Shift i Caps Lock. n mod normal, caracterul generat este a. Dac tasta Shift este apsat, sau tasta
Caps Lock este activ, caracterul generat este A. Dac tasta Ctrl este apsat, caracterul generat este
Ctrl+A. Dac se folosete un driver de tastatur pentru o limb strin, apsarea tastei A poate s fie
precedat de un caracter mort" (dead-character key") sau de tastele Shift, Ctrl sau Alt n diferite
combinaii. Combinaiile pot s genereze un caracter a sau A cu un accent.
Pentru acionrile de taste care genereaz caractere afiabile, Windows trimite programului att
mesaje pentru acionarea de taste, ct i mesaje pentru caractere. Unele taste nu genereaz caractere.
Astfel de taste sunt Shift, tastele funcionale, tastele de deplasare i tastele speciale, precum Insert i
Delete. n cazul acestor taste, Windows genereaz numai mesaje pentru acionari de taste.
49.

n ce const arhitectura orientat pe mesaje?


?

Arhitectura bazat pe mesaje


S-a dovedit c rspunsul la aceste ntrebri este esenial pentru nelegerea arhitecturii folosite la
construirea interfeelor grafice cu utilizatorul. n Windows, atunci cnd utilizatorul redimensioneaz o
fereastr, sistemul de operare trimite programului un mesaj prin care i comunic noile dimensiuni ale
ferestrei. Programul poate apoi s modifice coninutul ferestrei, astfel nct acesta s se adapteze la
noile dimensiuni.
Sistemul de operare trimite programului un mesaj." Sper c nu ai luat ad-litteram sensul acestei
propoziii. Ce poate s nsemne acest lucru? Pentru c nu este vorba despre un sistem de pot
electronic, ci despre cod, cum poate un sistem de operare s trimit" mesaje ctre un program?
Atunci cnd am spus c sistemul de operare trimite programului un mesaj" m-am referit la faptul
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").
50.

n ce const consecvena privind interfaa cu utilizatorul?


?

Consecvena privind interfa cu utilizatorul


Utilizatorii nu mai sunt dispui s piard prea mult timp pentru a nva cum se folosete
calculatorul sau cum s stpneasc un anumit program. Windows i ajut n acest sens, deoarece 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.
Dup ce nvai s folosii un program Windows, vei fi capabil deja s utilizai orice alt program
pentru Windows. Meniurile i casetele de dialog permit utilizatorului s experimenteze diferite
funcii ale programului i s i exploreze posibilitile. Majoritatea programelor Windows au
interfa att cu mouse-ul, ct i cu tastatura. Dei majoritatea funciilor unui program pentru
Windows pot fi controlate i cu ajutorul tastaturii, mouse-ul este deseori mai convenabil pentru
diferite sarcini.
Din punctul de vedere al programatorului, consecvena n realizarea interfeei cu utilizatorul este
rezultatul folosirii procedurilor integrate n Windows pentru construirea meniurilor i a casetelor de

dialog. Toate meniurile au aceeai interfa cu tastatura i cu mouse-ul deoarece aceste operaii sunt
manipulate mai degrab de Windows, dect de programul respectiv.
51.

n ce const interfaa grafic independent de dispozitiv?


. ?

Interfaa grafic independent de dispozitiv


Windows este o interfa grafic i programele pentru Windows pot folosi toate avantajele oferite de
elementele grafice i de textul formatat att pentru ecran, ct i pentru imprimant. O interfa grafic
nu are numai avantajul de a fi mai atractiv, ci i pe acela de a furniza utilizatorului o cantitate mai
mare de informaii.
Programele scrise pentru Windows nu au acces direct la componentele hardware ale dispozitivelor de
afiare, cum ar fi ecranul sau imprimanta. n schimb, Windows folosete un limbaj de programare
pentru grafic (numit GDI - Graphics Device Interface) care simplific afiarea textului formatat i a
elementelor grafice. Windows transform componentele hardware de afiare n dispozitive virtuale. Un
program scris pentru Windows va rula cu orice plac video i cu orice imprimanta pentru care
Windows are un driver de dispozitiv. Programul nu trebuie s determine ce tip de dispozitiv fizic este
ataat la calculator.
Crearea unei interfee grafice independente de dispozitiv pentru calculatoarele IBM PC nu a fost o
sarcin uoar pentru dezvoltatorii sistemului de operare Windows. Proiectarea calculatoarelor
personale s-a fcut pe baza principiului arhitecturilor deschise. Productorii teri de componente
hardware au fost ncurajai s dezvolte dispozitive periferice, i datorit acestui fapt au aprut o
mulime de astfel de dispozitive. Dei au fost create anumite standarde, programele convenionale
pentru MS-DOS trebuie s asigure suportul individual pentru diferite configuraii standard. De
exemplu, este un lucru destul de obinuit ca un program de procesare de texte pentru MS-DOS s fie
livrat mpreun cu cteva dischete care conin mai multe fiiere mici, pentru adaptarea la diferite tipuri
de imprimante. Programele Windows 95 nu au nevoie de drivere proprii, deoarece acestea sunt
asigurate chiar de sistemul de operare.
52.

Interfaa pentru dispozitive grafice. Filozofia GDI. Structura interfeei GDI. Tipuri de apeluri de funcii.
Primitive GDI. . GDI. GDI.
. GDI.

Filozofia GDI
n versiunile pe 32 de bii ale sistemului de operare Windows elementele grafice sunt manipulate,
n principal, prin funcii exportate din biblioteca cu legturi dinamice GDI32.DLL, care, la rndul ei,
folosete biblioteca cu legturi dinamice pe 16 bii GDI.EXE. (n versiunile Windows anterioare,
bibliotecile cu legturi dinamice erau fiiere cu extensia .EXE, nu .DLL.) Aceste module apeleaz
proceduri din diferite fiiere driver pentru afiare - un fiier .DRV pentru afiarea pe ecran i, probabil,
unul sau mai multe fiiere .DRV care controleaz imprimantele i plotterele. Driverele execut
operaiile de acces la componentele hardware ale monitorului video sau convertesc comenzile GDI n
coduri sau comenzi pe care le pot interpreta diferite tipuri de imprimante. Pentru diferite tipuri de plci
video sau de imprimante este nevoie, desigur, de diferite fiiere driver.
Deoarece la calculatoarele compatibile PC pot fi ataate diferite dispozitive de afiare, unul dintre
scopurile principale ale interfeei GDI este s permit manipularea elementelor grafice independent de
dispozitiv. Programele scrise pentru Windows ar trebui s ruleze fr probleme, indiferent de
dispozitivul grafic de afiare folosit, dac acesta este acceptat de sistemul de operare. Interfaa GDI
realizeaz acest lucru prin furnizarea unor componente care izoleaz programele de caracteristicile
particulare ale diferitelor dispozitive de ieire.

Lumea dispozitivelor grafice de ieire este mprit n dou categorii: dispozitive rastru i
dispozitive vectoriale. Majoritatea dispozitivelor de ieire pentru PC sunt dispozitive rastru, ceea ce
nseamn c reprezentarea imaginilor se face prin matrice de puncte. Aceast categorie include plcile
video, imprimantele matriceale i imprimantele laser. Dispozitivele vectoriale, care deseneaz
imaginile prin linii, sunt, n general, limitate la plottere.
Majoritatea limbajelor de programare cu posibiliti grafice tradiionale se bazeaz n exclusivitate
pe vectori. Aceasta nseamn c un program care folosete unul dintre aceste limbaje grafice este
desprit de componentele hardware printr-un nivel de abstractizare. Dispozitivul de ieire folosete
pixeli pentru reprezentarea elementelor grafice, dar programul nu comunic deloc cu interfaa n
limbajul pixelilor. Dei putei s folosii interfaa Windows GDI ca sistem de desenare vectorial la
nivel nalt, putei s folosii aceeai interfaa i pentru manipularea la nivel sczut a pixelilor.
Din acest punct de vedere, interfaa Windows GDI este pentru limbajele grafice de interfaa
tradiionale ceea ce este C pentru alte limbaje de programare. Limbajul C e bine cunoscut pentru
gradul nalt de portabilitate ntre diferite medii i sisteme de operare. Dar, n acelai timp, limbajul C e
cunoscut i pentru faptul c permite efectuarea unor operaii de nivel sczut, care n alte limbaje de
nivel nalt sunt, deseori, imposibile. Aa cum C este numit uneori limbaj de asamblare de nivel nalt",
putei s considerai c GDI este o interfa de nivel nalt ctre componentele hardware ale
dispozitivelor grafice.
Aa cum ai vzut, n mod prestabilit. Windows folosete un sistem de coordonate bazat pe pixeli.
Majoritatea limbajelor grafice tradiionale folosesc un sistem de coordonate virtual", cu o ax
vertical i una orizontal care merg, de exemplu, de la 0 la 32.767. Dei unele limbaje grafice nu v
permit s folosii coordonate n pixeli, interfa GDI v las s lucrai n oricare dintre cele dou
sisteme de coordonate (i chiar ntr-un alt sistem, bazat pe dimensiunile fizice). Putei s folosii un
sistem de coordonate virtual i s izolai astfel programul de componentele hardware, sau s folosii
sistemul de coordonate al dispozitivului i s scriei programul direct pentru componentele hardware
utilizate.
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.

Structura interfeei GDI


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:

Funcii care obin (sau creeaz) i elibereaz (sau distrug) un context de dispozitiv. Aa cum am
vzut n Capitolul 3, pentru a desena avei nevoie de un context de dispozitiv. Funciile GetDC i
ReleaseDC v permit s facei aceste lucruri n timpul prelucrrii altor mesaje dect WM_PAINT,
pe cnd funciile BeginPaint i EndPaint (dei din punct de vedere tehnic fac parte din subsistemul
USER din Windows) sunt folosite n timpul prelucrrii mesajului WM_PAINT. Vom discuta n
curnd despre alte funcii legate de contextul de dispozitiv.

Funcii care obin informaii despre contextul de dispozitiv. n programele SYSMETS, cu care ai
fcut cunotin n Capitolul 3, am folosit funcia GetTextMetrics ca s obinem informaii despre
dimensiunile fontului selectat n contextul de dispozitiv. Mai trziu n acest capitol vom prezenta
programul DEVCAPS1, pentru a obine informaii generale despre contextul de dispozitiv.

Funcii care deseneaz ceva. Evident, dup rezolvarea problemelor preliminare, acestea sunt
funciile cu adevrat importante. n Capitolul 3 am folosit funcia TextOut pentru afiarea textului
n zona client a ferestrei. Aa cum vom vedea, alte funcii GDI sunt folosite pentru desenarea
liniilor, a zonelor colorate i a imaginilor de tip bitmap.

Funcii care stabilesc sau obin atribute ale contextului de dispozitiv. Un atribut" al contextului de
dispozitiv specific modul de lucru al funciilor de desenare. De exemplu, folosii funcia
SetTextColor ca s precizai culoarea textului afiat cu funcia TextOut (sau cu o alt funcie de
afiare a textului). n programele SYSMETS din Capitolul 3 am folosit funcia SetTextAlign ca s
artm interfeei GDI faptul c poziia de nceput a irului de caractere este n partea dreapt a
irului de caractere, nu n partea stng, aa cum se ntmpl de obicei. Toate atributele contextului
de dispozitiv au valori prestabilite, care devin active la obinerea contextului de dispozitiv. Pentru
fiecare funcie de tip Set exist i o funcie Get corespondent, folosit pentru obinerea valorilor
curente ale atributelor contextului de dispozitiv.

Funcii care lucreaz cu obiecte GDI. Aici este punctul n care lucrurile se ncurc puin n
interfaa GDI. Mai nti vom da un exemplu: n mod prestabilit, toate liniile pe care le desenai
folosind interfaa GDI sunt continue i au o grosime standard. Ce se ntmpl, ns, dac dorii s
desenai o linie mai groas sau o linie punctat ori ntrerupt? Grosimea i stilul liniei nu sunt
atribute ale contextului de dispozitiv. Acestea sunt caracteristici ale peniei logice" (logical pen").
Putei s indicai o peni logic prin specificarea acestor caracteristici n funciile CreatePen,
CreatePenIndirect i ExtCreatePen. Funciile de mai sus returneaz o variabil handle a peniei
logice create. (Dei se consider c aceste funcii fac parte din interfaa GDI, spre deosebire de
majoritatea celorlalte funcii acestea nu au nevoie, ca parametru, de o variabil handle a contextului
de dispozitiv.) Pentru folosirea peniei selectai variabila handle a acesteia n contextul de
dispozitiv. Din acest moment, orice linie va fi desenat eu penia selectat. Ulterior, deselectai
obiectul peni din contextul de dispozitiv i distrugei-l. n afara penielor, putei s folosii obiecte
GDI pentru crearea pensulelor care coloreaz o suprafa nchis, pentru fonturi, pentru imagini
bitmap i pentru alte aspecte ale interfeei GDI, despre care vom discuta n acest capitol.

Primitive 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. Despre toate aceste clemente vom mai discuta n capitolul de fa. Orice curb mai
complex poate n desenat ea o linie poligonal, adic o serie de linii foarte scurte care definesc o
curb. 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. Imaginile bitmap sunt instrumente de baz pentru sistemele grafice de
tip rastru. 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.
Interfaa GDI accept dou tipuri de imagini bitmap: un tip mai vechi (dar util) de imagini bitmap
dependente de dispozitiv i un tip mai nou (precum cele din Windows 3.0) de imagini bitmap
independente de dispozitiv (DIB - Device Independent Bitmap) care pot fi stocate n fiiere.

53.

Text. Textul este mai puin matematic" dect alte aspecte ale graficii pe calculator. Textul, aa cum
l tim, este legat de sute de ani de tipografia tradiional, apreciat adesea ca adevrat art. Din
acest motiv, textul este de multe ori nu doar cea mai complex parte a sistemului grafic, ci i cea
mai important. 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 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.
Mesaje CARACTER. Mesajul WM_CHAR. Mesaje pentru caractere moarte". .
WM_CHAR. .

Mesajul WM_CHAR
Atunci cnd trebuie s prelucreze caracterele introduse de la tastatur (de exemplu, ntr-un
procesor de texte sau ntr-un program de comunicaii) programul prelucreaz mesajele WM_CHAR.
Probabil dorii s prelucrati ntr-un mod mai special tastele Backspace, Tab i Enter (eventual si tasta
de salt la linie nou) dar toate celelalte caractere sunt tratate la fel:
case WH_CHAR :
switch (wParam)
{
case '\b' :
case '\f' :
case '\n' :
case '\r' :
default :

// backspace
[alte linii de program]
break ;
// tab
[alte linii de program]
break ;
// salt la linie nou
[alte linii de program]
break ;
// retur de car
[alte linii de program]
break ;
// cod de caractere
[alte linii de program]
break ;

}
return 0 ;

Acest fragment de program este asemntor cu secvenele de cod pentru tratarea caracterelor dintrun program MS-DOS obinuit.

Mesaje pentru caractere moarte"


De obicei, programele pot s ignore mesajele WM_DEADCHAR si WM_SYSDEADCHAR. Pe
unele tastaturi, n afar de tastatura de tip american, o serie de taste sunt folosite pentru adugarea
semnelor diacritice la o liter. Acestea se numesc taste moarte" (dead keys") deoarece nu pot crea
singure caractere. De exemplu, pe o tastatura german, n locul tastei +/= de pe tastatura american se
afl o tast moart pentru accentul ascuit ('') dac nu este apsat tasta Shift, si pentru accentul grav (`)
dac este apsat tasta Shift.
Atunci cnd utilizatorul apas aceast tast moart, procedura de fereastr pri mete un mesaj
WM_DEADCHAR pentru care parametrul wParam conine codul ASCII al semnului diacritic. Dac
utilizatorul apas apoi o liter (de exemplu, tasta A), procedura de fereastr primete un mesaj
WM_CHAR pentru care parametrul wParam conine codul ASCII al literei a" cu semnul diacritic
respectiv. Ca urmare, programul nu trebuie s prelucreze mesajul WM_DEADCHAR, deoarece
mesajul WM_CHAR urmtor i furnizeaz toate informaiile necesare. Codul Windows se ocup chiar

i de tratarea erorilor: dac tasta moart este urmat de o liter care nu poate avea semnul diacritic
respectiv (cum ar fi litera s"), procedura de fereastr primete dou mesaje WM_CHAR - pentru
primul parametrul wParam conine codul ASCII al semnului diacritic, iar pentru al doilea parametrul
wParam conine codul ASCII al literei s".
54.

Mesaje de la barele de derulare. Structurarea programului pentru desenare. ScrollWindow.


. . ScrollWindow.

55.

Mesaje generate de mouse n afara zonei client. Mesajul de testare a poziiei. Mesajele genereaz mesaje.
. .
.

Mesaje generate de mouse n afara zonei client


Cele zece mesaje discutate pn acum sunt generate atunci cnd mouse-ul este deplasat sau cnd 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 prelucrai mesajele generate n afara zonei client. Le transmitei pur i
simplu funciei DefWindowProc pentru a permite sistemului de operare Windows s execute funciile
de sistem corespunztoare. Din acest punct de vedere, mesajele non-client" sunt asemntoare 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 primete urmtoarele mesaje:
Buton

Apsat

Stn WM_NCLBUTTON DOWN


ga
Mijl WM_NCMBUTTONDOWN
oc
Dre WM_NCRBUTTONDOWN
apta

Eliberat
WM_NCLBUTTON
UP
WM_NCMBUTTON
UP
WM_NCRBUTTON
UP

Apsat (al doilea clic)


WM_NCLBUTTONDBLC
LK
WM_NCMBUTTONDBL
CLK
WM_NCRBUTTONDBLC
LK

Totui, parametrii wParam i lParam pentru mesajele generate de mouse din afara zonei client sunt
diferite de cele generate din zona client. Parametrul wParam indic zona non-client din care a fost
generat mesajul. Parametrul wParam poate conine unul dintre identificatorii cu prefixul HT (hit
test") definii n fiierele antet din Windows.
Variabila lParam conine coordonata pe axa x n cuvntul mai puin semnificativ i coordonata pe
axa y n cuvntul mai semnificativ. Totui, aceste coordonate sunt relative la ecran, nu la zona client.
Pentru coordonatele de ecran, punctul de origine (0,0) este colul din stnga-sus al zonei de afiare a
ecranului. Valorile coordonatei x cresc ctre dreapta, iar valorile coordonatei y cresc n jos (vezi Figura
6.3).

Figura 6-3. Coordonatele ecranului i coordonatele zonei client.


Putei s transformai coordonatele ecranului n coordonate ale zonei client i invers, folosind dou
funcii Windows:
ScreenToClient (hwnd, pPoint) ;
ClientToScreen (hwnd, pPoint) ;

Parametrul pPoint este un pointer la o structur de tip POINT. Aceste funcii transform valorile
stocate n structura transmis ca parametru fr s pstreze vechile valori. Remarcai faptul c dac un
punct se afl deasupra zonei client a unei ferestre, n urma transformrii coordonatelor de ecran n
coordonate ale zonei client, valoarea coordonatei pe axa y va fi negativ. Similar, dac un punct se afl
n stnga zonei client a unei ferestre, n urma transformrii coordonatelor de ecran n coordonate ale
zonei client, valoarea coordonatei pe axa x va fi negativ.

Mesajul de testare a poziiei


Dac ai inut socoteala, am discutat pn acum despre 20 dintre cele 21 de mesaje generate de
mouse. Ultimul mesaj este WM_NCHITTEST (non client hit test") folosit pentru verificarea poziiei
din care a fost generat mesajul. Acest mesaj precede toate celelalte mesaje generate de mouse, din zona
client sau din afara acesteia. Parametrul IParam al mesajului conine coordonatele x i y ale
indicatorului de mouse. Parametrul wParam nu este folosit.
De obicei, aplicaiile Windows transmit acest mesaj funciei DefWindowProc. Windows folosete
mesajul WM_NCHITTEST ca s genereze celelalte mesaje, n funcie de poziia mouse-ului. Pentru
mesajele din afara zonei client, valoarea returnat de funcia DefWindowProc n urma prelucrrii
mesajului WM_NCHITTEST devine parametrul wParam al mesajului generat. Aceast valoare poate
fi oricare dintre valorile wParam care nsoesc mesajele generate de mouse din afara zonei client, plus
urmtoarele:
HTCLIENT
Zona client
HTNOWHERE
Nici o fereastr
HTTRANSPARENT
O fereastr acoperit de o alt fereastr
HTERROR
Determin funcia DefWindowProc s emit un semnal sonor
Dac funcia DefWindowProc genereaz un mesaj HTCLIENT n urma prelucrrii mesajului
WM_NCHITTEST, Windows transform coordonatele ecran n coordonate ale zonei client i
genereaz un mesaj pentru zona client.

Dac v amintii cum am dezactivat toate funciile de sistem activate de la tastatur, prin
interceptarea mesajului WM_SYSKEYDOWN, probabil v ntrebai dac putei s facei ceva
asemntor i prin interceptarea mesajelor generate de mouse. Desigur, putei face acest lucru
incluznd n procedura de fereastr liniile:
case WM_NCHITTEST
return (LRESULT) HTNOWHERE ;

Vei dezactiva toate mesajele de mouse trimise procedurii de fereastr pentru zona client i pentru
poriunile din afara zonei client. Butoanele mouse-ului nu vor mai funciona ct timp indicatorul
mouse-ului se afl n fereastra dumneavoastr, inclusiv deasupra pictogramei meniului sistem, a
butoanelor de redimensionare i a butonului pentru nchiderea ferestrei.
56.

MESAJE GENERATE DE MOUSE N ZONA CLIENT Mesaje non-client. Mtile MK_LBUTTON,


MK_MBUTTON, MK_RBUTTON, MK_SHIFT, MK_CONTROL. .
non-client. MK_LBUTTON, MK_MBUTTON, MK_RBUTTON, MK_SHIFT,
MK_CONTROL.

MESAJE GENERATE DE MOUSE N ZONA CLIENT


o procedur de fereastr primete mesaje de la mouse de fiecare dat cnd indicatorul mouse-ului
trece pe deasupra ferestrei sau cnd se execut clic n fereastra respectiv, chiar dac fereastra nu este
activ sau nu deine cursorul de intrare. n Windows sunt definite 21 de mesaje generate de mouse.
Totui, 11 dintre aceste mesaje nu se refer la zona client (le vom numi de aici nainte mesaje nonclient") i de obicei sunt ignorate de programele Windows.
Atunci cnd mouse-ul este deplasat peste zona client a unei ferestre, procedura de fereastr
primete mesajul WM_MOUSEMOVE. Dac un buton al mouse-ului este apsat sau eliberat n zona
client a unei ferestre, procedura de fereastr primete urmtoarele mesaje:
Buton
Stnga
Mijloc

Apsat

Eliberat

Apsat (al doilea clic)

WM_LBUTTONDOWN
WM_MBUTTONDOWN

WM_LBUTTONUP
WM_MBUTTONUP

WM_LBUTTONDBLCLK
WM_MBUTTONDBLCLK

Dreapta

WM_RBUTTONDOWN

WM_RBUTTONUP

WM_RBUTTONDBLCLK

Procedura de fereastr primete mesaje MBUTTON" numai de la un mouse cu trei butoane i


mesaje RBUTTON" numai de la un mouse cu dou sau cu trei butoane. Procedura de fereastr
primete mesaje DBLCLK" numai n cazul n care clasa de ferestre a fost definit astfel nct s
recepioneze aceste mesaje (aa cum vom vedea mai jos).
Pentru toate mesajele, parametrul lParam conine poziia mouse-ului. Cuvntul mai puin
semnificativ conine coordonata pe axa x, iar cuvntul mai semnificativ conine coordonata pe axa y,
relative la colul din stnga-sus al zonei client a ferestrei. Putei s extragei coordonatele pe axele x i
y din parametrul IParam folosind macroinstruciunile LOWORD i HIWORD, definite n fiierele
antet din Windows. Valoarea parametrului wParam indic starea buloanelor mouse-ului i starea
tastelor Shift i Ctrl. Putei s testai parametrul wParam folosind o serie de mti definite n fiierele
antet din Windows. Prefixul MK vine de la mouse key" (tast de mouse").
MK_LBUTTON
MK_MBUTTON
MK_RBUTTON
MK_SHIFT
MK_CONTROL

Butonul din stnga al mouse-ului este apsat


Butonul din mijloc al mouse-ului este apsat
Butonul din dreapta al mouse-ului este apsat
Tasta Shift este apsat
Tasta Ctrl este apsat

Atunci cnd deplasai indicatorul mouse-ului peste zona client a unei ferestre nu se genereaz un
mesaj WM_MOUSEMOVE pentru fiecare pixel peste care trece indicatorul. Numrul mesajelor
WM_MOUSEMOVE depinde de componentele hardware ale mouse-ului i de viteza cu care
procedura de fereastr poate s prelucreze aceste mesaje

57.

Mesajele de la o fereastr child la una printe.

Atunci cnd rulai programul BTNLOOK n partea stng a zonei client, sunt afiate diferite tipuri de butoane.
Aa cum am menionat anterior, atunci cnd executai clic pe un buton, controlul de tip fereastr descendent
trimite mesajul WM_COMMAND ctre fereastra printe. Programul BTNLOOK intercepteaz mesajul
WM_COMMAND i afieaz valorile lParam i wParam. Iat ce semnificaie au acestea:
LOWORD (wParam)
Identificatorul ferestrei descendent
HIWORD (wParam)
Codul de ntiinare
lParam
Variabila handle a ferestrei descendent
Dac facei conversia unor programe scrise pentru versiunile pe 16 bii ale sis temului de operare
Windows, reinei c aceti parametri au fost modificai n vederea adaptrii la dimensiunea pointerilor pe 32
de bii.
Identificatorul ferestrei descendent este valoarea transmis funciei CreateWindow la crearea ferestrei
descendent. n programul BTNLOOK, aceti identificatori au valori de la 0 la 9, corespunztoare celor 10
butoane afiate n zona client. Variabila handle a ferestrei descendent este valoarea returnat de funcia
CreateWindow.
Codul de ntiinare este un cod de submesaj pe care fereastra descendent l folosete pentru a transmite
ferestrei printe mai multe informaii despre semnificaia mesajului. Valorile pe care le pot avea aceste coduri
sunt definite n fiierele antet definite n Windows:
Identificatorul codului de ntiinare al butonului
Valoare
BN_CLICKED
0
BN_PAINT
1
BN_HILITE
2
BN_UNHILITE
3
BN_DISABLE
4
BN_DOUBLECLICKED
5
Codurile de ntiinare de la 1 la 5 sunt pstrate pentru compatibilitatea cu un stil nvechit de butoane,
numit BS_SERBUTTON, aa c nu vei ntlni dect codul BN_CLICKED.

58.

Mesajele de la timer. ( e)

Mesajele WM_TIMER seamn cu mesajele WM_PAINT i dintr-un alt punct de vedere.


Windows nu insereaz n coada de ateptare mai multe mesaje WM_TIMER, ci le combin ntrunul singur. Ca urmare, programul nu primete deodat mai multe mesaje WM_TIMER, dei este
posibil s primeasc dou astfel de mesaje la un interval foarte scurt. O aplicaie nu poate s
determine numrul mesajelor WM_TIMER care lipsesc" din secven.
59.

60.

Mesajele privind tastatura: acionri de taste i caractere". Taste obinuite i taste de sistem.
WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP. Variabila lParam.
: .
. WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP.
lParam.
Mesajele WM_CREATE, WM_PAINT i WM_DESTROY. WM_CREATE, WM_PAINT
WM_DESTROY.

Procedura de fereastr WndProc din fiierul SYSMETS1.C trateaz trei mesaje: WM_CREATE,
WM_PAINT i WM_DESTROY. Mesajul WM_DESTROY 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.

WM_CREATE este primul mesaj pe care l primete procedura de fereastr. Acest mesaj este
generat de Windows atunci cnd funcia Create Window creeaz fereastra. n timpul prelucrrii
mesajului WM_CREATE, se obine un context de dispozitiv pentru fereastr, apelnd funcia GetDC,
i dimensiunile fontului sistem prestabilit, apelnd funcia GetTextMetrics. SYSMETS1 salveaz
limea medie a caracterelor n variabila cxChar i nlimea total (inclusiv spaiul suplimentar
extern) a caracterelor n variabila cyChar.
61.

Mesajul WM_PAINT. Dreptunghiuri valide i invalide. WM_PAINT.


.

Mesajul WM_PAINT
Majoritatea programelor Windows apeleaz funcia UpdateWindow n timpul procesului de
iniializare din procedura WinMain, puin dup intrarea n ciclul de tratare a mesajelor. Windows
profit de aceast ocazie ca s trimit ctre procedura ferestrei primul mesaj WM_PAINT. Acest mesaj
informeaz procedura ferestrei c zona client este pregtit pentru desen. Din acest moment, procedura
ferestrei ar trebui s fie pregtit s prelucreze orice mesaj WM_PAINT n urmtoarele situaii:
O zon anterior acoperit a ferestrei este adus la suprafa atunci cnd utilizatorul mut o
fereastr.
Utilizatorul redimensioneaz fereastra (dac stilul clasei ferestrei include seturile de bii
CS_HREDRAW si CS_VREDRAW).
Programul folosete funciile ScrollWindow sau ScrollDC ca s deruleze o parte din zona client a
ferestrei.
Programul folosete funciile InvalidateRect sau InvalidateRgn pentru a genera n mod explicit un
mesaj WM_PAINT.
n anumite cazuri, cnd zona client este acoperit parial cu text, Windows ncearc s salveze o
zon a ecranului, pe care o va restaura mai trziu. Aceast metod, ns, nu d ntotdeauna rezultate
bune. Windows poate trimite, de aceea, un mesaj WM_PAINT, n situaiile n care:
Windows a ters o caset de dialog sau caset de mesaje care acoperea o parte a ferestrei.
Un meniu este tras n jos i apoi eliberat.
Windows salveaz zona de ecran pe care a scris i apoi o restaureaz, n cazurile n care:
Indicatorul mouse-ului este micat n zona client.
O pictogram este tras n zona client.
Tratarea mesajelor WM_PAINT implic revizuirea modului de scriere pe ecran. Programul trebuie
structurat astfel nct s acumuleze toate informaiile necesare pentru redesenarea zonei client, dar s
fac aceast operaie numai la cerere" - atunci cnd Windows i trimite un mesaj WM_PAINT. Dac
programul trebuie s actualizeze zona client, poate fora sistemul de operare s i trimit un mesaj
WM_PAINT. Dei aceast metod de afiare pare ocolitoare, ea contribuie la structurarea programului.

Dreptunghiuri valide i invalide


Dei procedura unei ferestre trebuie s fie pregtit s actualizeze ntreaga zon client a ferestrei
atunci cnd primete mesajul WM_PAINT, deseori este necesar numai reactualizarea unei poriuni
mai mici (de cele mai multe ori o suprafa dreptunghiular din zona client). O astfel de situaie apare
atunci cnd o parte a zonei client este acoperit de o caset de dialog. Redesenarea este necesar numai
pentru zona dreptunghiular adus la suprafa dup nchiderea casetei de dialog.
Aceast zon este numit regiune invalid" (invalid region") sau regiune de actualizare"
(update region"). Prezena unei regiuni invalide n cadrul zonei client determin sistemul de operare
s plaseze un mesaj WM_PAINT n coada de ateptare a aplicaiei. Procedura de fereastr a unui
program recepioneaz un mesaj WM_PAINT numai dac o parte a zonei client a ferestrei este
invalid.

Windows pstreaz n interior o structur cu informaii pentru desenare" (paint information


structure) pentru fiecare fereastr. Aceast structur conine (printre alte informaii) coordonatele celui
mai mic dreptunghi n care se ncadreaz regiunea invalid. Acesta este cunoscut sub numele de
dreptunghi invalid", dar uneori este numit tot regiune invalid". Dac o alt regiune a zonei client
devine invalid nainte ca mesajul WM_PAINT s fie prelucrat, Windows calculeaz un nou
dreptunghi invalid care cuprinde ambele regiuni i stocheaz informaiile actualizate n structura de
informaii pentru desenare, fr s plaseze un nou mesaj WM_PAINT n coada de ateptare a aplicaiei.
Procedura unei ferestre poate s invalideze un dreptunghi din zona client proprie prin apelarea
funciei InvalidateRect. Dac n coada de ateptare exist deja un mesaj WM_PAINT, Windows
calculeaz un nou dreptunghi invalid. n caz contrar, plaseaz n coada de ateptare un nou mesaj
WM_PAINT. La recepionarea mesajului WM_PAINT, procedura ferestrei poate obine coordonatele
dreptunghiului invalid .De asemenea, poate obine aceste coordonate n orice alt moment, apelnd
funcia GetUpdateRect.
Dup ce procedura de fereastr apeleaz funcia BeginPaint n timpul prelucrrii mesajului
WM_PAINT, ntreaga zon client este validat. De asemenea, programul poate s valideze orice
poriune dreptunghiular din zona client, apelnd funcia ValidateRect. Dac n urma acestui apel
ntreaga zon invalid este validat, toate mesajele WM_PAINT aflate n coada de ateptare sunt
terse.
62.

Modificarea textului unui buton.

Modificarea textului unui buton


Putei s modificai textul unui buton (sau al unei alte ferestre) prin apelarea funciei SetWindowText:
SetWindowText (hwnd, pszString) ;

unde hwnd este variabila handle a ferestrei al crei text urmeaz s fie nlocuit, iar pszString este un pointer la
un ir de caractere terminat cu caracterul nul. Pentru o fereastr normal, acesta este textul care va fi afiat n
bara de titlu. Pentru un buton, acesta este textul afiat pe buton.
De asemenea, putei s obinei textul ferestrei curente:
iLength = GetWindowText (hwnd, pszBuffer, iMaxLength) ;

Parametrul iMaxLength specific numrul maxim de caractere care va fi copiat n bufferul adresat de
pointerul pszBuffer. Funcia returneaz lungimea irului de caractere copiat. Putei s pregtii programul
pentru un text de o anumit lungime apelnd mai nti funcia GetWindowTextLength:
iLength = GetWindowTextLength (hwnd) ;

63.

Moduri de desenare. Operaii rastru (ROP - raster operation). Funciile SetROP2, iDrawMode, GetROP2.
. .

Atunci cnd folosete o peni pentru desenarea unei linii, Windows face de fapt o operaie
boolean ntre pixelii peniei i pixelii de pe suprafaa destinaie. Efectuarea operaiei booleene ntre
pixeli se numete operaie rastru" (ROP - raster operation).
Deoarece desenarea unei linii implic numai dou modele de pixeli (penia i destinaia), operaia
boolean se numete operaie rastru binar" sau ROP2. Windows definete 16 coduri ROP2 care
specific modul de combinare ntre pixelii peniei i pixelii suprafeei, n contextul de dispozitiv
prestabilit, modul de desenare definit este R2_COPYPEN, ceea ce nseamn c Windows copiaz
pixelii peniei pe suprafaa destinaie - adic modul normal n care suntem obinuii s funcioneze o
peni. Exist alte 15 coduri ROP2.
Care este originea celor 16 coduri ROP2 diferite? Pentru exemplificare, s presupunem c avem un
sistem monocrom. Culoarea destinaiei (culoarea zonei client a ferestrei) poate fi negru (reprezentat
prin valorea 0) sau alb (1). La fel, culoarea peniei poate fi alb sau negru. Exist patru combinaii

posibile n cazul folosirii unei penie alb/negru pe o suprafa alb/negru: alb pe alb, alb pe negru, negru
pe alb i negru pe negru.
Ce se ntmpl cu destinaia dup ce desenai cu penia? O posibilitate este ca linia s fie desenat
ntotdeauna cu negru, indiferent de culoarea peniei i a destinaiei: acest mod de desenare este indicat
de codul R2_BLACK. O alt posibilitate este ca linia s fie desenat cu negru, exceptnd situaia n
care att penia ct i destinaia sunt negre, caz n care linia este desenat cu alb. Dei pare puin
ciudat, Windows are un nume pentru acest mod de desenare: R2_NOTMERGEPEN. Windows face o
operaie orientat pe bii de tip SAU ntre pixelii destinaie i pixelii peniei, i inverseaz rezultatul.
Tabelul de mai jos prezint toate cele 16 moduri de desenare ROP2. Tabelul indic modul n care
sunt combinate culoarea peniei (P) i culoarea destinaiei (D) pentru obinerea culorii afiate. n
coloana Operaia boolean" sunt folosite notaiile C pentru indicarea modului n care sunt combinai
pixelii peniei cu pixelii destinaiei.
Peni (P):
Destinaie (D):
Rezultate:

1
1
0

1
0
0

0
1

Operaia
boolean

Mod de desenare

0
0
0

R2_BLACK

0
0
0
0
0
0
0
1
1
1
1
1

0
0
0
1
1
1
1
0
0
0
0
1

0
1
1
0
0
1
1
0
0
1
1
0

1
0
1
0
1
0
1
0
1
0
1
0

~(P | D)
~P & D
~P
P & ~D
~D
P^D
~(P & D)
P&D
~(P ^ D)
D
~P | D
P

R2_NOTMERGEPEN
R2_MASKNOTPEN
R2_NOTCOPYPEN
R2_MASKPENNOT
R2_NOT
R2_XORPEN
R2_NOTMASKPEN
R2_MASKPEN
R2_NOTXORPEN
R2_NOP
R2_MERGENOTPEN
R2_COPYPEN
(prestabilit)
1
1
0
1
P | ~D
R2_MERGEPENNOT
1
1
1
0
P|D
R2_MERGEPEN
1
1
1
1
1
R2_WHITE
Putei s selectai un nou mod de desenare n contextul de dispozitiv astfel:
SetROP2 (hdc, iDrawMode) ;

unde parametrul iDrawMode este una dintre valorile din coloana Mod de desenare" a tabelului de mai
sus. Putei s obinei modul curent de desenare astfel:
iDrawMode = GetROP2 (hdc) ;

Modul de desenare prestabilit al contextului de dispozitiv este R2_COPYPEN, care transfer la


destinaie culoarea peniei. Modul R2_NOTCOPYPEN deseneaz cu alb dac penia este neagr i cu
negru dac penia este alb. Modul R2_BLACK deseneaz ntotdeauna cu negru, indiferent de
culoarea peniei i a destinaiei. n mod similar, modul R2_WHITE deseneaz ntotdeauna cu alb.
Modul R2_NOP este o operaie nul" - destinaia rmne nemodificat.
64.

Modurile de mapare metrice". Moduri de mapare proprii. Modul de mapare MM_ISOTROPIC. Modul de
mapare MM_ANISOTROPIC sau ajustarea imaginii. .
. MM_ISOTROPIC. MM_ANISOTROPIC:

Modurile de mapare metrice"

Windows include dou moduri de mapare n care coordonatele logice sunt exprimate n uniti
fizice. Deoarece coordonatele logice pe axele x i y sunt mapate la uniti fizice identice, aceste moduri
de mapare v ajut s desenai cercuri mai rotunde" i ptrate mai ptrate".
Cele cinci moduri de mapare metrice" sunt prezentate mai jos n ordinea cresctoare a preciziei.
Cele dou coloane din partea dreapt prezint dimensiunile unitilor logice n inci (in.) i n milimetri
(mm) pentru comparare:
Mod de mapare
MM_LOENGLISH
MM_LOMETRIC
MM_HIENGLISH
MM_TWIPS*
MM_HIMETRIC

Uniti logice
0,01 in.
0,1 mm
0,001 in.
1/1440 in.
0,01 mm

Inci
0,001
0,00394

Milimetri
0,254
0,1

0,001

0,0254

0,000694
0,000394

0,0176
0,01

* Un twip este 1/20 dintr-un punct (care este 1/72 dintr-un inci), deci 1 /1440 dintr-un inci.

Ca s putei face o comparaie ntre modul de mapare MM_TEXT i aceste rezoluii, trebuie s v
amintesc faptul c, pe un monitor VGA standard, fiecare pixel este un ptrat cu latura de 0,325 mm,
ceea ce nseamn c coordonatele unui dispozitiv VGA sunt mult mai grosiere dect oricare dintre
modurile de mapare metrice.
Pentru o imprimant laser cu rezoluia de 300 dpi (puncte pe inci) fiecare pixel are 0,0033 inci - o
rezoluie mai mare dect cea a modurilor de mapare MM_LOENGLISH si MM_LOMETRIC, dar mai
mic dect cea a modurilor de mapare MM_HIENGLISH, MM_TWIPS i MM_HIMETRIC.
Originile i extensiile prestabilite sunt urmtoarele:
Originea ferestrei:
Originea vizorului:
Extensia ferestrei:
Extensia vizorului:

(0,0)
(0,0)
(?, ?)
(?, ?)

Poate fi modificat
Poate fi modificat
Nu poate fi modificat
Nu poate fi modificjat

Moduri de mapare proprii


Ultimele dou moduri de mapare se numesc MM_ISOTROPIC i MM_ANISOTROPIC. Acestea
sunt singurele moduri de mapare care v permit s modificai extensiile ferestrei i ale vizorului, ceea
ce nseamn c v permit s modificai factorul de scalare pe care Windows l folosete pentru
convertirea coordonatelor logice i a coordonatelor de dispozitiv. Cuvntul izotrop" nseamn egal n
toate direciile"; anizotrop" este antonimul acestuia. Ca i modurile de mapare metrice prezentate mai
nainte, MM_ISOTROPIC folosete axe scalate egal. Unitile logice de pe axa x au aceeai
dimensiune fizic ca i unitile logice de pe axa y. Acest fapt v ajut s creai imagini care pstreaz
raportul corect de afiare, indiferent de raportul de afiare al dispozitivului.
Diferena dintre modurile de mapare metrice i modul de mapare MM_ISOTROPIC const n
faptul c putei s controlai dimensiunea fizic a unitilor logice. Dac dorii, putei s ajustai
dimensiunea fizic a unitilor logice n funcie de dimensiunea zonei client, astfel nct imaginile pe
care le desenai s fie ntotdeauna coninute de zona client, mrindu-se i micorndu-se corespunztor.
Programul ANACLOCK (ceasul analogic) din Capitolul 7 este un exemplu de imagine izotrop.
Ceasul este ntotdeauna rotund. Dac redimensionai fereastra, ceasul se redimen-sioneaz automat. Un
program Windows poate s manipuleze redimensionarea unei imagini prin ajustarea extensiilor
ferestrei i ale vizorului. Apoi programul poate s foloseasc aceleai uniti logice la apelarea
funciilor de desenare, indiferent de dimensiunea ferestrei.
Uneori, modurile de mapare metrice i modul MM_TEXT sunt numite moduri de mapare complet
restricionate" (fully constrained"). Aceasta nseamn c nu putei s modificai extensiile ferestrei i
ale vizorului sau modul n care Windows scaleaz coordonatele logice fa de coordonatele de

dispozitiv. MM_ISOTROPIC este un mod de mapare partial restricionat" (partly constrained").


Windows v permite s modificai extensiile ferestrei i ale vizorului, dar le ajusteaz astfel nct
unitile logice x i y s aib aceleai dimensiuni fizice. Modul de mapare MM_ANISOTROPIC este
nerestricionat". Putei s modificai extensiile ferestrei i ale vizorului, fr ca Windows s mai fac
vreo ajustare a valorilor.
Modul de mapare MM_ISOTROPIC

Modul de mapare MM_ISOTROPIC este ideal pentru folosirea unor axe arbitrare, cu uniti logice
egale pe cele dou axe. Dreptunghiurile cu limi i nlimi logice egale sunt afiate ca ptrate.
Elipsele cu limi i nlimi logice egale sunt afiate ca cercuri.
Atunci cnd selectai pentru prima dat modul de mapare MM_ISOTROPIC, Windows folosete
aceleai extensii pentru fereastr i pentru vizor, ca i pentru modul de mapare MM_LOMETRIC.
(Totui, nu v bazai pe acest fapt.) Diferena este c acum putei s schimbai extensiile dup cum
dopi, apelnd funciile SetWindowExtEx i SetViewportExtEx. Windows va ajusta apoi aceste extensii
astfel nct unitile logice de pe ambele axe s reprezinte distane fizice egale.
n general, vei folosi ca parametri ai funciei SetWindowExtEx dimensiunile dorite pentru fereastra
logic, iar ca parametri ai funciei SetViewportExtEx dimensiunile reale ale zonei client. Atunci cnd
ajusteaz aceste extensii, Windows trebuie s ncadreze fereastra logic n vizorul fizic, ceea ce
nseamn c o parte a zonei client poate s rmn n afara ferestrei logice. Pentru folosirea mai
eficient a spaiului din zona client trebuie s apelai funcia SetWindowExtEx nainte de apelarea
funciei SetViewportExtEx.
De exemplu, s presupunem c vrei s folosii un sistem de coordonate virtual, tradiional", cu un
singur cadran n care punctul (0, 0) este colul din stnga-jos al zonei client, iar limea i nlimea au
valori de la 0 la 32.767. Dac dorii ca unitile logice x i y s aib aceleai dimensiuni, iat ce trebuie
s facei:
SetMapMode (hdc, HH_ISOTROPIC) ;
SetWindowExtEx (hdc, 32767, 32767, NULL) ;
SetViewportExtEx (hdc, cxClient, -cyClient, NULL) ;
SetViewportOrgEx (hdc, 0, cyClient, NULL) ;

Dac apoi obinei extensiile ferestrei i ale vizorului apelnd funciile GetWindowExtEx i
GetViewportExtEx vei vedea c acestea au alte valori dect cele specificate. Windows ajusteaz
extensiile n funcie de raportul de afiare (aspect ratio) al dispozitivului, astfel nct unitile logice de
pe cele dou axe s reprezinte aceleai dimensiuni fizice.
Dac zona client este mai mult lat dect nalt (n dimensiuni fizice), Windows ajusteaz extensia
x astfel nct fereastra logic s fie mai mic dect vizorul zonei client. Fereastra logic va fi
poziionat n partea stng a zonei client:

Nu putei s afiai nimic n partea dreapt a zonei client dincolo de captul axei x, deoarece pentru
aceasta ar trebui s folosii o coordonat logic x mai mare de 32.767. Dac zona client este mai mult
nalt dect lat (n dimensiuni fizice), Windows ajusteaz extensia y. Fereastra logic va fi poziionat
n partea de jos a zonei client:

Nu putei s afiai nimic n partea de sus a zonei client dincolo de captul axei y, deoarece pentru
aceasta ar trebui s folosii o coordonat logic y mai mare de 32.767. Dac preferai ca fereastra
logic s fie poziionat ntotdeauna n partea stng i n partea de sus a zonei client, putei s
modificai astfel codul precedent:
SetMapMode (hdc, HH_ISOTROPIC) ;
SetWindowExtEx (hdc, 32767, 32767, NULL) ;
SetViewportExtEx (hdc, cxClient, -cyClient, NULL) ;
SetWindowOrgEx (hdc, 0, 32767, NULL) ;

n acest fel, prin apelul funciei SetWihdowOrgEx precizm c dorim ca punctul logic (0,32767) s
fie mapat la punctul de dispozitiv (0,0). Dac zona client este mai mult nalt dect lat, sistemul de
coordonate este poziionat astfel:

Pentru imaginile de genul celei folosite de programul ANACLOCK putei s folosii un sistem de
coordonate cartezian cu patru cadrane avnd axe arbitrar scalate n cele patru direcii i cu punctul
de coordonate (0, 0) n centrul zonei client. Dac, de exemplu, vrei ca fiecare ax s ia valori de la
0 la 1000, folosii codul urmtor:
SetMapMode (hdc, MM_ISOTROPIC) ;
SetWindowExtEx (hdc, 1000, 1000, NULL);
SetViewportExtEx (hdc, cxClient/2, -cyClient/2, NULL) ;
SetViewportOrgEx (hdc, cxClient/2, cyCllent/2, NULL) ;

Dac zona client este mai mult lat dect nalt, sistemul logic de coordonate arat astfel:

Sistemul logic de coordonate este centrat i atunci cnd zona client este mai mult nalt dect lat:

Reinei faptul c extensiile ferestrei i ale vizorului nu implic nici o operaie de decupare. La
apelarea funciilor GDI putei s folosii pentru coordonatele x i y valori mai mici de -1000 sau mai
mari de +1000. n funcie de forma zonei client, aceste puncte pot s fie sau s nu fie vizibile.
Folosind modul de mapare MM_ISOTROPIC putei s facei ca unitile logice s fie mai mari
dect pixelii. De exemplu, s presupunem c dorii s creai un sistem de coordonate n care punctul de
coordonate (0, 0) se afl n colul din stnga-sus al ecranului i valorile de pe axa y cresc de sus n jos
(ca n modul de mapare MM_TEXT) dar cu coordonate logice msurate n uniti de 1/16 dintr-un inci.
Acest mod de mapare v-ar permite s desenai o rigl avnd un capt n colul din stnga-sus al zonei
client, cu diviziuni de aisprezecimi de inci:
SetMapMode (hdc, MM_ISOTROPIC) ;
SetWindowExtEx(hdc, 160*GetDeviceCaps (hdc, HORZSIZE)/254,160*GetDeviceCaps(hdc, VERTSIZE)/254, NULL);
SetViewportExtEx(hdc, GetDeviceCaps(hdc, HORZRES),GetDeviceCaps(hdc, VERTRES), NULL);

n aceast secven de cod extensiile vizorului sunt stabilite la dimensiunile n pixeli ale ntregului
ecran. Extensiile ferestrei trebuie s fie stabilite la dimensiunile ntregului ecran n uniti de
aisprezecimi de inci. Indicii HORZSIZE i VERTSIZE ai funciei GetDeviceCaps returneaz
dimensiunile dispozitivului n milimetri. Dac lucrai cu numere n virgul mobil, trebuie s
transformai milimetrii n inci mprind valorile obinute la 2,54, i apoi s transformai incii n
aisprezecimi de inci nmulind rezultatul operaiei anterioare cu 16. Deoarece aici lucrm cu numere
ntregi, am nmulit rezultatul cu 160 i l-am mprit la 254.
Pentru majoritatea dispozitivelor, acest cod face ca unitile logice s fie mult mai mari dect
unitile fizice. Tot ce desenai pe dispozitiv va avea pentru coordonate valori mapate la multipli de
1/16 inci. Nu putei s desenai dou linii orizontale aflate la distana de 1/32 de inci, deoarece pentru
aceasta ai avea nevoie de o coordonat logic fracionar.
Modul de mapare MM_ANISOTROPIC sau ajustarea imaginii
Atunci cnd stabilii extensiile ferestrei i pe ale vizorului n modul de mapare MM_ISOTROPIC,
Windows ajusteaz valorile astfel nct unitile logice de pe cele dou axe s aib aceleai dimensiuni.
n modul de mapare MM_ANISOTROPIC, Windows nu face nici o ajustare a valorilor pe care le
stabilii. Aceasta nseamn c n modul de mapare MM_ANISOTROPIC nu este obligatorie pstrarea
raportului corect de afiare.
Pentru a folosi modul de mapare MM_ANISOTROPIC, stabilii un sistem arbitrar de coordonate
pentru zona client, ca i pentru modul de mapare MM_ISOTROPIC. Codul de mai jos stabilete
punctul de coordonate (0, 0) n colul din stnga-jos al zonei client, iar axele de coordonate x i y pot
lua valori de la 0 la 32.767:
SetMapMode (hdc, MM_ANISOTROPIC) ;
SetWindowExtEx (hdc, 32767, 32767, NULL) ;
SetViewportExtEx (hdc, cxClient, -cyClient, NULL) ;
SetViewportOrgEx (hdc, 0, cyClient, NULL) ;

65.

Modurile de mapare. Coordonate de dispozitiv i coordonate logice. Sistemele de coordonate ale


dispozitivului. Vizorul i fereastra. Folosirea modului de mapare MM_TEXT. .
. . .
MM_TEXT.

Modurile de mapare
Pn acum am presupus c toate desenele se fac ntr-un sistem de coordonate raportate la colul,
din stnga-sus al zonei client i folosind ca unitate de msur pixelul. Acesta este modul de lucru
prestabilit, dar nu este singurul mod de lucru.
Un atribut al contextului de dispozitiv care afecteaz aproape toate operaiile de desenare din zona
client este modul de mapare" (mapping mode"). Alte patru atribute ale contextului de dispozitiv originea ferestrei, originea vizorului (viewport), extensia ferestrei i extensia vizorului - sunt strns
legate de modul de mapare.
Majoritatea funciilor GDI primesc coordonate sau dimensiuni ca parametri. Iat, ca exemplu,
funcia TextOut:
TextOut (hdc, x, y, szBuffer, iLength) ;

Parametrii x i y indic poziia n care ncepe textul. Parametrul x reprezint poziia pe axa
orizontal, iar parametrul y reprezint poziia pe axa vertical. Deseori, pentru indicarea acestui punct
este folosit notaia (x, y).
n funcia TextOut i, de fapt, n toate funciile GDI, coordonatele sunt furnizate n uniti logice".
Windows trebuie s transforme unitile logice" n uniti de dispozitiv", adic n pixeli. Aceast
transformare este guvernat de modul de mapare, de originile ferestrei, ale vizorului i de extensiile
ferestrei i ale vizorului. De asemenea, modul de mapare stabilete i orientarea axelor x i y, adic
determin sensul n care cresc valorile coordonatelor x i y.
Windows definete opt moduri de mapare. Acestea sunt prezentate n tabelul urmtor, folosind
identificatorii definii n fiierele antet din Windows:
Mod de mapare
MM_TEXT
MM_LOMETRIC
MM_HIMETRIC
MM_LOENGLISH
MM_HIENGLISH
MM_TWIPS
MM_ISOTROPIC
MM_ANISOTROPIC

Uniti logice
Pixel
0,1 mm
0,01mm
0,01 mei
0,001 inci
1/1440 inci
Arbitrar (x = y)
Arbitrar (x != y)

Creterea valorilor axax axay


Spre dreapta
n jos
n sus
Spre dreapta
Spre dreapta
n sus
Spre dreapta
n sus
Spre dreapta
nsus
Spre dreapta
n sus
Selectabil
Selectabil
Selectabil
Selectabil

Putei s selectai modul de mapare folosind funcia SetMapMode:


SetMapMode (hdc, iMapHode) ;

unde iMapMode este unul dintre cei opt identificatori definii pentru modurile de mapare. Putei s
obinei modul de mapare curent folosind funcia GefMapMode:
iMapMode = GetMapMode (hdc) ;

Twip este un cuvnt fabricat, care nseamn a douzecea parte dintr-un punct" (twentieth of a point"). Un punct - unitate de msur folosit n
tipografie - este aproximativ egal cu 1/72 dintr-un inci, dar n sistemele grafice precum GDI se consider de cele mai multe ori c este exact 1/72 dintr-un
inci. Un twip este 1/20 dintr-un punct, deci 1/1440 dintr-un inci.

Modul de mapare prestabilit este MM_TEXT. n acest mod de mapare unitile logice sunt aceleai
cu unitile fizice, ceea ce v permite (sau, privind dintr-o alt perspectiv, v foreaz) s lucrai n
pixeli. ntr-un apel al funciei TextOut care arat astfel:
TextOut (hdc, 8, 16, szBuffer, iLength) ;

textul ncepe la o distan de opt pixeli fa de marginea din stnga a zonei client i de 16 pixeli fa de
marginea de sus a acesteia.
Dac modul de mapare este MM_LOENGLISH, o unitate logic este egal cu o sutime de inci:
SetMapHode (hdc, HM_LOENGLISH) ;

Acum apelul de mai sus al funciei TextOut trebuie s arate astfel:


TextOut (hdc, 50, -100, szBuffer, iLength) ;

Textul afiat ncepe la 0,5 inci fa de marginea din stnga i la 1 inci fa de marginea de sus a
zonei client. (Motivul folosirii unei valori negative pentru coordonata y va deveni evident ceva mai
trziu, atunci cnd vom discuta n detaliu despre modurile de mapare.) Celelalte moduri de mapare
permit programului s specifice coordonatele n milimetri, n puncte pentru imprimant sau ntr-un
sistem de coordonate arbitrar.
Dac vi se pare convenabil folosirea pixelilor ca unitate de msur, putei s folosii numai modul
de mapare MM_TEXT. Dac trebuie s afiai o imagine la dimensiunile reale n inci sau milimetri,
putei s obinei informaiile necesare cu ajutorul funciei GetDeviceCaps i s facei singur scalarea.
Celelalte moduri de mapare sunt doar metode convenabile de evitare a acestor operaii de scalare.
Indiferent de modul de mapare folosit, toate coordonatele specificate la apelarea funciilor
Windows trebuie s fie numere ntregi cu semn avnd valori de la -32 768 la 32 767. n plus, unele
funcii care folosesc coordonate pentru punctele de nceput i de sfrit ale unui dreptunghi cer ca
limea i nlimea dreptunghiului s nu depeasc 32 767.
Coordonate de dispozitiv i coordonate logice

S-ar putea s v punei urmtoarea ntrebare: Dac folosesc modul de mapare MM_LOENGLISH
voi primi mesajele WM_SIZE n sutimi de inci?" Bineneles c nu. Windows va folosi n continuare
coordonatele de dispozitiv pentru toate mesajele (cum ar fi WM_SIZE, WM_MOVE i
WM_MOUSEMOVE), pentru toate funciile care nu fac parte din interfaa GDI i chiar pentru unele
funcii GDI. Lucrurile se petrec n felul urmtor: modul de mapare fiind un atribut al contextului de
dispozitiv, are efect numai atunci cnd folosii funcii GDI care primesc o variabil handle a
contextului de dispozitiv ca parametru. GetSystemMetrics nu este o funcie GDI, aa c va returna n
continuare dimensiunile n uniti de dispozitiv, adic n pixeli. Dei GetDeviceCaps este o funcie
GDI care primete ca parametru o variabil handle a contextului de dispozitiv, Windows continu s
returneze uniti de dispozitiv pentru identificatorii HORZRES i VERTRES, deoarece unul dintre
scopurile acestei funcii este s furnizeze programului dimensiunea n pixeli a dispozitivului.
Totui, valorile din structura TEXTMETRIC pe care le obinei prin apelarea funciei
GetTextMetrics sunt furnizate n uniti logice. Dac modul de mapare este MM_LOENGLISH n
momentul apelrii funciei, GetTextMetrics returneaz limea i nlimea caracterelor, n sutimi de
inci. Atunci cnd apelai funcia GetTextMetrics ca s obinei nlimea i limea caracterelor, modul
de mapare trebuie s fie acelai cu cel pe care l vei folosi atunci cnd afiai textul pe baza acestor
dimensiuni. Pe msur ce voi prezenta diferite funcii GDI n acest capitol, voi preciza dac acestea
utilizeaz coordonate logice sau coordonate de dispozitiv. Toate funciile despre care am discutat pn
acum utilizeaz coordonate logice, exceptnd cele pentru stabilirea spaiilor ntre puncte sau liniue
pentru stilurile de linii i ntre liniile de haur din modele. Acestea sunt independente de modul de
mapare.
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 stngasus 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
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. Aceste funcii v furnizeaz
suficiente informaii ca s transferai coordonatele ntre oricare dintre sistemele de coordonate de
dispozitiv.
66.

Obinerea informaiilor despre culori. PLANES, BITSPIXEL, NUMCOLORS: Tipul COLORREF.


. PLANES, BITSPIXEL, NUMCOLORS: COLORREF.
Obinerea informaiilor despre culori

Pentru afiarea culorilor este nevoie de mai muli bii. Cu ct se folosesc mai muli bii, cu att pot
fi afiate mai multe culori. Sau, mai precis, numrul culorilor care pot fi afiate simultan este egal cu 2
la o putere egal cu numrul de bii folosii. De obicei, biii sunt organizai n planuri de culori - un
plan pentru rou, un plan pentru verde, unul pentru albastru i unul pentru intensitatea culorii.
Adaptoarele video cu 8,16 sau 24 de bii pentru fiecare pixel au un singur plan de culoare, n care un
numr de bii adiaceni reprezint culoarea fiecrui pixel.
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);

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);

De exemplu, cele dou numere vor fi diferite pentru majoritatea plotterelor. n cazul unui plotter,
PLANES i BITSPIXEL vor avea valoarea 1, dar NUMCOLORS va reprezenta numrul de penie pe
care le folosete plotterul. Pentru dispozitivele monocrome, funcia GetDeviceCaps apelat cu
parametrul NUMCOLORS returneaz valoarea 2.
107PARTEA 1 NCEPUTUL
Aceste valori pot fi diferite i n cazul adaptoarelor video care permit ncrcarea paletelor de culori.
Funcia GetDeviceCaps apelat cu parametrul NUMCOLORS returneaz numrul de culori rezervate
de Windows, adic 20. Celelalte 236 de culori pot fi stabilite de program folosind un manager de
palete.
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).

Figura 4-3. Valoarea pe 32 de bii folosita pentru reprezentarea culorilor.


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:
#define RBG (r, g, b) ((COLORREF)(((BYTE)(r)|\
((WORD)(g)<<8))|\
(((DWORD) (BYTE) (b))<<16)))

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. Aceste macroinstructiuni sunt utile atunci cnd apelai funcii Windows care returneaz
culori RGB.
Numrul de culori returnat de funcia GetDeviceCaps reprezint numrul de culori pure pe care le
poate afia dispozitivul respectiv. Windows poate s foloseasc amestecarea culorilor - aceasta implic
folosirea unui model de pixeli de diferite culori - pentru reprezentarea altor culori n afara celor pure.
Nu toate combinaiile de valori pentru rou, verde i albastru produc modele diferite de amestecare a
culorilor. De exemplu, n cazul unui monitor VGA pe care pot fi afiate 16 culori, valorile pentru rou,
verde i albastru trebuie s fie incrementate cu patru, ca s genereze un model diferit de amestecare. Ca
urmare, pentru aceste tipuri de adaptoare avei la dispoziie 218 (sau 262.144) culori amestecate.
Putei s determinai cea mai apropiat culoare pur pentru o anumit valoare apelnd funcia
GetNearestColor:
rgbPureColor = GetNearestColor (hdc, rgbColor) ;

67.

Obinerea variabilei handle a contextului de dispozitiv. Obinerea informaiilor despre contextul de dispozitiv.

Obinerea variabilei handle a contextului de dispozitiv


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);
[alte Unii 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. Structura PAINTSTRUCT conine i o structur de tip
RECT numit rcPaint, care definete dreptunghiul ce cuprinde regiunea invalid a zonei client a
ferestrei. 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);

Contextul de dispozitiv include, n afar de zona client, bara de titlu a ferestrei, barele de derulare
i chenarul. Funcia GetWindowDC este rareori folosit de aplicaii. Dac vrei s experimentai
folosirea acestei funcii, trebuie s interceptai mesajele WM_NCPAINT (nonclient paint"),
mpiedicnd sistemul de operare s redeseneze poriunile din fereastr care nu fac parte din zona client.
Funciile BeginPaint, GetDC i GetWindowDC obin variabila handle a contextului de dispozitiv
asociat unei anumite ferestre de pe ecran. O funcie mai general pentru obinerea variabilei handle a
unui context de dispozitiv este CreateDC:
hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData);
[alte linii de program] DeleteDC (hdc);

De exemplu, putei s obinei variabila handle a contextului de dispozitiv pentru tot spaiul de
afiare, cu urmtorul apel:
hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);

Scrierea n afara ferestrei proprii nu este n general recomandat, dar poate fi convenabil pentru
unele aplicaii speciale. (Dei aceast metod nu e documentat, se poate obine o variabila handle a
contextului de dispozitiv pentru ntregul ecran i prin apelarea funciei GetDC, cu parametrul NULL.)
n Capitolul 15 vom folosi funcia CreateDC pentru a obine o variabil handle a contextului de
dispozitiv pentru o imprimant.
Uneori avei nevoie de unele informaii despre un context de dispozitiv fr s desenai nimic. n
aceast situaie putei s obinei o variabila handle a contextului de informaii (information context")
folosind funcia CreateIC. Parametrii sunt aceiai ca i pentru funcia CreateDC:
hdclnfo = CreatelC ("DISPLAY", NULL, NULL, NULL);
[alte linii de program] DeleteDC (hdclnfo);

Nu putei s executai operaii de scriere la un dispozitiv folosind aceast variabil handle. Atunci
cnd lucrai cu imagini bitmap, poate fi uneori util obinerea unui context de dispozitiv n memorie":

hdcMem = CreateCompatibleDC (hdc);


[alte linii de program] DeleteDC (hdcHem)

Acesta este un concept destul de abstract. n esen, putei s selectai o imagine bitmap ntr-un
context de dispozitiv n memorie i apoi s desenai peste folosind funciile GDI. Vom discuta mai
trziu despre aceast tehnic i o vom folosi n programul GRAFMENU din Capitolul 10.
Aa cum am menionat mai devreme, un metafiier este o colecie de apeluri GDI codificate ntr-o
form binar. Putei s creai un metafiier prin obinerea unui context de dispozitiv pentru metafiiere:
hdcMeta = CreateMetaFile (pszFilename);
[alte linii de program] hmf = CloseMetaFile (hdcMeta);

Ct timp acest context este valid, nici un apel GDI pe care l facei folosind parametrul hdcMeta nu
afieaz nimic pe ecran, ci devine parte a metafiierului. Apelai apoi funcia CloseMetaFile i
contextul de dispozitiv este invalidat. Funcia returneaz o variabil handle a metafiierului (hmf).
Obinerea informaiilor despre contextul de dispozitiv

Un context de dispozitiv se refer, de obicei, la un dispozitiv fizic de ieire, cum ar fi un monitor


video sau o imprimant. Dac avei nevoie de anumite informaii despre acest dispozitiv, cum ar fi
dimensiunile ecranului (dimensiunile n pixeli i cele fizice) sau posibilitile de folosire a culorilor,
putei s le obinei prin apelarea funciei GetDeviceCaps (get device capabilities"):
iValue = GetDeviceCaps (hdc, iIndex) ;

Parametrul iIndex este unul dintre cei 28 de identificatori definii n fiierele antet din Windows.
De exemplu, dac iIndex are valoarea HORZRES funcia GetDeviceCaps returneaz limea
dispozitivului n pixeli; VERTRES returneaz nlimea dispozitivului n pixeli. Dac hdc este o
variabil handle a contextului de dispozitiv pentru un monitor video, informaiile obinute sunt aceleai
cu cele returnate de funcia GetSystemMetrics. Dac hdc este o variabil handle a contextului de
dispozitiv pentru o imprimant, funcia GetDeviceCaps returneaz nlimea i limea zonei pe care
imprimant o poate tipri.
Putei s folosii funcia GetDeviceCaps i ca s obinei informaii despre posibilitile unui
dispozitiv de prelucrare a anumitor tipuri de elemente grafice. Aceast posibilitate nu este important
pentru ecran, dar poate fi folosit n cazul imprimantelor. De exemplu, majoritatea plotterelor nu pot
tipri imagini bitmap - iar funcia GetDeviceCaps v poate comunica acest lucru.
68.

69.

Parametrul PitchAndFamily. Funcia SetTextAlign. PitchAndFamily. SetTextAlign.

Funcii care stabilesc sau obin atribute ale contextului de dispozitiv. Un atribut" al contextului
de dispozitiv specific modul de lucru al funciilor de desenare. De exemplu, folosii funcia
SetTextColor ca s precizai culoarea textului afiat cu funcia TextOut (sau cu o alt funcie de
afiare a textului). n programele SYSMETS din Capitolul 3 am folosit funcia SetTextAlign ca s
artm interfeei GDI faptul c poziia de nceput a irului de caractere este n partea dreapt a
irului de caractere, nu n partea stng, aa cum se ntmpl de obicei. Toate atributele contextului
de dispozitiv au valori prestabilite, care devin active la obinerea contextului de dispozitiv. Pentru
fiecare funcie de tip Set exist i o funcie Get corespondent, folosit pentru obinerea valorilor
curente ale atributelor contextului de dispozitiv.
Pensule haurate". Stiluri de haura. Funcia CreatePatternBrush. .
. CreatePatternBrush.

Atunci cnd Windows folosete metoda amestecrii culorilor (dithering) pentru afiarea unui
numr mai mare de culori dect ar fi n mod normal disponibile pe monitorul respectiv, de fapt
folosete o pensul pentru fiecare culoare. Pe un ecran monocrom, Windows poate s afieze 64 de

tonuri de gri prin amestecarea pixelilor pentru alb cu cei pentru negru. Pentru negru toi biii din
matricea 8x8 au valoarea zero. Unul dintre cei 64 de bii are valoarea 1 (adic alb) pentru primul ton de
gri, doi bii au valoarea 1 pentru al doilea ton de gri i aa mai departe, pn cnd toi cei 64 de bii au
valoarea 1 ca s se obin albul pur. n cazul unui monitor color, culorile amestecate sunt tot imagini
bitmap, dar domeniul disponibil de culori este mult mai mare.
Windows conine patru funcii pe care putei s le folosii pentru crearea pensulelor logice.
Selectai o pensul n contextul de dispozitiv folosind funcia Select-Object. Ca i peniele logice,
pensulele logice sunt obiecte GDI. Trebuie s tergei toate pensulele pe care le-ai creat, dar nu trebuie
s le tergei ct timp sunt selectate n contextul de dispozitiv.
Iat prima funcie pentru crearea unei pensule logice:
hBrush = CreateSolidBrush (rgbColor) ;

Cuvntul Solid din numele acestei funcii nu nseamn c pensula folosete o culoare pur. Atunci
cnd selectai pensula n contextul de dispozitiv, Windows creeaz o imagine bitmap 8x8 pentru
culorile amestecate i folosete imaginea respectiv atunci cnd este necesar pensula selectat.
Putei s creai i o pensul haurat" cu linii orizontale, verticale sau oblice. Acest stil de pensule
este folosit frecvent pentru colorarea barelor din diagrame sau grafice i pentru desenele executate de
plottere. Funcia care creeaz o pensul haurat este:
hBrush = CreateHatchBrush (iHatchStyle, rgbColor) ;

Parametrul iHatchStyle precizeaz aspectul haurii i poate avea una dintre urmtoarele valori:
HS_HORIZONTAL, HS_VERTICAL, HS_FDIAGONAL, HS_BDIAGONAL, HS_CROSS i
HS_DIAGCROSS. Figura 4-18 prezint haurile produse de fiecare dintre stilurile de mai sus.
Parametrul rgbColor din funcia CreateHatchBrush reprezint culoarea liniilor cu care se face
haurarea. Atunci cnd selectai pensula n contextul de dispozitiv, Windows convertete aceast
culoare n cea mai apropiat culoare pur. Spaiul dintre liniile de haur sunt colorate n funcie de
modul de desenare a fondului i de culoarea fondului, definite n contextul de dispozitiv. Dac modul
de desenare a fondului este OPAQUE, culoarea fondului (care este convertit, la rndul ei, ntr-o
culoare pur) este folosit pentru umplerea spaiilor dintre linii, n acest caz, nici liniile de haur, nici
culoarea de umplere nu pot fi culori amestecate. Dac modul de desenare a fondului este
TRANSPARENT, Windows deseneaz liniile de haura fr s umple spaiile dintre acestea.

Figura 4-18. Cele ase stiluri de haura.


Deoarece pensulele sunt ntotdeauna imagini bitmap 8x8, aspectul pensulelor haurate va depinde
de rezoluia dispozitivului pe care se face afiarea. Fiecare dintre haurile din Figura 4-18 a fost
desenat ntr-un dreptunghi de 32x16 pixeli, ceea ce nseamn c imaginea bitmap 8x8 a fost repetat
de patru ori pe orizontal i de dou ori pe vertical. Pe o imprimant laser cu rezoluia 300 dpi (dots
per inch) acelai dreptunghi de 32x16 pixeli ar ocupa o suprafa cu nlimea de 1 /9 inci si limea de
1/19 inci.
Cu ajutorul funciei CreatePatternBrush putei s creai pensule proprii, bazate pe o imagine
bitmap:
hBrush = CreatePatternBrush (hBitmap) ;

Vom discuta despre aceast funcie n seciunea rezervat imaginilor bitmap din capitolul de fa.
Windows conine o funcie care poate nlocui toate celelalte trei funcii de creare a pensulelor
(CreateSolidBrush, CreateHatchBrush i CreatePatternBrush):

hBrush = CreateBrushIndirect (&logbrush) ;

Variabila logbrush este o structur de tip LOGBRUSH (logical brush"). Cele trei cmpuri ale
structurii sunt prezentate mai jos. Valoarea cmpului lbStyle determin modul n care Windows
interpreteaz celelalte dou cmpuri:
lbStyle (UINT)
lbColor (COLORREF) lbHatch (LONG)
BS_SOLID
Culoarea pensulei
Ignorat
BS_HOLLOW
Ignorat
Ignorat
BS_HATCHED Culoarea haurii
Stilul de haur
BS_PATTERN
Ignorat
Variabila handle a unei imagini bitmap
Am folosit mai devreme funcia SelectObject ca s selectm n contextul de dispozitiv o peni
logic, funcia DeleteObject ca s tergem o peni logic i funcia GetObject ca s obinem informaii
despre o peni logic. Putei s folosii aceleai funcii i pentru pensule. Dac avei o variabil handle
a unei pensule, putei s selectai pensula n contextul de dispozitiv folosind funcia SelectObject:
SelectObject (hdc, hBrush) ;

O pensul creat poate fi tears cu ajutorul funciei DeleteObject:


DeleteObject (hBrush) ;

Totui, nu tergei pensula selectat n contextul de dispozitiv. Dac vrei s obinei informaii
despre o pensul, apelai funcia GetObject:
GetObject (hBrush, sizeof (LOGBRUSH), (LPVOID) &logbrush) ;

unde variabila logbrush este o structur de tip LOGBRUSH (logical brush").


70.

Redesenarea zonei client. Ciclul de mesaje. Structura de tip MSG. Funciile GetMessage, TranslateMessage,
DispatchMessage.
. . MSG.
GetMessage, TranslateMessage, DispatchMessage.

UpdateWindow (hwnd) ;
determin redesenarea zonei client. Acest lucru se face prin trimiterea ctre procedura de fereastr
(funcia WndProc din HELLOWIN.C) a unui mesaj WM_PAINT. Vom vedea imediat cum trateaz
funcia WndProc aceste mesaje.

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.
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. Windows completeaz
cmpurile structurii de mesaje cu urm torul mesaj din coada de ateptare. Cmpurile acestei structuri
sunt:
hwnd - variabila handle a ferestrei creia i este destinat mesajul. n pro gramul HELLOWIN,
aceasta este aceeai cu valoarea hwnd returnat de funcia CreateWindow, deoarece aceasta este
singura fereastr a programului.
message - identificatorul mesajului. Acesta este un numr folosit pentru identificarea mesajului.
Pentru fiecare mesaj n fiierele antet din Windows este definit un identificator care ncepe cu
prefixul WM_ (window message"). De exemplu, dac poziionai indicatorul mouse-ului n zona
client a programului HELLOWIN i apsai butonul din stnga, Windows va insera n coada de
ateptare un mesaj pentru care cmpul message conine identificatorul WM_LBUTTONDOWN,
adic valoarea 0x0201.

wParam - un parametru pe 32 de bii a crui valoare depinde de mesajul trimis.


lParam - un alt parametru pe 32 de bii dependent de mesaj.
time - momentul inserrii mesajului n coada de mesaje.
pt - coordonatele poziiei mouse-ului n momentul inserrii mesajului n coada de mesaje.
Dac n cmpul message este transmis orice alt valoare dect WM_QUIT (egal cu 0x0012),
funcia GetMessage returneaz o valoare diferit de zero. Mesajul WM_QUIT determin ieirea din
ciclul de mesaje. Programul se ncheie, returnnd valoarea parametrului wParam al structurii msg.
Instruciunea:
TranslateMessage (&msg) ;
retransmite structura msg sistemului de operare, pentru convertirea unor mesaje de la tastatur. (Vom
discuta mai multe despre aceasta n Capitolul 5.)
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. n programul HELLOWIN, procedura de fereastr este WndProc.
Dup ce prelucreaz mesajul, funcia WndProc pred controlul sistemului de operare, care nc
elaboreaz rspunsul la apelul DispatchMessage. Atunci cnd Windows returneaz controlul
programului HELLOWIN, dup executarea apelului DispatchMessage, ciclul de tratare a mesajelor
continu cu urmtorul apel al funciei GetMessage.
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 ;
Variabila msg este o structur de tip MSG, definit n fiierele antet din Windows astfel:
typedef struct tagMSG
{
HWND hwnd ;
UINT
message ;
WPARAMwParam ;
LPARAM lParam ;
DWORD time ;
POINT pt ;
}
MSG ,
Tipul de date POINT este tot o structur, definit astfel:
typedef struct tagPOINT
{

LONG x ;
LONG y ;
}
POINT ;
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. Windows completeaz
cmpurile structurii de mesaje cu urm torul mesaj din coada de ateptare. Cmpurile acestei structuri
sunt:
hwnd - variabila handle a ferestrei creia i este destinat mesajul. n pro gramul HELLOWIN,
aceasta este aceeai cu valoarea hwnd returnat de funcia CreateWindow, deoarece aceasta este
singura fereastr a programului.
message - identificatorul mesajului. Acesta este un numr folosit pentru identificarea mesajului.
Pentru fiecare mesaj n fiierele antet din Windows este definit un identificator care ncepe cu
prefixul WM_ (window message"). De exemplu, dac poziionai indicatorul mouse-ului n zona
client a programului HELLOWIN i apsai butonul din stnga, Windows va insera n coada de
ateptare un mesaj pentru care cmpul message conine identificatorul WM_LBUTTONDOWN,
adic valoarea 0x0201.
wParam - un parametru pe 32 de bii a crui valoare depinde de mesajul trimis.
lParam - un alt parametru pe 32 de bii dependent de mesaj.
time - momentul inserrii mesajului n coada de mesaje.
pt - coordonatele poziiei mouse-ului n momentul inserrii mesajului n coada de mesaje.
Dac n cmpul message este transmis orice alt valoare dect WM_QUIT (egal cu 0x0012),
funcia GetMessage returneaz o valoare diferit de zero. Mesajul WM_QUIT determin ieirea din
ciclul de mesaje. Programul se ncheie, returnnd valoarea parametrului wParam al structurii msg.
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. n programul HELLOWIN, procedura de fereastr este WndProc.
Dup ce prelucreaz mesajul, funcia WndProc pred controlul sistemului de operare, care nc
elaboreaz rspunsul la apelul DispatchMessage. Atunci cnd Windows returneaz controlul
programului HELLOWIN, dup executarea apelului DispatchMessage, ciclul de tratare a mesajelor
continu cu urmtorul apel al funciei GetMessage.
71.
72.

Sistemul i cronometrul. Timpul Windows standard. . Windows


Tipul PAINTSTRCUT, MM_TEXT. Regiuni de decupare (clipping region). Fontul sistem SYSTEM_FONT.
PAINTSTRCUT, MM_TEXT. lipping regions. SYSTEM_FONT.

Folosirea modului de mapare MM_TEXT


Pentru modul de mapare MM_TEXT, originile i extensiile prestabilite sunt urmtoarele:
Originea ferestrei:

(0, 0)

Poate fi modificat

Originea vizorului:
Extensia ferestrei:
Extensia vizorului:

(0, 0)
(1, 1)
(1, 1)

Poate fi modificat
Nu poate fi modificat
Nu poate fi modificat

Raportul din extensia ferestrei i extensia vizorului este 1, aa c nu este necesar nici o operaie de
scalare pentru transformarea coordonatelor logice n coordonate de dispozitiv. Formulele prezentate
anterior se reduc la acestea:
xViewport = xWindow - xWinOrg + xViewOrg
yViexport = yWindow - yWinOrg + yViewOrg
Acest mod de mapare se numete mapare de tip text", nu fiindc este cea mai potrivit pentru text,
ci datorit orientrii axelor. n general, citim textul de la stnga spre dreapta i de sus n jos, iar n
modul de mapare MM_TEXT, valorile cresc n acelai sens:

Windows furnizeaz funciile SetViewportOrgEx i SetWindowOrgEx pentru modificarea originii


vizorului i a ferestrei. Aceste funcii au ca efect deplasarea axelor, astfel nct punctul de coordonate
(0, 0) nu se mai refer la colul din stnga-sus al ecranului. n general, vei folosi ori funcia
SetViewportOrgEx, ori SetWindowOrgEx, dar nu pe amndou.
Iat cum lucreaz aceste funcii: dac schimbai originea vizorului la (xViewOrg, yViewOrg), atunci
punctul logic de coordonate (0, 0) va fi mapat la punctul de dispozitiv (xViewOrg, yViewOrg). Dac
schimbai originea ferestrei la (xWinOrg, yWinOrg), atunci punctul logic (xWinOrg, yWinOrg) va fi
mapat la punctul de dispozitiv (0, 0). Indiferent de modificrile pe care le facei asupra originii
ferestrei i a vizorului, punctul de dispozitiv (0, 0) este ntotdeauna colul din stnga-sus al zonei
client.
De exemplu, s presupunem c zona client are limea cxClient i nlimea cyClient. Dac vrei ca
punctul logic de coordonate (0, 0) s se afle n centrul zonei client, putei s apelai funcia urmtoare:
SetViewportOrgEx (hdc, cxClient/2, cyClient/2, NULL) ;

Argumentele funciei SetViewportEx sunt exprimate ntotdeauna n uniti de dispozitiv. Punctul


logic (0, 0) va fi acum mapat la punctul .de dispozitiv (cxClient/2, cyClient/2). Din acest moment
folosii zona client ca i cum ar avea urmtorul sistem de coordonate:

Valorile logice ale axei x sunt cuprinse n intervalul de la -cxClient/2 la +cxClient/2 iar valorile
logice ale axei y sunt cuprinse n intervalul de la -cyClient/2 la +cyClient/2. Colul din dreapta-jos al
zonei client are coordonatele (cxClient/2, cyClient/2). Dac vrei s afiai text ncepnd din colul din

stnga-sus al zonei client, care are coordonatele de dispozitiv (0, 0), trebuie s folosii coordonate
logice negative:
TextOut (hdc, -cxClient/2, -cyClient/2, "Hello", 5) ;

Acelai rezultat poate fi obinut cu ajutorul funciei SetWindowOrgEx n locul funciei


SetViewportOrgEx:
SetWindowOrgEx (hdc, -cxClient/2, -cyClient/2, NULL) ;

Argumentele funciei SetWindowOrgEx sunt exprimate ntotdeauna n coordonate logice. Dup


apelul de mai sus, punctul logic (-cxClient/2, -cyClient/2) este mapat la punctul de dispozitiv (0, 0),
care este colul din stnga-sus al zonei client.
Ceea ce probabil nu dorii s facei (dect dac tii ce rezultat vei obine) este s folosii cele dou
funcii mpreun:
SetViewportOrgEx (hdc, cxClient/2, cyClient/2, NULL) ;
SetWindowOrgEx (hdc, -cxClient/2, -cyClient/2, NULL) ;

Aceasta nseamn c punctul logic (-cxClient/2, -cyClient/2) este mapat la punctul de dispozitiv
(cxClient/2, cyClient/2), rezultnd urmtorul sistem de coordonate:

Putei s obinei originea vizorului apelnd funcia GetViewportOrgEx:


GetViewportOrgEx (hdc, &pt) ;

i originea ferestrei apelnd funcia GetWindowOrgEx:


GetWindowOrgEx (hdc, &pt) ;

unde pt este o structur de tip POINT. Valorile returnate de funcia GetViewportOrgEx sunt n
coordonate de dispozitiv, iar valorile returnate de funcia GetWindowOrgEx sunt n coordonate logice.
Uneori este de dorit s modificai originea ferestrei sau a vizorului ca s deplasai imaginea afiat
pe ecran - de exemplu, ca rspuns la acionarea barei de derulare de ctre utilizator. Modificarea
originii nu determin deplasarea imediat a imaginii afiate. Mai nti modificai originea, apoi
redesenai ecranul. De exemplu, n programul SYSMETS2 din Capitolul 2 am folosit valoarea
iVscrollPos (poziia curent a casetei de derulare de pe bara de derulare vertical) ca s ajustm
coordonatele de afiare pe axa y:
case WM_PAINT :
BeginPaint (hwnd, &ps) ;
for 0 = 0; i<NUMLINES ; i++)
{
y = cyChar * (1 - iVscrollPos + 1) ;
[afieaz textul]
}
EndPaint (hwnd, &ps) ;
return 0 ;

Putem s obinem acelai rezultat cu ajutorul funciei SetWindowOrgEx:


case WM_PAINT :
BeginPaint (hwnd, &ps);
SetWindowOrgEx (ps.hdc, 0, cyChar * iVscrollPos) ;
for (i = 0; i < NUMLINES ; i++)
{

y = cyChar * (1 + i) ;
[afieaz textul]
}
EndPaint (hwnd, &ps) ;
return 0 ;

Acum nu mai este nevoie s fie folosit valoarea iVscrollPos pentru calcularea coordonatei y
pentru funcia TextOut. Aceasta nseamn c putei s apelai funciile de afiare a textului dintr-o
subrutin, fr s transmitei subrutinei valoarea iVscrollPos, deoarece ajustarea poziiei de afiare a
textului s-a fcut prin modificarea originii ferestrei.
Dac ai mai lucrat cu sistemele de coordonate rectangulare (carteziene), probabil deplasarea
punctului logic de coordonate (0, 0) n centrul zonei client vi se pare o operaie logic. Totui, modul
de mapare MM_TEXT prezint o mic problem: de obicei, ntr-un sistem de coordonate cartezian,
valorile de pe axa y cresc n sus, pe cnd n modul de mapare MM_TEXT acestea cresc n jos. In acest
sens, modul de mapare MM_TEXT este un caz izolat, aceast problem fiind corectat de celelalte
cinci moduri de mapare.
Modul de mapare prestabilit este MM_TEXT. n acest mod de mapare unitile logice sunt aceleai
cu unitile fizice, ceea ce v permite (sau, privind dintr-o alt perspectiv, v foreaz) s lucrai n
pixeli. ntr-un apel al funciei TextOut care arat astfel:
TextOut (hdc, 8, 16, szBuffer, iLength) ;

73.

Umplerea golurilor. Modul de desenare a fondului OPAQUE. Funciile SetBkColor, SetBkMode. .


OPAQUE. SetBkColor, SetBkMode.

Umplerea golurilor
Folosirea penielor pentru linii punctate sau pentru linii ntrerupte ridic o ntrebare interesant: ce
se ntmpl cu pauzele dintre puncte sau dintre liniue? Culoarea acestor spaii depinde de atributele
pentru culoarea fondului i de modul de desenare a fondului, definite n contextul de dispozitiv.
Modul prestabilit de desenare a fondului este OPAQUE, ceea ce nseamn c Windows umple
spaiile cu culoarea fondului, care n mod prestabilit este alb. Rezultatele sunt aceleai n cazul
pensulei WHITE_BRUSH, folosit de majoritatea programelor n clasa ferestrei pentru tergerea
fondului.
Putei s schimbai culoarea fondului pentru completarea spaiilor goale dintre linii, prin apelarea
funciei SetBkColor:
SetBkColor (hdc, rgbColor) ;

Ca i n cazul valorii rgbColor folosit pentru culoarea peniei, Windows convertete valoarea
specificat ntr-o culoare pur. Putei s obinei culoarea defint n contextul de dispozitiv prin
apelarea funciei GetBkColor.
De asemenea, putei s mpiedicai colorarea spaiilor stabilind modul TRANSPARENT de
desenare a fondului:
SetBkMode (hdc, TRANSPARENT) ;

Windows va ignora culoarea fondului i nu va mai colora spaiile goale. Modul de desenare a
fondului (TRANSPARENT sau OPAQUE) poate fi obinut cu ajutorul funciei GetBkMode.
74.

Utilizarea cronometrului pentru a realiza un ceas.

FOLOSIREA CRONOMETRULUI PENTRU


IMPLEMENTAREA UNUI CEAS

Un program de afiare a ceasului este cea mai evident aplicaie pentru un cronometru, aa c vom
prezenta un ceas digital i un ceas analogic. Programul DIGCLOCK, prezentat n Figura 7-5, creeaz o
fereastr popup, care se poziioneaz n colul din dreapta-sus al ecranului. Programul afieaz ziua, data i ora,
aa cum se poate vedea n Figura 7-6.
Toate programele prezentate pn acum au folosit pentru cel de-al treilea parametru al funciei
CreateWindow stilul de fereastr WS_OVERLAPPEDWINDOW. n programul DIGCLOCK este folosit
stilul de fereastr:

WS_POPUP | WS_DLGFRAME | WS_SYSMENU


Acest stil creeaz o fereastr popup, cu un chenar ca al casetelor de dialog i un meniu sistem. Acest
stil este folosit n mod frecvent pentru casete de dialog i casete de mesaje, dar mai rar pentru aplicaii.
DIGCLOCK folosete i o alt variant de apelare a funciei ShowWindow.

ShowWindow (hwnd, SW_SHOWNOACTIVATE) ;


n mod normal, fereastra unui program devine activ n momentul rulrii programului.
Identificatorul SW_SHOWNOACTIVATE cere sistemului de operare s lase activat fereastra
programului care a lansat n execuie programul DIGCLOCK. Putei s activai fereastra programului
DIGCLOCK executnd clic pe aceasta sau apsnd tastele Alt+Tab sau Alt+Esc. Dei programul
DIGCLOCK nu are o caset pentru meniul de sistem, avei acces la acest meniu apsnd tastele Alt+bara
de spaiu n timp ce fereastra programului este activ. Dac selectai opiunea Move, putei s mutai
fereastra pe ecran cu ajutorul tastaturii.
75.
76.

Utilizarea cronometrului pentru animaii. timer-a


Utilizarea cronometrului. Prima metod. :

Prima metod
Prima metod (i cea mai simpl) determin sistemul de operare s trimit mesajele
WM_TIMER ctre procedura de fereastr normal a aplicaiei. Apelul funciei SetTimer arat astfel:
SetTimer (hwnd, 1, iMsecInterval, NULL);
Primul parametru este o variabil handle pentru fereastra a crei procedur de fereastr va primi
mesajele WM_TIMER. Al doilea parametru este identificatorul cronometrului, care trebuie s fie o valoare
diferit de zero i care n acest exemplu este n mod arbitrar 1. Al treilea parametru este o valoare ntreag fr
semn pe 32 de bii, care specific intervalul de timp n milisecunde. Dac acest parametru are valoarea
60000, programul va primi un mesaj WM_TIMER la fiecare minut. Putei s oprii generarea mesajelor
WM_TIMER n orice moment, chiar i n timpul prelucrrii unui mesaj WM_TIMER, apelnd funcia:

KillTimer (hwnd, 1);

Al doilea parametru al funciei KillTimer este acelai identificator cu cel folosit la apelarea funciei
SetTimer. naintea terminrii programului, ca rspuns la mesajul WM_DESTROY, este recomandat s
distrugei toate cronometrele active din program.
Atunci cnd procedura de fereastr primete un mesaj WM_TIMER, parametrul wParam conine
identificatorul cronometrului (care n acest caz este 1) iar parametrul lParam este 0. Dac avei nevoie de mai
multe cronometre, folosii un identificator unic pentru fiecare. Valoarea parametrului wParam va diferenia
mesajele WM_TIMER trimise ferestrei. Pentru ca programul s fie mai uor de citit, putei s folosii
instruciuni define pentru definirea identificatorilor fiecrui cronometru:

#define TIMERSEC 1
#define TIMERMIN 2
Apoi putei s creai cele dou cronometre prin apelarea funciei SetTimer:

SetTimer(hwnd, TIMERSEC, 1000, NULL);


SetTjmer (hwnd, TIMERMIN, 60000, NULL);
Logica de prelucrare a mesajului WM_TIMER poate s arate astfel:

case WM_TIMER :
switch (wParam)
{
case TIMERSEC :
[operaii de prelucrare la fiecare secunda]
break ;
case TIMERMIN :

[operaii de prelucrare la fiecare minut]


break ;
}
return 0 ;
Dac vrei s schimbai intervalul de timp al unui cronometru existent, oprii cronometrul i apelai
din nou funcia SetTimer:

KillTimer (hwnd, 1);


SetTimer (hwnd, 1, iMsecInterval, NULL);
Parametrul iMsecInterval reprezint noul interval de timp, n milisecunde. Putei s folosii aceast tehnic
ntr-un program care conine o opiune de afiare a secundelor. Nu trebuie dect s schimbai intervalul de
msurare al cronometrului de la 1000 ms la 60000 ms.

77.

Utilizarea cronometrului. Metoda a doua. :

Prima metod de folosire a cronometrelor determin trimiterea mesajelor WM _TIMER ctre procedura
normal de fereastr. A doua metod v permite s folosii un cronometru astfel nct Windows s trimit
mesajele WM_TIMER ctre o alt funcie din program.
Funcia care recepioneaz mesajele de cronometru este numit funcie cu apel invers (callback). Aceasta
este o funcie din program care poate fi apelat direct de sistemul de operare. Programul comunic
sistemului de operare adresa funciei, iar sistemul de operare Windows apeleaz ulterior funcia. Acest mod
de lucru ar trebui s vi se par cunoscut, deoarece procedura de fereastr a unui program este tot o funcie
cu apel invers. Atunci cnd nregistrai clasa de fereastr i comunicai sistemului de operare adresa procedurii de
fereastr i Windows apeleaz apoi procedura de fereastr atunci cnd trimite mesaje ctre program.
SetTimer nu este singura funcie Windows care folosete funcii cu apel invers. Funciile CreateDialog i
DialogBox (despre care vom discuta n Capitolul 14) folosesc funcii cu apel invers pentru prelucrare mesajelor
trimise ctre casetele de dialog; mai multe funcii Windows (cum ar fi EnumChildWindows, EnumFonts,
EnumObjects, EnumProps i EnumWindows) transmit informaii de tip enumerare unor funcii cu apel
invers; i alte funcii mai puin folosite, cum ar fi GrayString, LineDDA si SetWindowsHookEx) impun
folosirea unor funcii cu apel invers.
Ca i procedurile de fereastr, funciile cu apel invers trebuie s fie definite de tipul CALLBACK, deoarece
sunt apelate de Windows din afara spaiului de cod al programului. Parametrii transmii funciilor cu apel
invers i valoarea returnat de acestea depind de scopul funciei. n cazul unei funcii cu apel invers
asociate unui cronometru, parametrii de intrare sunt aceiai cu parametrii de intrare ai unei proceduri de
fereastr. Funciile cu apel invers folosite pentru cronometre nu returneaz nici o valoare ctre sistemul de
operare.
Presupunem c funcia cu apel invers se numete TimerProc. (Putei s dai orice nume dorii.) Aceast
funcie va prelucra numai mesajele WM_TIMER.

VOID CALLBACK TimerProc (HWND hwnd, UINT iMsg, UINT iTimerlD, DWORD
dwTime) [prelucreaz mesajele WM_TIMER]
Parametrul de intrare hwnd reprezint variabila handle a ferestrei specificate la apelarea funciei SetTimer.
Windows va trimite funciei TimerProc numai mesajele WM_TIMER, aa c parametrul iMsg va avea
ntotdeauna valoarea WM_TIMER. Parametrul iTimerlD conine identificatorul cronometrului, iar
parametrul dwTime reprezint timpul sistemului.
Aa cum am menionat anterior, prima metod de pornire a unui cronometru impune apelarea funciei
SetTimer n felul urmtor:

SetTimer (hwnd, iTimerlD, iHsednterval, NULL) ;


Atunci cnd folosii o funcie cu apel invers pentru prelucrarea mesajelor WM_TIMER, al patrulea
parametru al funciei SetTimer trebuie s conin adresa funciei cu apel invers, ca n exemplul urmtor:

SetTimer (hwnd, iTimerlD, iHsednterval, (TIMERPROC) TimerProc) ;

78.

Utilizarea cronometrului. Metoda a treia. :

A treia metod
A treia metod este asemntoare cu cea de-a doua, cu diferena c parametrul hwnd din apelul funciei
SetTimer are valoare NULL, iar al doilea parametru (care ar fi trebuit sa fie identificatorul cronometrului)
este ignorat. Rezultatul este faptul c funcia SetTimer returneaz un identificator al cronometrului:

iTimerID = SetTimer (NULL, 0, iMsecInterval, (TIMERPROC) TimerProc) ;


Variabila iTimerID returnat de funcia SetTimer va avea valoarea NULL dac nu este disponibil nici un
cronometru.
Primul parametru al funciei KillTimer (de obicei folosit pentru transmiterea variabilei handle a ferestrei)
trebuie s aib valoarea NULL. Al doilea parametru (identificatorul cronometrului) trebuie s fie valoarea
returnat de funcia SetTimer:

KillTimer (NULL, iTimerlD) ;


Parametrul hwnd transmis funciei TimerProc trebuie s aib tot valoarea NULL.
Aceast metod de pornire a cronometrelor este rareori folosit. Se poate dovedi totui util dac folosii
n program mai multe cronometre n diferite puncte, i nu vrei s inei socoteala identificatorilor pe care
deja i-ai folosit.
Acum tii s folosii cronometrele din Windows, aa c este timpul s vedei cteva programe utile.
79.
80.

Variabilele handle. Notaia ungar. Punctul de intrare n program. nregistrarea clasei de fereastr. Crearea
ferestrei. Afiarea ferestrei.
handle. . .
Arhitectura .NET Framework. Compilarea programelor. De ce am alege .NET?
2. Platforma .NET
2.1. Prezentare
.NET este un cadru (framework) de dezvoltare software unitar care permite realizarea,
distribuirea i rularea aplicaiilor-desktop Windows i aplicaiilor WEB.
Tehnologia .NET pune laolalt mai multe tehnologii (ASP, XML, OOP, SOAP, WDSL,
UDDI) i limbaje de programare (VB, C++, C#, J#) asigurnd totodat att portabilitatea
codului compilat ntre diferite calculatoare cu sistem Windows, ct i reutilizarea codului n
programe, indiferent de limbajul de programare utilizat.
.NET Framework este o component livrat npreun cu sistemul de operare Windows.
De fapt, .NET 2.0 vine cu Windows Server 2003 i Windows XP SP2 i se poate instala pe
versiunile anterioare, pn la Windows 98 inclusiv; .NET 3.0 vine instalat pe Windows Vista i
poate fi instalat pe versiunile Windows XP cu SP2 i Windows Server 2003 cu minimum SP1.
Pentru a dezvolta aplicatii pe platforma .NET este bine sa avem 3 componente eseniale:
un set de limbaje (C#, Visual Basic .NET, J#, Managed C++, Smalltalk, Perl, Fortran,
Cobol, Lisp, Pascal etc),
un set de medii de dezvoltare (Visual Studio .NET, Visio),
i o bibliotec de clase pentru crearea serviciilor Web, aplicaiilor Web i aplicaiilor
desktop Windows.
Cnd dezvoltm aplicaii .NET, putem utiliza:
Servere specializate - un set de servere Enterprise .NET (din familia SQL Server 2000,
Exchange 2000 etc), care pun la dispoziie funcii de stocare a bazelor de date, email,
aplicaii B2B (Bussiness to Bussiness comer electronic ntre partenerii unei afaceri).
Servicii Web (n special comerciale), utile n aplicaii care necesit identificarea
utilizatorilor (de exemplu, .NET Passport - un mod de autentificare folosind un singur
nume i o parol pentru toate ste-urile vizitate)
Servicii incluse pentru dispozitive non-PC (Pocket PC Phone Edition, Smartphone,
Tablet PC, Smart Display, XBox, set-top boxes, etc.)
2.2. .NET Framework
Componenta .NET Framework st la baza tehnologiei .NET, este ultima interfa ntre
aplicaiile .NET i sistemul de operare i actualmente conine:
Limbajele C#, VB.NET, C++ i J#. Pentru a fi integrate n platforma .NET toate aceste
limbaje respect nite specificaii OOP numite Common Type System (CTS). Ele au
ca elemente de baz: clase, interfee, delegri, tipuri valoare i referin, iar ca
mecanisme: motenire, polimorfism i tratarea excepiilor.
Platforma comun de executare a programelor numit Common Language Runtime
(CLR), utilizat de toate cele 4 limbaje.
Ansamblul de biblioteci necesare n realizarea aplicaiilor desktop sau Web numit
Framework Class Library (FCL).

Arhitectura ,NET Framework

81.

Introducere n C#. Caracterizare. Crearea aplicaiilor consol


3.1. Caracterizare
Limbajul C# fost dezvoltat de o echip restrns de ingineri de la Microsoft, echip din
care s-a evideniat Anders Hejlsberg (autorul limbajului Turbo Pascal i membru al echipei
care a proiectat Borland Delphi).
C# este un limbaj simplu, cu circa 80 de cuvinte cheie, i 12 tipuri de date predefinite.
El permite programarea structurat, modular i orientat obiectual, conform perceptelor
moderne ale programrii profesioniste.
Principiile de baz ale programrii pe obiecte (INCAPSULARE, MOSTENIRE,
POLIMORFISM) sunt elemente fundamentale ale programrii C#. n mare, limbajul
motenete sintaxa i principiile de programare din C++. Sunt o serie de tipuri noi de date
sau funciuni diferite ale datelor din C++, iar n spiritul realizrii unor secvene de cod sigure
(safe), unele funciuni au fost adugate (de exemplu, interfee i delegri), diversificate (tipul
struct), modificate (tipul string) sau chiar eliminate (motenirea multipl i pointerii ctre
funcii). Unele funciuni (cum ar fi accesul direct la memorie folosind pointeri) au fost
pstrate, dar secvenele de cod corespunztoare se consider nesigure.
3.2. Compilarea la linia de comand
Se pot dezvolta aplicaii .NET i fr a dispune de mediul de dezvoltare Visual Studio, ci
numai de .NET SDK (pentru 2.0 i pentru 3.0). n acest caz, codul se scrie n orice editor de
text, fiierele se salveaz cu extensia cs, apoi se compileaz la linie de comand.
Astfel, se scrie n Notepad programul:
using System;
class primul
{
static void Main()
{ Console.WriteLine("Primul program");
Console.ReadKey(true);
}
} Limbajul C# 15
Dac se salveaz fiierul primul.cs, n directorul WINDOWS\Microsoft.NET\Framework\V2.0,
atunci scriind la linia de comand: csc primul.cs se va obine fiierul primul.exe direct
executabil pe o platform .NET.
3.3. Crearea aplicaiilor consol
Pentru a realiza aplicaii n mediul de dezvoltare Visual Studio, trebuie s instalm o
versiune a acestuia, eventual versiunea free Microsoft Visual C# 2005 Express Edition de
la adresa http://msdn.microsoft.com/vstudio/express/downloads/default.aspx. Pentru nceput,
putem realiza aplicaii consol (ca i cele din Borland Pascal sau Borland C).
Dup lansare, alegem
opiunea New Project din
meniul File. n fereastra de
dialog (vezi figura), selectm
pictograma Console
Application, dup care, la
Name, introducem numele
aplicaiei noastre.
Fereastra n care scriem
programul se numete
implicit Programs.cs i se
poate modifica prin salvare
explicit (Save As). Extensia
cs provine de la C Sharp.

n scrierea programului suntem asistati


de IntelliSense, ajutorul contextual.
Compilarea programului se realizeaz cu
ajutorul opiunii Build Solution (F6) din meniul
Build. Posibilele erori de compilare sunt listate
n fereastra Error List. Efectund dublu click pe
fiecare eroare n parte, cursorul din program se
poziioneaz pe linia coninnd eroarea.
Rularea programului se poate realiza n
mai multe moduri: rapid fr asisten de
depanare (Start Without Debugging Shift+F5) ,
rapid cu asisten de depanare (Start
Debugging F5 sau cu butonul din bara de
instrumente), rulare pas cu pas (Step Into F11
i Step Over F12) sau rulare rapid pn la linia
marcat ca punct de ntrerupere (Toggle
Breakpoint F9 pe linia respectiv i apoi Start
Debugging F5). ncetarea urmririi pas cu pas
(Stop Debugging Shift+F5) permite ieirea din
modul depanare i revenirea la modul normal de
lucru. Toate opiunile de rulare i depanare se
gsesc n meniul Debug al meniului.
Fereastra de cod i ferestrele auxiliare ce ne
ajut n etapa de editare pot fi vizualizate alegnd
opiunea corespunztoare din meniul View.
Ferestrele auxiliare utile n etapa de depanare se
pot vizualiza alegnd opiunea corespunztoare
din meniul Debug/Windows.
82.

Structura unui program C#. Sintaxa limbajului.


3.4. Structura unui program C#
S ncepem cu exemplul clasic Hello World adaptat la limbajul C#:
1
using System;
2
3
namespace HelloWorld
4
{
5
class Program
6
{
7
static void Main()
8
{
9
Console.WriteLine("Hello World!");
10
}
11
}
12
}
O aplicatie C# este format din una sau mai multe clase, grupate n spaii de nume
(namespaces). Un spaiu de nume cuprinde mai multe clase cu nume diferite avnd
funcionaliti nrudite. Dou clase pot avea acelai nume cu condiia ca ele s fie definite n
spaii de nume diferite. n cadrul aceluiai spaiu de nume poate aprea definiia unui alt
spaiu de nume, caz n care avem de-a face cu spaii de nume imbricate. O clas poate fi
identificat prin numele complet (nume precedat de numele spaiului sau spaiilor de nume
din care face parte clasa respectiv, cu separatorul punct). n exemplul nostru,
HelloWorld.Program este numele cu specificaie complet al clasei Program.
O clas este format din date i metode (funcii). Apelarea unei metode n cadrul clasei
n care a fost definit aceasta presupune specificarea numelui metodei. Apelul unei metode
definite n interiorul unei clase poate fi invocat i din interiorul altei clase, caz n care este
necesar specificarea clasei i apoi a metodei separate prin punct. Dac n plus, clasa
aparine unui spaiu de nume neinclus n fiierul curent, atunci este necesar precizarea
tuturor componentelor numelui: spaiu.clas.metod sau spaiu.spaiu.clas.metod etc.
n fiierul nostru se afl dou spaii de nume: unul definit (HelloWorld) i unul extern
inclus prin directiva using (System). Console.Writeln reprezint apelul metodei Writeln

definit n clasa Console. Cum n spaiul de nume curent este definit doar clasa Program,
deducem c definiia clasei Console trebuie s se gseasc n spaiul System.
Pentru a facilita cooperarea mai multor programatori la realizarea unei aplicaii
complexe, exist posibilitatea de a segmenta aplicaia n mai multe fiiere numite
assemblies. ntr-un assembly se pot implementa mai multe spaii de nume, iar pari ale unui
aceeai spaiu de nume se pot regsi n mai multe assembly-uri. Pentru o aplicaie consol,
ca i pentru o aplicaie Windows de altfel, este obligatoriu ca una (i numai una) dintre clasele
aplicaiei s conin un punct de intrare (entry point), i anume metoda (funcia) Main.
S comentm programul de mai sus:
linia 1: este o directiv care specific faptul c se vor folosi clase incluse n spaiul de nume
System. n cazul nostru se va folosi clasa Console.
linia 3: spaiul nostru de nume
linia 5: orice program C# este alctuit din una sau mai multe clase
linia 7: metoda Main, punctul de intrare n program
linia 9: clasa Console, amintit mai sus, este folosit pentru operaiile de intrare/ieire. Aici
se apeleaz metoda WriteLine din acest clas, pentru afiarea mesajului dorit pe ecran.
3.5. Sintaxa limbajului
Ca i limbajul C++ cu care se nrudete, limbajul C# are un alfabet format din litere
mari i mici ale alfabetului englez, cifre i alte semne. Vocabularul limbajului este format din
acele simboluri27 cu semnificaii lexicale n scrierea programelor: cuvinte (nume), expresii,
separatori, delimitatori i comentarii.
Comentarii
comentariu pe un rnd prin folosirea // Tot ce urmeaz dup caracterele // sunt
considerate, din acel loc, pn la sfritul rndului drept comentariu
// Acesta este un comentariu pe un singur rand
comentariu pe mai multe rnduri prin folosirea /* i */ Orice text cuprins ntre
simbolurile menionate mai sus se consider a fi comentariu. Simbolurile /* reprezint
nceputul comentariului, iar */ sfritul respectivului comentariu.
/* Acesta este un
comentariu care se
intinde pe mai multe randuri */
Nume
Prin nume dat unei variabile, clase, metode etc. nelegem o succesiune de caractere
care ndeplinete urmtoarele reguli:
numele trebuie s nceap cu o liter sau cu unul dintre caracterele _ i @;
primul caracter poate fi urmat numai de litere, cifre sau un caracter de subliniere;
numele care reprezint cuvinte cheie nu pot fi folosite n alt scop dect acela
pentru care au fost definite
cuvintele cheie pot fi folosite n alt scop numai dac sunt precedate de @
dou nume sunt distincte dac difer prin cel puin un caracter (fie el i liter mic
ce difer de aceeai liter majuscul)
Convenii pentru nume:
n cazul numelor claselor, metodelor, a proprietilor, enumerrilor, interfeelor,
spaiilor de nume, fiecare cuvnt care compune numele ncepe cu majuscul
n cazul numelor variabilelor dac numele este compus din mai multe cuvinte,
primul ncepe cu minuscul, celelalte cu majuscul
Cuvinte cheie n C#

83.

C#: Expresii i operatori. Instruciunile try-catch-finally i throw


3.10. Expresii i operatori
Prin expresie se nelege o secven format din operatori i operanzi. Un operator
este un simbol ce indic aciunea care se efectueaz, iar operandul este valoarea asupra
creia se execut operaia.
n C# sunt definii mai muli operatori. n cazul n care ntr-o expresie nu intervin
paranteze, operaiile se execut conform prioritii operatorilor. n cazul n care sunt mai
muli operatori cu aceeai prioritate, evaluarea expresiei se realizeaz de la stnga la
dreapta.

3.13. Instruciunile try-catch-finally i throw


Prin excepie se nelege un obiect care ncapsuleaz informaii despre situaii
anormale n funcionarea unui program. Ea se folosete pentru a semnala contextul n care
28 de exemplu, pentru prelucrarea sistematic a tuturor componentlelor unei ferestre (butoane,
liste, casete de text etc.) 24 POO i Programare vizual (suport de curs)
apare o situaie special. De exemplu: erori la deschiderea unor fiiere, mprire la 0 etc.
Aceste erori se pot manipula astfel nct programul s nu se termine abrupt.
Sunt situaii n care prefigurm apariia unei erori ntr-o secven de prelucrare i atunci
integrm secvena respectiv n blocul unei instruciuni try, preciznd una sau mai multe
secvene de program pentru tratarea excepiilor aprute (blocuri catch) i eventual o
secven comun care se execut dup terminarea normal sau dup recuperarea
programului din starea de excepie (blocul finally).
Exemplu: using System;
using System.IO;
class tryCatch
{
static void Main(string[] args)
{ string s;
Console.Write("Numele fisierului:");
Console.Readln(s);
try
{
File.OpenRead(s);
}
catch (FileNotFoundException a)
{
Console.WriteLine(a.ToString());
}
catch (PathTooLongException b)
{
Console.WriteLine(b.ToString());
}
finally
{
Console.WriteLine("Programul s-a sfarsit");
Console.ReadLine();
}
}
Alteori putem simula prin program o stare de eroare aruncnd o excepie
(instruciunea throw) sau putem profita de mecanismul de tratare a erorilor pentru a
implementa un sistem de validare a datelor prin generarea unei excepii proprii pe care, de
asemenea, o aruncm n momentul nendeplinirii unor condiii puse asupra datelor.
Clasa System.Exception i derivate ale acesteia servesc la tratarea adecvat i
diversificat a excepiilor.
Exemplu: Considerm clasele Copil, Fetita, Baiat definite fragmentat n capitolul 1. O
posibilitate de validare la adugara unui copil este aceea care genereaz o excepie proprie
la depirea dimensiunii vectorului static copii:
public static void adaug_copil(Copil c)
{
if (nr_copii < nr_max)
copii[nr_copii++] = c;
else throw new Exception("Prea multi copii");
}
84.

Evoluia tehnicilor de programare. Tipuri de date obiectuale. ncapsulare. Suprancrcare.


1.1. Evoluia tehnicilor de programare
Programarea nestructurat (un program simplu, ce utilizeaz numai variabile globale);
complicaiile apar cnd prelucrarea devine mai ampl, iar datele se multiplic i se diversific.
Programarea procedural (program principal deservit de subprograme cu parametri
formali, variabile locale i apeluri cu parametri efectivi); se obin avantaje privind depanarea
i reutilizarea codului i se aplic noi tehnici privind transferul parametrilor i vizibilitatea

variabilelor; complicaiile apar atunci cnd la program sunt asignai doi sau mai muli
programatori care nu pot lucra simultan pe un acelai fiier ce conine codul surs.
Programarea modular (gruparea subprogramelor cu
funcionaliti similare n module, implementate i depanate
separat); se obin avantaje privind independena i
ncapsularea (prin separarea zonei de implementare,
pstrnd vizibilitatea numai asupra zonei de interfa a
modulului) i se aplic tehnici de asociere a procedurilor cu
datele pe care le manevreaz, stabilind i diferite reguli de
acces la date i la subprograme.
Se observ c modulele sunt centrate pe proceduri,
acestea gestionnd i setul de date pe care le prelucreaz
(date+date1 din figur). Daca, de exemplu, dorim s avem mai multe seturi diferite de date,
toate nzestrate comportamental cu procedurile din modulul module1, aceast arhitectur de
aplicaie nu este avantajoas.
Programarea orientat obiect (programe cu noi tipuri ce
integreaz att datele, ct i metodele asociate crerii,
prelucrrii i distrugerii acestor date); se obin avantaje prin
abstractizarea programrii (programul nu mai este o succesiune
de prelucrri, ci un ansamblu de obiecte care prind via, au
diverse proprieti, sunt capabile de aciuni specifice i care
interacioneaz n cadrul programului); intervin tehnici noi privind
instanierea, derivarea i polimorfismul tipurilor obiectuale.
1.2. Tipuri de date obiectuale. ncapsulare
Un tip de date abstract (ADT) este o entitate caracterizat printr-o structur de date i
un ansamblu de operaii aplicabile acestor date. Considernd, n rezolvarea unei probleme
de gestiune a accesului utilizatorilor la un anumit site, tipul abstract USER, vom obseva c
sunt multe date ce caracterizeaz un utilizator Internet. Totui se va ine cont doar de datele
semnificative pentru problema dat. Astfel, culoarea ochilor este irelevant n acest caz, n
timp ce data naterii poate fi important. n aceeai idee, operaii specifice ca se
nregistreaz, comand on-line pot fi relevante, n timp ce operaia mannc nu este, n
cazul nostru. Evident, nici nu se pun n discuie date sau operaii nespecifice (numrul de
laturi sau aciunea zboar).
Operaiile care sunt accesibile din afara entitii formeaz interfaa acesteia. Astfel,
operaii interne cum ar fi conversia datei de natere la un numr standard calculat de la
01.01.1900 nu fac parte din interfaa tipului de date abstract, n timp ce operaia plaseaz o
comand on-line face parte, deoarece permite interaciunea cu alte obiecte (SITE, STOC etc.)
O instan a unui tip de date abstract este o concretizare a tipului respectiv, format
din valori efective ale datelor.
Un tip de date obiectual este un tip de date care implementeaz un tip de date abstract.
Vom numi operaiile implementate n cadrul tipului de date abstract metode. Spunem c
datele i metodele sunt membrii unui tip de date obiectual. Folosirea unui astfel de tip
presupune: existena definiiei acestuia, apelul metodelor i accesul la date.
Un exemplu de-acum clasic de tip de date abstract este STIVA. Ea poate avea ca date:
numerele naturale din stiv, capacitatea stivei, vrful etc. Iar operaiile specifice pot fi:
introducerea n stiv (push) i extragerea din stiv (pop). La implementarea tipului STIVA,
vom defini o structura de date care s rein valorile memorate n stiv i cmpuri de date
simple pentru: capacitate, numr de elemente etc. Vom mai defini metode (subprograme)
capabile s creeze o stiv vid, care s introduc o valoare n stiv, s extrag valoarea din
vrful stivei, s testeze dac stiva este vid sau dac stiva este plin etc.
Crearea unei instane noi a unui tip obiectual, presupune operaii specifice de
construire a noului obiect, metoda corespunztoare purtnd numele de constructor. Analog,
la desfiinarea unei instane i eliberarea spaiului de memorie aferent datelor sale, se aplic
o metod specific numit destructor1
.
O aplicaie ce utilizeaz tipul obiectual STIVA, va putea construi dou sau mai multe
stive (de cri de joc, de exemplu), le va umple cu valori distincte, va muta valori dintr-o stiv
n alta dup o anumit regul desfiinnd orice stiv golit, pn ce rmne o singur stiv.
De observat c toate aceste prelucrri recurg la datele, constructorul, destructorul i la
metodele din interfaa tipului STIVA descris mai sus.
Principalul tip obiectual ntlnit n majoritatea mediilor de dezvoltare (Viisual Basic,
Delphi, C++, Java, C#) poart numele de clas (class). Exist i alte tipuri obiectuale (struct,
object). O instan a unui tip obiectual poart numele de obiect.

La implementare, datele i metodele asociate trebuie s fie complet i corect definite,


astfel nct utilizatorul s nu fie nevoit s in cont de detalii ale acestei implementri. El va
accesa datele, prin intermediul proprietilor i va efectua operaiile, prin intermediul
metodelor puse la dispoziie de tipul obiectual definit. Spunem c tipurile de date obiectuale
respect principiul ncapsulrii. Astfel, programatorul ce utilizeaz un tip obiectual CONT (n
banc) nu trebuie s poarte grija modului cum sunt reprezentate n memorie datele
referitoare la un cont sau a algoritmului prin care se realizeaz actualizarea soldului conform
operaiilor de depunere, extragere i aplicare a dobnzilor. EL va utiliza unul sau mai multe
conturi (instane ale tipului CONT), accesnd proprietile i metodele din interfa,
realizatorul tipului obiectual asumndu-i acele griji n momentul definirii tipului CONT.
Permind extensia tipurilor de date abstracte, clasele pot avea la implementare:
date i metode caracterisitice fiecrui obiect din clas (membri de tip instan),
date i metode specifice clasei (membri de tip clas).
Astfel, clasa STIVA poate beneficia, n plus, i de date ale clasei cum ar fi: numrul de
stive generate, numrul maxim sau numrul minim de componente ale stivelor existente etc.
Modificatorul static plasat la definirea unui membru al clasei face ca acela s fie un
membru de clas, nu unul de tip instan. Dac n cazul membrilor nestatici, exist cte un
exemplar al membrului respectiv pentru fiecare instan a clasei, membrii statici sunt unici,
fiind accesai n comun de toate instanele clasei. Mai mult, membrii statici pot fi referii fr a
crea vreo instan a clasei respective.
1.3. Suprancrcare
Dei nu este o tehnic specific programrii orientat obiect, ea creeaz un anumit
context pentru metodele ce formeaz o clas i modul n care acestea pot fi (ca orice
subprogram) apelate.
Prin suprancarcare se nelege posibilitatea de a defini n acelai domeniu de
vizibilitate2
mai multe funcii cu acelai nume, dar cu parametri diferiti ca tip i/sau ca numr.
Astfel ansamblul format din numele funciei i lista sa de parametri reprezint o modalitate
unic de identificare numit semntur sau amprent. Suprancrcarea permite obinerea
unor efecte diferite ale apelului n contexte diferite3
.
1
Datorit tehnicii de suprancrcare C++, Java i C# permit existena mai multor constructori 2
Noiunile generale legate de vizibilitate se consider cunoscute din programarea procedural.
Aspectele specifice i modificatorii de acces/vizibilitate pot fi studiai din documentaiile de referin C#. 3
Capacitatea unor limbaje (este i cazul limbajului C#) de a folosi ca nume al unui
subprogram un operator, reprezint suprancrcarea operatorilor. Aceasta este o facilitate care Programarea Orientat
Obiect (POO) 5
Apelul unei funcii care beneficiaz, prin suprancrcare, de dou sau mai multe
semnturi se realizeaz prin selecia funciei a crei semntur se potrivete cel mai bine cu
lista de parametri efectivi (de la apel).
Astfel, poate fi definit metoda comand on-line cu trei semnturi diferite:
comanda_online(cod_prod) cu un parametru ntreg (desemnnd comanda unui singur
produs identificat prin cod_prod.
comanda_online(cod_prod,cantitate) cu primul parametru ntreg i celalalt real
comanda_online(cod_prod,calitate) cu primul parametru ntreg i al-II-ilea caracter
85.

Motenire. Polimorfism. Metode virtuale. Principiile programrii orientate pe obiecte.


1.4. Motenire
Pentru tipurile de date obiectuale class este posibil o operaie de extindere sau
specializare a comportamentului unei clase existente prin definirea unei clase noi ce
motenete datele i metodele clasei de baz, cu aceast ocazie putnd fi redefinii unii
membri existeni sau adugai unii membri noi. Operaia mai poart numele de derivare.
Clasa din care se motenetea se mai numete clas de baz sau superclas. Clasa
care motenete se numete subclas, clas derivat sau clas descendent.
Ca i n Java, n C# o subclas poate moteni de la o singur superclas, adic avem
de-a face cu motenire simpl; aceeai superclas ns poate fi derivat n mai multe
subclase distincte. O subclas, la randul ei, poate fi superclas pentru o alt clas derivat.
O clas de baz impreun cu toate clasele descendente (direct sau indirect) formeaza o
ierarhie de clase. n C#, toate clasele motenesc de la clasa de baz Object.
n contextul mecanismelor de motenire trebuie amintii modificatorii abstract i sealed
aplicai unei clase, modificatori ce oblig la i respectiv se opun procesului de derivare. Astfel, o

clas abstract trebuie obligatoriu derivat, deoarece direct din ea nu se pot obine obiecte
prin operaia de instaniere, n timp ce o clas sigilat (sealed) nu mai poate fi derivat (e un
fel de terminal n ierarhia claselor). O metod abstract este o metod pentru care nu este
definit o implementare, aceasta urmnd a fi realizat n clasele derivate din clasa curent4
.
O metod sigilat nu mai poate fi redefinit n clasele derivate din clasa curent.
1.5. Polimorfism. Metode virtuale
Folosind o extensie a sensului etimologic, un obiect polimorfic este cel capabil s ia
diferite forme, s se afle n diferite stri, s aib comportamente diferite. Polimorfismul
obiectual5
se manifest n lucrul cu obiecte din clase aparinnd unei ierarhii de clase, unde,
prin redefinirea unor date sau metode, se obin membri diferii avnd ns acelai nume.
Astfel, n cazul unei referiri obiectuale, se pune problema stabilirii datei sau metodei referite.
Comportamentul polimorfic este un element de flexibilitate care permite stabilirea
contextual, n mod dinamic6
, a membrului referit.
De exemplu, dac este definit clasa numit PIESA (de ah), cu metoda nestatic
muta(pozitie_initiala,pozitie_finala), atunci subclasele TURN i PION trebuie
s aib metoda muta definit n mod diferit (pentru a implementa maniera specific a
pionului de a captura o pies en passant7
). Atunci, pentru un obiect T, aparinnd claselor
reduce diferenele dintre operarea la nivel abstract (cu DTA) i apelul metodei ce realizeaz acest
operaie la nivel de implementare obiectual. Dei ajut la sporirea expresivitii codului, prin
suprancrcarea operatorilor i metodelor se pot crea i confuzii. 4
care trebuie s fie i ea abstract (virtual pur, conform terminologiei din C++) 5
deoarece tot aspecte polimorfice mbrac i unele tehnici din programarea clasic sau tehnica
suprancrcrcrii funciilor i operatorilor. 6
Este posibil doar n cazul limbajelor ce permit legarea ntrziat. La limbajele cu "legare
timpurie", adresa la care se face un apel al unui subprogram se stabilete la compilare. La limbajele
cu legare ntrziat, aceast adresa se stabileste doar in momentul rulrii, putndu-se calcula distinct,
n funcie de contextul n care apare apelul. 7
ntr-o alt concepie, metoda muta poate fi implementat la nivelul clasei PIESA i redefinit
la nivelul subclasei PION, pentru a particulariza acest tip de deplasare care captureaz piesa peste
care trece pionul n diagonal. 6 POO i Programare vizual (suport de curs)
derivate din PIESA, referirea la metoda muta pare nedefinit. Totui mecanismele POO
permit stabilirea, n momentul apelului, a clasei proxime creia i aparine obiectul T i
apelarea metodei corespunztore (mutare de pion sau tur sau alt pies).
Pentru a permite acest mecanism, metodele care necesit o decizie contextual (n
momentul apelului), se decalr ca metode virtuale (cu modificatorul virtual). n mod
curent, n C# modificatorului virtual al funciei din clasa de baz, i corespunde un
specificator override al funciei din clasa derivat ce redefinete funcia din clasa de baz.
O metod ne-virtual nu este polimorfic i, indiferent de clasa creia i aparine
obiectul, va fi invocat metoda din clasa de baz.
86.

STRUCTURA UNEI APLICAII ORIENTAT PE OBIECTE N C#. Clas de baz i clase derivate.
3.4. Structura unui program C#
S ncepem cu exemplul clasic Hello World adaptat la limbajul C#:
1 using System;
2
3 namespace HelloWorld
4{
5 class Program
6{
7 static void Main()
8{
9 Console.WriteLine("Hello World!");
10 }
11 }
12 }

O aplicatie C# este format din una sau mai multe clase, grupate n spaii de nume
(namespaces). Un spaiu de nume cuprinde mai multe clase cu nume diferite avnd
funcionaliti nrudite. Dou clase pot avea acelai nume cu condiia ca ele s fie definite n
spaii de nume diferite. n cadrul aceluiai spaiu de nume poate aprea definiia unui alt
spaiu de nume, caz n care avem de-a face cu spaii de nume imbricate. O clas poate fi
identificat prin numele complet (nume precedat de numele spaiului sau spaiilor de nume
din care face parte clasa respectiv, cu separatorul punct). n exemplul nostru,
HelloWorld.Program este numele cu specificaie complet al clasei Program.
O clas este format din date i metode (funcii). Apelarea unei metode n cadrul clasei
n care a fost definit aceasta presupune specificarea numelui metodei. Apelul unei metode
definite n interiorul unei clase poate fi invocat i din interiorul altei clase, caz n care este
necesar specificarea clasei i apoi a metodei separate prin punct. Dac n plus, clasa
aparine unui spaiu de nume neinclus n fiierul curent, atunci este necesar precizarea
tuturor componentelor numelui: spaiu.clas.metod sau spaiu.spaiu.clas.metod etc.
n fiierul nostru se afl dou spaii de nume: unul definit (HelloWorld) i unul extern
inclus prin directiva using (System). Console.Writeln reprezint apelul metodei Writeln
definit n clasa Console. Cum n spaiul de nume curent este definit doar clasa Program,
deducem c definiia clasei Console trebuie s se gseasc n spaiul System.
Pentru a facilita cooperarea mai multor programatori la realizarea unei aplicaii
complexe, exist posibilitatea de a segmenta aplicaia n mai multe fiiere numite
assemblies. ntr-un assembly se pot implementa mai multe spaii de nume, iar pari ale unui
aceeai spaiu de nume se pot regsi n mai multe assembly-uri. Pentru o aplicaie consol,
ca i pentru o aplicaie Windows de altfel, este obligatoriu ca una (i numai una) dintre clasele
aplicaiei s conin un punct de intrare (entry point), i anume metoda (funcia) Main.
S comentm programul de mai sus:
linia 1: este o directiv care specific faptul c se vor folosi clase incluse n spaiul de nume
System. n cazul nostru se va folosi clasa Console.
linia 3: spaiul nostru de nume
linia 5: orice program C# este alctuit din una sau mai multe clase
linia 7: metoda Main, punctul de intrare n program
linia 9: clasa Console, amintit mai sus, este folosit pentru operaiile de intrare/ieire. Aici
se apeleaz metoda WriteLine din acest clas, pentru afiarea mesajului dorit pe ecran.
87.

STRUCTURA UNEI APLICAII ORIENTAT PE OBIECTE N C#. Constructori. Suprancrcarea


constructorilor i definirea constructorilor n clasele derivate. Destructor. Metode.

1.3. Suprancrcare
Dei nu este o tehnic specific programrii orientat obiect, ea creeaz un anumit
context pentru metodele ce formeaz o clas i modul n care acestea pot fi (ca orice
subprogram) apelate.
Prin suprancarcare se nelege posibilitatea de a defini n acelai domeniu de
vizibilitate2
mai multe funcii cu acelai nume, dar cu parametri diferiti ca tip i/sau ca numr.
Astfel ansamblul format din numele funciei i lista sa de parametri reprezint o modalitate
unic de identificare numit semntur sau amprent. Suprancrcarea permite obinerea
unor efecte diferite ale apelului n contexte diferite3
.
1
Datorit tehnicii de suprancrcare C++, Java i C# permit existena mai multor constructori 2
Noiunile generale legate de vizibilitate se consider cunoscute din programarea procedural.
Aspectele specifice i modificatorii de acces/vizibilitate pot fi studiai din documentaiile de referin C#. 3
Capacitatea unor limbaje (este i cazul limbajului C#) de a folosi ca nume al unui
subprogram un operator, reprezint suprancrcarea operatorilor. Aceasta este o facilitate care Programarea Orientat Obiect
(POO) 5
Apelul unei funcii care beneficiaz, prin suprancrcare, de dou sau mai multe
semnturi se realizeaz prin selecia funciei a crei semntur se potrivete cel mai bine cu
lista de parametri efectivi (de la apel).
Astfel, poate fi definit metoda comand on-line cu trei semnturi diferite:
comanda_online(cod_prod) cu un parametru ntreg (desemnnd comanda unui singur
produs identificat prin cod_prod.
comanda_online(cod_prod,cantitate) cu primul parametru ntreg i celalalt real
comanda_online(cod_prod,calitate) cu primul parametru ntreg i al-II-ilea caracter.

1.8. Constructori
Sintaxa:
[atrib]o [modificatori]o [nume_clas] ([list_param_formali]o) [:iniializator]o [corp_constr]o
Modificatori: public protected internel private extern
Iniializator: base([list_param]o), this([list_param]o) ce permite invocarea unui constructor
anume12 nainte de executarea instruciunilor ce formeaz corpul constructorului curent. Dac
nu este precizat niciun iniializator, se asociaz implicit iniializatorul base().
Corpul constructorului este format din instruciuni care se execut la crearea unui nou obiect al
clasei respective (sau la crearea clasei, n cazul constructorilor cu modificatorul static).
pot exista mai muli constructori care se pot diferenia prin lista lor de parametri
constructorii nu pot fi motenii
dac o clas nu are definit niciun constructor, se va asigna automat constructorul fr
parametri al clasei de baz (clasa object, dac nu este precizat clasa de baz)
Instanierea presupune declararea unei variabile de tipul clasei respective i iniializarea
acesteia prin apelul constructorului clasei (unul dintre ei, dac sunt definii mai muli)
precedat de operatorul new. Acestea se pot realiza i simultan ntr-o instruciune de felul:
[Nume_clas] [nume_obiect]=new [Nume_clas] ([list_param]o)
Utilizarea unui constructor fr parametri i a constructorului implicit n clas derivat
public abstract class Copil
{ protected string nume;
public Copil() {nume = Console.ReadLine();} //la iniializarea obiectului se citete
//de la tastatur un ir de caractere ce va reprezenta numele copilului
}
class Fetita:Copil {}
...
Fetita f=new Fetita();
Copil c= new Copil(); //Pentru clasa Copil abstract, s-ar fi obinut eroare aici
Suprancrcarea constructorilor i definirea explicit a constructorilor n clase derivate
public class Copil
{ protected string nume; //dat acceesibil numai n interiorul clasei i claselor derivate
public Copil() {nume = Console.ReadLine();}
public Copil(string s) {nume=s;}
}
class Fetita:Copil
{ public Fetita(string s):base(s) {nume=Fetita +nume}13
public Fetita(){} //preia constructorul fr parametri din clasa de baz14
//public Fetita(string s):base() {nume=s}
}
...
Copil c1= new Copil(); //se citeste numele de la tastatur
Copil c2= new Copil(Codrina);
Fetita f1=new Fetita();Fetita f2=new Fetita("Ioana);
Exist dou motive pentru care definiia constructorului al treilea din clasa Fetita este greit
i de aceea este comentat. Care sunt aceste motive?
1.9. Destructor
Sintaxa: [atrib]o [extern]o ~[nume_clas] () [corp_destructor]o
Corpul destructorului este format din instruciuni care se execut la distrugerea unui
obiect al clasei respective. Pentru orice clas poate fi definit un singur constructor. Destructorii
12 Din clasa de baz (base) sau din clasa insi (this) 13 Preia i specializeaz constructorul al doilea din clasa de baz 14
Este echivalent cu public Fetita():base(){} 8 POO i Programare vizual (suport de curs)
nu pot fi motenii. n mod normal, destructorul nu este apelat n mod explicit, deoarece
procesul de distrugere a unui obiect este invocat i gestionat automat de Garbagge Collector.
1.10. Metode
Sintaxa:[atrib]o[modificatori]o[tip_returnat] [nume] ([list_param_formali]o) [corp_metoda]o
Modificatori: new public protected internal private static virtual abstract
sealed override extern15
Tipul rezultat poate fi un tip definit sau void. Numele poate fi un simplu identificator sau, n
cazul n care definete n mod explicit un membru al unei interfee, numele este de forma
[nume_interfata].[nume_metoda]
Lista de parametri formali este o succesiune de declarri desprite prin virgule, declararea
unui parametru avnd sintaxa: [atrib]o [modificator]o [tip] [nume]
Modificatorul unui parametru poate fi ref (parametru de intrare i ieire) sau out (parametru

care este numai de ieire). Parametrii care nu au niciun modificator sunt parametri de intrare.
Un parametru formal special este parametrul tablou cu sintaxa: [atrib]o params [tip][] [nume].
Pentru metodele abstracte i externe, corpul metodei se reduce la un semn ;
Semntura fiecrei metode este format din numele metodei, modificatorii acesteia,
numrul i tipul parametrilor16
Numele metodei trebuie s difere de numele oricrui alt membru care nu este metod.
La apelul metodei, orice parametru trebuie s aib acelai modificator ca la definire
Invocarea unei metode se realizeaz prin sintagma [nume_obiect].[nume_metoda] (pentru
metodele nestatice) i respectiv [nume_clas].[nume_metoda] (pentru metodele statice).
Definirea datelor i metodelor statice corespunztoare unei clase
public class Copil
{ public const int nr_max = 5; //constant
public static int nr_copii=0; //cmp simplu (variabil)
static Copil[] copii=new Copil[nr_max]; //cmp de tip tablou (variabil)
public static void adaug_copil(Copil c) //metod
{ copii[nr_copii++] = c;
if (nr_copii==nr_max) throw new Exception("Prea multi copii");
}
public static void afisare() //metod
{
Console.WriteLine("Sunt {0} copii:", nr_copii);
for (int i = 0; i<nr_copii; i++)
Console.WriteLine("Nr.{0}. {1}", i+1, copii[i].nume);
} ...17
}
...
Fetita c = new Fetita();Copil.adaug_copil(c);
referina noului obiect se memoreaz n tabloul static copii (caracteristic clasei) i se
incrementeaz data static nr_copii
Baiat c = new Baiat(); Copil.adaug_copil(c);
Copil c = new Copil(); Copil.adaug_copil(c);
Copil.afisare();//se afieaz o list cu numele celor 3 copii
15 Poate fi folosit cel mult unul dintre modificatorii static, virtual I override ; nu pot aprea
mpreun new i override, abstract nu poate s apar cu niciunul dintre static, virtual, sealed, extern;
private nu poate s apar cu niciunul dintre virtual, override i abstract; seald oblig i la override 16 Din semntur
(amprent) nu fac parte tipul returnat, numele parametrilor formali i nici
specificatorii ref i out. 17 Se are n vedere i constructorul fr parametri definit i preluat implicit n subclasele din cadrul
primului exemplu din subcapitolul 1.8: public Copil() {nume = Console.ReadLine();} Programarea Orientat Obiect (POO)
9
Definirea datelor i metodelor nestatice corespunztoare clasei Copil i claselor derivate
public class Copil
{ ...
public string nume;
public virtual void se_joaca() //virtual se poate suprascrie la derivare
{Console.WriteLine("{0} se joaca.", this.nume);}
public void se_joaca(string jucaria) //nu permite redefinire18
{Console.WriteLine("{0} se joaca cu {1}.", this.nume, jucaria);}
} //suprancrcarea metodei se_joaca
class Fetita:Copil
{ public override void se_joaca() //redefinire comportament polimorfic
{Console.WriteLine("{0} leagana papusa.",this.nume);}
}
class Baiat:Copil
{ public override void se_joaca()
{Console.WriteLine("{0} chinuie pisica.",this.nume);}
}
...
Fetita c = new Fetita();c.se_joaca("pisica");c.se_joaca(); //polimorfism
Baiat c = new Baiat();c.se_joaca("calculatorul");c.se_joaca(); //polimorfism
Copil c = new Copil();c.se_joaca(); //polimorfism
Pentru a evidenia mai bine comportamentul polimorfic, propunem secvena
urmtoare n care nu se tie exact ce este obiectul copii[i] (de tip Copil, Fetita sau Baiat?):
for (int i=0; i<nr_copii; i++) copii[i].se_joaca;

88.

CLASE I FUNCII GENERICE. DERIVAREA CLASELOR (MOTENIRE). Principiile motenirii.


Accesibilitatea membrilor motenii.

89.

Metode. Interfee n C#.


1.10. Metode
Sintaxa:[atrib]o[modificatori]o[tip_returnat] [nume] ([list_param_formali]o) [corp_metoda]o
Modificatori: new public protected internal private static virtual abstract
sealed override extern15
Tipul rezultat poate fi un tip definit sau void. Numele poate fi un simplu identificator sau, n
cazul n care definete n mod explicit un membru al unei interfee, numele este de forma
[nume_interfata].[nume_metoda]
Lista de parametri formali este o succesiune de declarri desprite prin virgule, declararea
unui parametru avnd sintaxa: [atrib]o [modificator]o [tip] [nume]
Modificatorul unui parametru poate fi ref (parametru de intrare i ieire) sau out (parametru
care este numai de ieire). Parametrii care nu au niciun modificator sunt parametri de intrare.
Un parametru formal special este parametrul tablou cu sintaxa: [atrib]o params [tip][] [nume].
Pentru metodele abstracte i externe, corpul metodei se reduce la un semn ;
Semntura fiecrei metode este format din numele metodei, modificatorii acesteia,
numrul i tipul parametrilor16
Numele metodei trebuie s difere de numele oricrui alt membru care nu este metod.
La apelul metodei, orice parametru trebuie s aib acelai modificator ca la definire
Invocarea unei metode se realizeaz prin sintagma [nume_obiect].[nume_metoda] (pentru
metodele nestatice) i respectiv [nume_clas].[nume_metoda] (pentru metodele statice).
Definirea datelor i metodelor statice corespunztoare unei clase
public class Copil
{ public const int nr_max = 5; //constant
public static int nr_copii=0; //cmp simplu (variabil)
static Copil[] copii=new Copil[nr_max]; //cmp de tip tablou (variabil)
public static void adaug_copil(Copil c) //metod
{ copii[nr_copii++] = c;
if (nr_copii==nr_max) throw new Exception("Prea multi copii");
}
public static void afisare() //metod
{
Console.WriteLine("Sunt {0} copii:", nr_copii);
for (int i = 0; i<nr_copii; i++)
Console.WriteLine("Nr.{0}. {1}", i+1, copii[i].nume);
} ...17
}
...
Fetita c = new Fetita();Copil.adaug_copil(c);
referina noului obiect se memoreaz n tabloul static copii (caracteristic clasei) i se
incrementeaz data static nr_copii
Baiat c = new Baiat(); Copil.adaug_copil(c);
Copil c = new Copil(); Copil.adaug_copil(c);
Copil.afisare();//se afieaz o list cu numele celor 3 copii
15 Poate fi folosit cel mult unul dintre modificatorii static, virtual I override ; nu pot aprea
mpreun new i override, abstract nu poate s apar cu niciunul dintre static, virtual, sealed, extern;
private nu poate s apar cu niciunul dintre virtual, override i abstract; seald oblig i la override 16 Din semntur
(amprent) nu fac parte tipul returnat, numele parametrilor formali i nici
specificatorii ref i out. 17 Se are n vedere i constructorul fr parametri definit i preluat implicit n subclasele din
cadrul
primului exemplu din subcapitolul 1.8: public Copil() {nume = Console.ReadLine();} Programarea Orientat Obiect
(POO) 9
Definirea datelor i metodelor nestatice corespunztoare clasei Copil i claselor derivate
public class Copil
{ ...

public string nume;


public virtual void se_joaca() //virtual se poate suprascrie la derivare
{Console.WriteLine("{0} se joaca.", this.nume);}
public void se_joaca(string jucaria) //nu permite redefinire18
{Console.WriteLine("{0} se joaca cu {1}.", this.nume, jucaria);}
} //suprancrcarea metodei se_joaca
class Fetita:Copil
{ public override void se_joaca() //redefinire comportament polimorfic
{Console.WriteLine("{0} leagana papusa.",this.nume);}
}
class Baiat:Copil
{ public override void se_joaca()
{Console.WriteLine("{0} chinuie pisica.",this.nume);}
}
...
Fetita c = new Fetita();c.se_joaca("pisica");c.se_joaca(); //polimorfism
Baiat c = new Baiat();c.se_joaca("calculatorul");c.se_joaca(); //polimorfism
Copil c = new Copil();c.se_joaca(); //polimorfism
Pentru a evidenia mai bine comportamentul polimorfic, propunem secvena
urmtoare n care nu se tie exact ce este obiectul copii[i] (de tip Copil, Fetita sau Baiat?):
for (int i=0; i<nr_copii; i++) copii[i].se_joaca;
1.13. Interfee
Interfeele sunt foarte importante n programarea orientat pe obiecte, deoarece permit
utilizarea polimorfismului ntr-un sens mai extins.O interfa este o component a aplicaiei,
asemntoare unei clase, ce declar prin membrii si (metode, proprieti, evenimente i
indexatori) un comportament unitar aplicabil mai multor clase, comportament care nu se
poate defini prin ierarhia de clase a aplicaiei.
De exemplu, dac vom considera arborele din figura urmtoare, n care AVERE este o
clas abstract, iar derivarea claselor a fost conceput urmrind proprietile comune ale
componentelor unei averi, atunci o clas VENIT nu este posibil, deoarece ea ar moteni de
la toate clasele evideniate, iar motenirea multipl nu este admis n C#.
22 De exmplu indicii componentelor interschimbate 23 A se observa c evenimentul n sine este anonim, doar
delegatul asociat are nume 24 ntr-o atribuire de felul x.E+=new [tip_delegat](M)
VENITURI
(din produse, din
chirii, din dobnzi,
dividende)
calc()
AVERE
Proprietate Bani
Imobiliara Bun Depunere Investiie Credit_primit
Teren
Imobil
B_inchiriat
Productiv
Neproductiv
De_folosin
I_inchiriat
Mobilier
Altul
Actiune
Cot
Credit_acordat 12 POO i Programare vizual (suport de curs)
Pentru metodele din cadrul unei interfee nu se d nici o implementare, ci sunt pur i simplu
specificate, implementarea lor fiind furnizat de unele dintre clasele aplicaiei25. Nu exist
instaniere n cazul interfeelor, dar se admit derivri, inclusiv moteniri multiple.
n exemplul nostru, se poate defini o interfa VENIT care s conin antetul unei
metode calc (s zicem) pentru calculul venitului obinut, fiecare dintre clasele care
implementeaz interfaa VENIT fiind obligat s furnizeze o implementare (dup o formul
de calcul specific) pentru metoda calc din interfa. Orice clas care dorete s adere la
interfa trebuie s implementeze toate metodele din interfa. Toate clasele care motenesc
dintr-o clas care implementeaz o interfa motenesc, evident, metodele respective, dar le

pot i redefini (de exemplu, clasa Credit_acordat redefinete metoda calc din clasa Investiie,
deoarece formula de calcul implementat acolo nu i se potrivete i ei26).
De exemplu, dac presupunem c toate clasele subliniate implementeaz interfaa
VENIT, atunci pentru o avere cu aciuni la dou firme, un imobil nchiriat i o depunere la
banc, putem determina venitul total:
Actiune act1 = new Actiune();Actiune act2 = new Actiune();
I_inchiriat casa = new I_inchiriat();Depunere dep=new Depunere();
Venit[] venituri = new Venit()[4];
venituri[0] = act1; venituri[1] = act2;
venituri[2] = casa; venituri[3] = dep;
...
int t=0;
for(i=0;i<4;i++) t+=v[i].calc();
Gsii dou motive pentru care interfaa VENIT i rezovarea de mai sus ofer o soluie
mai bun dect: t=act1.calc()+act2.calc()+casa.calc()+dep.calc().
90.

TRATAREA EXCEPIILOR N C#. Aruncarea i prinderea excepiilor.

Atunci cand programam este aproape imposibil sa nu primim erori: de sintaxa (abatere de la sintaxa limbajului de
programare), de logica (greseli in logica programului) sau erori la executie (exceptii).
O exceptie reprezinta o eroare care intervine la runtime, la momentul executiei. In C#, exceptiile se pot trata intr-o maniera
structurata si controlata, acest lucru insemanand faptul ca programatorul nu trebuie sa mai verifice manual daca o operatie
se executa sau nu cu succes.
C# defineste exceptii standard pentru tipurile de erori obisnuite dintr-un program. De exemplu: impartire la zero, depasirea
capacitatii unui vector, memorie insuficienta, etc.
Blocurile Try Catch Finally
Cuvintele cheie in C# rezervate pentru tratarea exceptiilor sunt try, catch, finally, throw. Acestea reprezinta un sistem
unitar, utilizarea unuia dintre ele implicand si utilizarea altuia.
Intr-un bloc try vom scrie instructiunile care trebuie verificate pentru aparitia erorilor. Daca pe parcursul executiei acestor
intructiuni apare o exceptie, aceasta este aruncata, lansata (thrown).
Cu ajutorul lui catch programul poate intercepta exceptia si o poate trata in functie de logica programului. Instructiunile
din catch se executa doar daca se lanseaza o exceptie.
Instructiunile din finally se vor executa intotdeauna.
O imagine de ansamblu a codului folosit pentru tratarea exceptiilor:
try
{
//in this block exception may get thrown
}
catch
{
//handle exception
}
finally
{
//cleanup code, optionally
}
Cuvantul cheie try nu poate aparea fara a fi completat de cuvantul cheie catch sau definally si nici invers. Finally este
optional.
Un exemplu simplu de tratare a exceptiei DivideByZeroException si de folosire a blocului try catch finally:
try
{
int x = 0;
//raise the exception
int y = 4 / x;
}
catch
{
//catch the exception
Console.WriteLine("X must be greater than zero");

}
finally
{
//this code will be allways executed
Console.WriteLine("Program completed");
Console.Read();
}
Pot exista mai multe instructiuni catch asociate unui try. Instructiunea care se va executa se va stabili in functie de tipul
exceptiei, celelalte sunt ignorate.
static void Compute(int [] numbers)
{
try
{
int secondNumber = numbers[0];
Console.Write(secondNumber);
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Must provide more than an argument");
}
catch (NullReferenceException)
{
Console.WriteLine("Argument is null");
}
catch (FormatException)
{
Console.WriteLine("Argument is not a number");
}
catch (Exception)
{
Console.WriteLine("Another exception occured");
}
}
Se adauga instructiunile pentru blocurile catch cat mai specifice, inainte celor generale.
CLR cauta instructiunea catch care va trata exceptia. Daca metoda curenta in care ne aflam cu debug-erul nu contine un
bloc catch, atunci CLR va cauta in metoda care a apelat metoda curenta, si asa mai departe conform call stack. Daca nu
este gasit nici un catch, atunci CLR va afisa un mesaj cum ca exceptia nu este tratata, unhandled exception message, apoi
va opri executia programului.
In general, instructiunea catch nu are un parametru. Totusi, il putem adauga in cazul in care vom avea nevoie de accesul la
obiectul care reprezinta exceptia. Este folositor pentru furnizarea informatiilor suplimentare despre eroarea produsa.
catch (Exception exception)
{
Console.WriteLine(exception.Message);
Console.WriteLine(exception.GetType());
}
Fluxul executiei programului continua cu instructiunile aflate dupa blocul catch.
Throw
Pentru a lansa manual o exceptie se foloseste throw.
if (numbers == null)
throw new ArgumentNullException("Array is null");
Tipul obiectului trebuie sa fie o clasa derivata din Exception.
Exemplu de folosire a blocului finally
Instructiunile dintr-un bloc finally se executa intotdeauna, chiar daca o exceptie este prinsa sau nu. Acest bloc este folosit
pentru a curata resursele folosite intr-un bloc trysi pentru a asigura executarea unor instructiuni de cod indiferent de
modul in care se iese din blocul precedent de try.
static void ReadFile()
{

StreamReader reader = null;


try
{
//open text file for reading
reader = File.OpenText(@"C:\fisier.txt");
//return if the current position is at the end of the stream
if (reader.EndOfStream) return;
//read the content of the stream
Console.WriteLine(reader.ReadToEnd());
}
catch (FileNotFoundException)
{
Console.WriteLine("File not found");
}
finally
{
//cleanup code, close the file
if(reader != null)
reader.Dispose();
}
}
Relansarea unei exceptii
Presupunem urmatoarea clasa. In metoda Divide vom trimite exceptiaDivideByZeroException la un nivel mai sus, in
metoda parinte.
class Compute
{
public void DivideTwoNumbers(int x, int y)
{
try
{
var result = x / y;
}
catch(DivideByZeroException)
{
// the control goes back to parent method
throw;
}
}
}
In metoda Main :
static void Main(string[] args)
{
Compute comp = new Compute();
try
{
comp.DivideTwoNumbers(5, 13);
}
catch(DivideByZeroException)
{
Console.WriteLine("Exception caught here");
}
}
System.Exception
Dupa cum s-a putut observa in exemplele de mai sus, exceptiile sunt reprezentate prin clase. Toate deriva din clasa de
baza Exception. Se disting doua clase prin reprezentarea a doua categorii generale de exceptii: exceptii generate de motorul
de executie SystemException si exceptii generate de programele de aplicatieApplicationException. Ele nu adauga membri

noi la clasa de baza, ci doar definesc radacile celor doua ierarhii de clase care reprezinta exceptii. De exemplu, in cazul
impartirii la zero se produce o exceptie de tipul DivideByZeroException.
Programatorul isi poate defini propriile clase care reprezinta exceptii prin derivarea clasei ApplicationException.
Pentru mai multe detalii, se poate consulta documentatia de pe msdn.
Un program trebuie sa trateze exceptiile intr-o maniera logica si eleganta si sa isi continue apoi executia. Daca programul
nu intercepteaza exceptia, el va fi fortat sa se inchida.
Chiar daca nu este considerata optima, o alta modalitate de raportare a erorilor o reprezinta codurile de retur. Ce parere
aveti? Voi ati utilizat-o?
Pentru ca tratarea erorilor constituie un subiect dificil voi continua intr-un viitor articol crearea propriilor clase de

exceptii si consecintele exceptiilor neinterceptate.


91.

POLIMORFISM. Polimorfismul parametric. Polimorfismul ad-hoc. Polimorfismul de motenire.

O singura interfata, mai multe metode sintagma pe care se bazeaza conceptul de polimorfism. Se incearca stabilirea
unei interfete generice pentru un intreg grup de activitati asemanatoare.
Un obiect polimorfic este capabil sa ia mai multe forme, sa se afle in diferite stari, sa aiba comportamente diferite.
Polimorfismul parametric
O metoda va prelua orice numar de parametri.
Cand cream o metoda, de regula se stie numarul parametrilor care vor fi transmisi. Sunt cazuri in care nu se intampla
acest lucru si va fi nevoie de un numar arbitrar de parametri. Se va recurge la un tip special de parametru, de
tipul params. Acesta va declara un tablou de parametri, care poate memora zero sau mai multe elemente.
Exemplu :
//metoda va returna numarul minim
public int metoda(params int[] numere)
{
int minim;
//in cazul in care nu e transmis functiei
//nici un parametru, afiseaza un mesaj
if (numere.Length == 0)
{
Console.WriteLine("Nu sunt parametri");
return 0;
}
//initializam variabila
//cu primul element al tabloului
minim = numere[0];
//comparam fiecare element al tabloului
//cu valoarea minima initiala
foreach (int i in numere)
if (i < minim)
//atribuim valoarea minima variabilei minim
minim = i;
//inapoi la programul apelant al functiei
return minim;
}
Polimorfismul ad-hoc

Se mai numeste si supraincarcarea metodelor, una dintre cele mai interesante facilitati oferite de limbaju C#. Cu ajutorul
acesteia, se pot defini in cadrul unei clase mai multe metode, toate avand acelasi nume, dar cu tipul si numarul parametrilor
diferit. La compilare, se va apela functia dupa numarul parametrilor folositi la apel.
Pentru a supraincarca o metoda, pur si simplu trebuie doar declararea unor versiuni diferite ale sale. Nu este suficient insa,
ca diferenta dintre doua metode sa fie facuta doar prin tipul valorii returnate, ci e nevoie si de tipurile sau numarul
parametrilor.
Exemplu:
class SupraincarcareMetoda
{
public void CalculeazaMedia()
{
Console.WriteLine("Nici un parametru");
}
//supraincarcam cu un parametru intreg
public void CalculeazaMedia(int nota)
{
Console.WriteLine("O nota:" + nota);
}
//supraincarcam cu doi parametri intregi
public void CalculeazaMedia(int nota1, int nota2)
{
Console.WriteLine("Doi parametri: " + nota1 + " " + nota2);
}
//supraincarcam cu parametri double
public void CalculeazaMedia(double nota)
{
Console.WriteLine("Un parametru double:" + nota);
}
//eroare, daca incerc sa suprascriu
//doar prin tipul de date returnat
public int CalculeazaMedia(double nota)
{
//
}
}
In metoda principala a programului :
//apelam toate versiunile lui CalculeazaMedia
SupraincarcareMetoda sup = new SupraincarcareMetoda();
sup.CalculeazaMedia();
sup.CalculeazaMedia(10);
sup.CalculeazaMedia(23, 23);
sup.CalculeazaMedia(34.34);
Polimorfismul de mostenire
Intr-o ierarhie de clase, se pune problema apelarii metodelor care au aceeasi lista de parametri, dar care sunt in clase
diferite.
Exemplu:
class Baza
{
public void Afiseaza()
{
Console.WriteLine("Apelul functiei Afiseaza din clasa de baza\n");
}

}
class Derivata : Baza
{
public void Afiseaza()
{
Console.WriteLine("Apelul functiei Afiseaza din clasa derivata");
}
}
La compilare se rezolva problema apelarii metode Afiseaza, pe baza tipului declarat al obiectelor :
Derivata obiect2 = new Derivata();
//instantiem pe un obiect din clasa derivata
Baza obiect1 = obiect2;
//afiseaza functia din clasa de Baza
obiect1.Afiseaza();
obiect2.Afiseaza();
Modificatorii virtual si override
Virtual este folosit in declararea unei metode sau a unei proprietati. Acestea se vor numi membri virtuali. Implementarea
unui membru virtual poate fi schimbata prin suprascrierea membrului intr-o clasa derivata.
Override se foloseste pentru a modifica o metoda sau o proprietate si furnizeaza o noua implementare a unui membru
mostenit dintr-o clasa de baza. Metoda de baza suprascrisa si metoda de suprascriere trebuie sa aiba aceeasi signatura ( tip
si numar de parametri ).
Implicit, metodele nu sunt virtuale. Nu se pot suprascrie metodele care nu sunt virtuale.
Exemplu:
class Baza
{
public virtual void Afiseaza()
{
Console.WriteLine("Apelul functiei Afiseaza din clasa de baza\n");
}
}
class Derivata : Baza
{
public override void Afiseaza()
{
Console.WriteLine("Apelul functiei Afiseaza din clasa derivata");
}
}
Derivata obiect2 = new Derivata();
//instantiem pe un obiect din clasa derivata
Baza obiect1 = obiect2;
//afiseaza functia din clasa de Baza
obiect1.Afiseaza();
obiect2.Afiseaza();
Polimorfismul ajuta la reducerea complexitatii pentru ca permite unei interfete sa fie folosita de fiecare data pentru
specificarea unei clase generice de actiuni. Programatorul nu va efectua manual selectia. Selectia actiunii
specifice (metoda) va fi facuta de compilator.

92.

Modificatorii virtual i override. Modificatorul new. Metoda sealed.

93.

CONCEPTE DE BAZ ALE PROGRAMRII VIZUALE.


4.1. Concepte de baz ale programrii vizuale
Programarea vizual trebuie privit ca un mod de proiectare a unui program prin
operare direct asupra unui set de elemente grafice (de aici vine denumirea de programare
vizual). Aceast operare are ca efect scrierea automat a unor secvene de program,
secvene care, mpreun cu secvenele scrise textual29, vor forma programul.
Spunem c o aplicaie este vizual dac dispune de o interfa grafic sugestiv i
pune la dispoziia utilizatorului instrumente specifice de utilizare (drag, click, hint etc.)
Realizarea unei aplicaii vizuale nu const doar n desenare i aranjare de controale, ci
presupune n principal stabilirea unor decizii arhitecturale30, decizii ce au la baz unul dintre
modelele arhitecturale de baz:
a) Modelul arhitectural orientat pe date.
Acest model nu este orientat pe obiecte, timpul de dezvoltare al unei astfel de aplicaii
este foarte mic, o parte a codului este generat automat de Visual Stdio.Net, codul nu
este foarte uor de ntreinut i este recomandat pentru aplicaii relativ mici sau cu multe
operaii de acces (in/out) la o baz de date.
b) Modelul arhitectural Model-view-controller
Este caracterizat de cele trei concepte de baz : Model (reprezentarea datelor se
realizeaz ntr-o manier specific aplicaiei: conine obiectele de business,
ncapsuleaz accesul la date), View (sunt utilizate elemente de interfa, este format
din Form-uri), Controller( proceseaz i rspunde la evenimente iar SO, clasele Form
i Control din .Net ruteaz evenimentul ctre un handler, eveniment tratat n codul din
spatele Form-urilor).
c) Modelul arhitectural Multi-nivel
Nivelul de prezentare ( interfaa)
Se ocup numai de afiarea informaiilor ctre
utilizator i captarea celor introduse de acesta. Nu
cuprinde detalii despre logica aplicaiei, i cu att
mai mult despre baza de date sau fiierele pe
care aceasta le utilizeaz. Cu alte cuvinte, n
cadrul interfeei cu utilizatorul, nu se vor folosi
obiecte de tipuri definite de programator, ci numai
baza din .NET.
Nivelul de logic a aplicaiei
Se ocup de tot ceea ce este specific aplicaiei
care se dezvolt. Aici se efectueaz calculele i
procesrile i se lucreaz cu obiecte de tipuri
definite de programator.
Nivelul de acces la date
Aici rezid codul care se ocup cu accesul la
baza de date, la fiiere, la alte servicii.
Aceast ultim structur este foarte bun pentru a organiza aplicaiile, dar nu este uor
de realizat. De exemplu, dac n interfaa cu utilizatorul prezentm date sub form ListView
i la un moment dat clientul ne cere reprezentarea datelor ntr-un GridView, modificrile la
nivel de cod nu se pot localiza doar n interfa deoarece cele dou controale au nevoie de
modele de acces la date total diferite.
29 Se utilizeaz ades antonimia dintre vizual (operaii asupra unor componente grafice) i textual
(scriere de linii de cod); proiectarea oricrei aplicaii vizuale mbin ambele tehnici. 30 Deciziile arhitecturale
stabilesc n principal cum se leag interfaa de restul aplicaiei i ct de
uor de ntreinut este codul rezultat. 26 POO i Programare vizual (suport de curs)
Indiferent de modelul arhitectural ales, n realizarea aplicaiei mai trebuie respectate i
principiile proiectrii interfeelor:
Simplitatea
Interfaa trebuie s fie ct mai uor de neles31 i de nvat de ctre utilizator i s permit
acestuia s efectueze operaiile dorite n timp ct mai scurt. n acest sens, este vital
culegerea de informaii despre utilizatorii finali ai aplicaiei i a modului n care acetia sunt
obinuii s lucreze.

Poziia controalelor
Locaia controalelor dintr-o fereastr trebuie s reflecte importana relativ i frecvena de
utilizare. Astfel, cnd un utilizator trebuie s introduc nite informaii unele obligatorii i
altele opionale este indicat s organizm controalele astfel nct primele s fie cele care
preiau informaii obligatorii.
Consistena
Ferestrele i controalele trebuie s fie afiate dup un design asemntor (template) pe
parcursul utilizrii aplicaiei. nainte de a implementa interfaa, trebuie decidem cum va arta
aceasta, s definim template-ul.
Estetica
Intefaa trebuie s fie pe ct posibil plcut i atrgtoare.
94.

MEDIUL DE DEZVOLTARE VISUAL C# (INTERFEA).

95.
96.
97.

ELEMENTELE POO N CONTEXT VIZUAL.


Barele de instrumente.
CONSTRUIREA INTERFEEI UTILIZATOR. Ferestre. Controale
4.3. Ferestre
Spaiul Forms ne ofer clase specializate pentru: creare de ferestre sau formulare
(System.Windows.Forms.Form), elemente specifice (controale) cum ar fi butoane
(System.Windows.Forms.Button), casete de text (System.Windows.Forms.TextBox) etc.
Proiectarea unei ferestre are la baz un cod complex, generat automat pe msur ce noi
desemnm componentele i comportamentul acesteia. n fapt, acest cod realizeaz:
derivarea unei clase proprii din System.Windows.Forms.Form, clas care este nzestrat
cu o colecie de controale (iniial vid). Constructorul ferestrei realizaz instanieri ale
claselor Button, MenuStrip, Timer etc. (orice plasm noi n fereastr) i adaug referinele
acestor obiecte la colecia de controale ale ferestrei.
Dac modelul de fereastr reprezint ferestra principal a aplicaiei, atunci ea este
instaniat automat n programul principal (metoda Main). Dac nu, trebuie s scriem noi
codul ce realizeaz instanierea.
Clasele derivate din Form motenesc o serie de proprieti care determin atributele
vizuale ale ferestrei (stilul marginilor, culoare de fundal, etc.), metode care implementeaz
anumite comportamente (Show, Hide, Focus etc.) i o serie de metode specifice (handlere)
de tratare a evenimentelor (Load, Click etc.).
O fereastr poate fi activat cu form.Show() sau cu form.ShowDialog(), metoda a
doua permind ca revenirea n fereastra din care a fost activat noul formular s se fac
numai dup ce noul formular a fost inchis (spunem c formularul nou este deschis modal).
Un propietar este o fereastr care contribuie la comportarea formularului deinut.
Activarea propietarului unui formular deschis modal va determina activarea formularului
deschis modal. Cnd un nou formular este activat folosind form.Show() nu va avea nici un
deintor, acesta stabilindu-se direct :
public Form Owner { get; set; }
F_nou form=new F_nou();
form.Owner = this; form.Show();
Formularul deschis modal va avea un proprietar setat pe null. Deintorul se poate
stabili setnd proprietarul nainte s apelm Form.ShowDialog() sau apelnd
From.ShowDialog() cu proprietarul ca argument.
F_nou form = new F_nou();form.ShowDialog(this);
Vizibilitatea unui formular poate fi setat folosind metodele Hide sau Show. Pentru a
ascunde un formular putem folosi :
this.Hide(); // setarea propietatii Visible indirect sau
this.Visible = false; // setarea propietatii Visible direct
Printre cele mai uzuale proprieti ale form-urilor, reamintim:
StartPosition determin poziia ferestrei atunci cnd aceasta apare prima dat, poziie
ce poate fi setat Manual sau poate fi centrat pe desktop (CenterScreen), stabilit de
Windows, formularul avnd dimensiunile i locaia stabilite de programator
(WindowsDefaultLocation) sau Windows-ul va stabili dimensiunea iniial i locaia
pentru formular (WindowsDefaultBounds) sau, centrat pe formularul care l-a afiat
(CenterParent) atunci cnd formularul va fi afiat modal. 28 POO i Programare vizual (suport de curs)
Location (X,Y) reprezint coordonatele colului din stnga sus al formularului relativ la

colul stnga sus al containerului. (Aceast propietate e ignorat dac StartPosition =


Manual).
Micarea formularului ( i implicit schimbarea locaiei) poate fi tratat n evenimentele
Move i LocationChanged .
Locaia formularului poate fi stabilit relativ la desktop astfel:
void Form_Load(object sender, EventArgs e) {
this.Location = new Point(1, 1);
this.DesktopLocation = new Point(1, 1); } //formularul in desktop
Size (Width i Height) reprezint dimensiunea ferestrei. Cnd se schimb propietile
Width i Height ale unui formular, acesta se va redimensiona automat, aceast
redimensionare fiind tratat n evenimentele Resize sau in SizeChanged.
Chiar dac propietatea Size a formularului indic dimensiunea ferestrei, formularul nu este
n totalitate responsabil pentru desenarea ntregului coninut al su. Partea care este
desenat de formular mai este denumit i Client Area. Marginile, titlul i scrollbar-ul sunt
desenate de Windows.
MaxinumSize i MinimumSize sunt utilizate pentru a restriciona dimensiunile unui
formular.
void Form_Load(object sender, EventArgs e) {
this.MinimumSize = new Size(200, 100);...
this.MaximumSize = new Size(int.MaxValue, 100);...}
IsMdiContainer precizeaz dac form-ul reprezint un container pentru alte form-uri.
ControlBox precizeaz dac fereastra conine sau nu un icon, butonul de nchidere al
ferestrei i meniul System (Restore,Move,Size,Maximize,Minimize,Close).
HelpButton-precizeaz dac butonul va aprea sau nu lng butonul de nchidere al
formularului (doar dac MaximizeBox=false, MinimizeBox=false). Dac utilizatorul apas
acest buton i apoi apas oriunde pe formular va aprea evenimentul HelpRequested
(F1).
Icon reprezint un obiect de tip *.ico folosit ca icon pentru formular.
MaximizeBox i MinimizeBox precizeaz dac fereastra are sau nu butonul Maximize i
respectiv Minimize
Opacity indic procentul de opacitate32
ShowInTaskbar precizeaz dac fereastra apare in TaskBar atunci cnd formularul este
minimizat.
SizeGripStyle specific tipul pentru Size Grip (Auto, Show, Hide). Size grip (n colul
din dreapta jos) indic faptul c aceast fereastr poate fi redimensionat.
TopMost precizeaz dac fereastra este afisat n faa tuturor celorlalte ferestre.
TransparencyKey identific o culoare care va deveni transparent pe form.
Definirea unei funcii de tratare a unui eveniment asociat controlului se realizeaz prin
selectarea grupului Events din ferestra Properties a controlului respectiv i alegerea
evenimentului dorit.
Dac nu scriem nici un nume pentru funcia de tratare, ci efectum dublu click n
csua respectiv, se genereaz automat un nume pentru aceast funcie, innd cont de
numele controlului i de numele evenimentului (de exemplu button1_Click).
Dac n Designer efectum dublu click pe un control, se va genera automat o funcie
de tratare pentru evenimentul implicit asociat controlului (pentru un buton evenimentul
implicit este Click, pentru TextBox este TextChanged, pentru un formular Load etc.).
Printre evenimentele cele mai des utilizate, se numr :
Load apare cnd formularul este pentru prima data ncrcat n memorie.
32 Dac va fi setat la 10% formularul i toate controalele sale vor fi aproape invizibile.
Programare vizual 29
FormClosed apare cnd formularul este nchis.
FormClosing apare cnd formularul se va inchide ca rezultat al aciunii utilizatorului
asupra butonului Close (Dac se seteaz CancelEventArgs.Cancel =True atunci se
va opri nchiderea formularului).
Activated apare pentru formularul activ.
Deactivate apare atunci cnd utilizatorul va da click pe alt formular al aplicatiei.
Controale
Unitatea de baz a unei interfee Windows o reprezint un control. Acesta poate fi
gzduit de un container ce poate fi un formular sau un alt control.
Un control este o instan a unei clase derivate din System.Windows.Forms i este
reponsabil cu desenarea unei pri din container. Visual Studio .NET vine cu o serie de
controale standard, disponibile n Toolbox. Aceste controale pot fi grupate astfel:

Controale de actiune (de exemplu button) care, atunci cnd sunt acionate, se poate
executa o prelucrare. De exemplu, cel mai important eveniment pentru Button este Click
(desemnnd aciunea click stnga pe buton).
n exemplul PV1 se adaug pe formular dou butoane i o caset
text. Apsarea primului buton va determina afiarea textului din TextBox
ntr-un MessageBox iar apsarea celui de-al doilea buton va nchide
nchide aplicaia. Dup adugarea celor dou butoane i a casetei text a
fost schimbat textul afiat pe cele dou butoane au fost scrise funciile
de tratare a evenimentului Click pentru cele dou butoane:
private void button1_Click(object sender, System.EventArgs e)
{ MessageBox.Show(textBox1.Text);}
private void button2_Click(object sender, System.EventArgs e)
{ Form1.ActiveForm.Dispose();}
Controale valoare (label, textbox, picturebox) care arat utilizatorului o informaie
(text, imagine).
Label este folosit pentru plasarea de text pe un formular. Textul afiat este coninut n
propietatea Text i este aliniat conform propietii TextAlign.
TextBox - permite utilizatorului s introduc un text. Prevede, prin intermediul
ContextMenu-ului asociat, un set de funcionaliti de baz, ca de exemplu (Cut,
Copy, Paste, Delete, SelectAll).
PictureBox permite afiarea unei imagini.
Exemplul PV2 afieaz un grup alctuit din 3
butoane, etichetate A,B respectiv C avnd iniial
culoarea roie. Apsarea unui buton determin
schimbarea culorii acestuia n galben. La o nou
apsare butonul revine la culoare iniial. Acionarea
butonului Starea butoanelor determin afiarea ntr-o
caset text a etichetelor butoanelor galbene. Caseta
text devine vizibil atunci cnd apsm prima oar
acest buton. Culoarea butonului mare (verde/portocaliu)
se schimb atunci cnd mouse-ul este poziionat pe
buton.
Dup adugarea butoanelor i a casetei text pe
formular, stabilim evenimentele care determin
schimbarea culoriilor i completarea casetei text.
private void button1_Click(object sender, System.EventArgs e)
{if (button1.BackColor== Color.IndianRed) button1.BackColor=Color.Yellow;
else button1.BackColor= Color.IndianRed;} 30 POO i Programare vizual (suport de curs)
private void button4_MouseEnter(object sender, System.EventArgs e)
{button4.BackColor=Color.YellowGreen;button4.Text="Butoane apasate";}
private void button4_MouseLeave(object sender, System.EventArgs e)
{textBox1.Visible=false;button4.Text="Starea butoanelor";
button4.BackColor=Color.Orange;}
private void button4_Click(object sender, System.EventArgs e)
{textBox1.Visible=true;textBox1.Text="";
if( button1.BackColor==Color.Yellow)textBox1.Text=textBox1.Text+'A';
if( button2.BackColor==Color.Yellow)textBox1.Text=textBox1.Text+'B';
if( button3.BackColor==Color.Yellow)textBox1.Text=textBox1.Text+'C';
}
Exerciiu Modificai aplicaia precedent astfel nct s avem un singur eveniment
button_Click, diferenierea fiind fcut de parametrul sender.
Exerciiu ( Password) Adugai pe un formular o caset text n care s introducei un
ir de caractere i apoi verificai dac acesta coincide cu o parol dat. Textul introdus n
caset nu este vizibil (fiecare caracter este nlocuit cu*). Rezultatul va fi afiat ntr-un
MessageBox.
Controale de selecie (CheckBox,RadioButton) au propietatea Checked care indic
dac am selectat controlul. Dup schimbarea strii unui astfel de control, se declaneaz
evenimentul Checked. Dac propietatea ThreeState este setat, atunci se schimb
funcionalitatea acestor controale, n sensul c acestea vor permite setarea unei alte
stri. n acest caz, trebuie verificat propietatea CheckState(Checked,
Unchecked,Indeterminate) pentru a vedea starea controlului.

98.
99.

Proprieti comune ale controalelor i formularelor. Metode i evenimente.


Obiecte grafice. Validarea informaiilor de la utilizator. MessageBox. Interfa definit de ctre utilizator.
4.6. Validarea informaiilor de la utilizator
nainte ca informaiile de la utilizator s fie preluate i transmise ctre alte clase, este
necesar s fie validate. Acest aspect este important, pentru a preveni posibilele erori. Astfel,
dac utilizatorul introduce o valoare real (float) cnd aplicaia ateapt un ntreg (int), este
posibil ca aceasta s se comporte neprevzut abia cteva secunde mai trziu, i dup multe
apeluri de metode, fiind foarte greu de identificat cauza primar a problemei.
Validarea la nivel de cmp
Datele pot fi validate pe msur ce sunt introduse, asociind o prelucrare unuia dintre
handlerele asociate evenimentelor la nivel de control (Leave, Textchanged, MouseUp etc.)
private void textBox1_KeyUp(object sender,
System.Windows.Forms.KeeyEventArgs e)
{if(e.Alt==true) MessageBox.Show ("Tasta Alt e apasata"); // sau
if(Char.IsDigit(e.KeyChar)==true) MessageBox.Show("Ati apasat o cifra");
}
Validarea la nivel de utilizator
n unele situaii (de exemplu atunci cnd valorile introduse trebuie s se afle ntr-o
anumit relaie ntre ele), validarea se face la sfritul introducerii tuturor datelor la nivelul
unui buton final sau la nchiderea ferestrei de date.
private void btnValidate_Click(object sender, System.EventArgs e)
{ foreach(System.Windows.Forms.Control a in this.Controls)
{ if( a is System.Windows.Forms.TextBox & a.Text=="")
{ a.Focus();return;}
}
}
ErrorProvider
O manier simpl de a semnala erori de validare este aceea de a seta un mesaj de
eroare pentru fiecare control .
myErrorProvider.SetError(txtName," Numele nu are spatii in stanga");
Aplicatii recapitulative.
Urmrii aplicaiile i precizai pentru fiecare dintre ele controalele utilizate,
evenimentele tratate: Forma poloneza (PV14), Triunghi (PV15), Ordonare vector(PV16),
Subsir cresctor de lungime maxim(PV17), Jocul de Nim (PV18)
Exerciiu (Test grila) Realizai un generator de teste gril (ntrebrile sunt preluate
dintr-un fisier text, pentru fiecare item se precizeaz punctajul, enunul, rspunsul corect,
distractorii i o imagine asociat enunului (dac exist). Dup efectuarea testului se
afieaz rezultatul obinut i statistica rspunsurilor.

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