Documente Academic
Documente Profesional
Documente Cultură
RAPORT
LA LUCRAREA DE LABORATOR NR. 2
Disciplina : Programarea în Windows
Chișinău 2014
Scopul lucrării
Sarcina propusă
Scrieţi un program care afişează în zona client un desen animat, utilizând toate primitivele GDI.
Noţiuni teoretice
Interfaţa pentru dispozitive grafice (GDI - Graphics Device Interface) este o componentă a sistemului de
operare Windows şi are ca sarcină afişarea elementelor grafice (inclusiv a textului) pe ecran şi la imprimantă.
De asemenea, trebuie să ştiţi că interfaţă Windows GDI îşi are limitele ei. Cel puţin în acest moment, interfaţă
GDI nu poate să facă tot ce v-aţi putea dori de la o interfaţă grafică. Deşi puteţi să mutaţi pe ecran obiecte
grafice, GDI este, în general, un sistem de afişare static, ce permite numai animaţii limitate. Aşa cum este
implementată în Windows 95, interfaţă GDI nu asigură un suport direct pentru afişarea tridimensională sau
pentru rotirea obiectelor. De exemplu, atunci când desenaţi o elipsă, axele acesteia trebuie să fie paralele cu
axele sistemului de coordonate. Deşi unele limbaje grafice folosesc numere în virgulă mobilă pentru
coordonatele virtuale. Windows 95 - din motive legate de performanţă - foloseşte numai numere întregi pe 16
biţi aceasta este una dintre deficienţele sistemului de operare Windows 95. Windows NT permite folosirea
coordonatelor pe 32 de biţi.
Din punctul de vedere al programatorului, interfaţa GDI este formată din câteva sute de apeluri de funcţii şi
unele tipuri de date, macroinstrucţiuni şi structuri asociate acestor funcţii, înainte de a studia în detaliu câteva
dintre aceste funcţii, haideţi să vedem care este structura generală a interfeţei GDI.
În general, apelurile de funcţii GDI pot fi clasificate în mai multe categorii. Chiar dacă nu sunt foarte stricte şi
există unele suprapuneri, aceste categorii pot fi enunţate astfel:
Funcţii care obţin (sau creează) şi eliberează (sau distrug) un context de dispozitiv.
Funcţii care obţin informaţii despre contextul de dispozitiv.
Funcţii care desenează ceva.
Funcţii care stabilesc sau obţin atribute ale contextului de dispozitiv.
Funcţii care lucrează cu obiecte GDI.
Elementele grafice pe care le afişaţi pe ecran sau le tipăriţi la imprimantă pot fi împărţite în mai multe
categorii, numite „primitive". Iată care sunt aceste categorii:
Linii şi curbe. Liniile reprezintă baza oricărui 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 reprezentând porţiuni din circumferinţa unei elipse sau a curbelor
Bezier. Liniile sunt desenate folosind peniţa curentă selectată în contextul de dispozitiv.
Suprafeţe 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 (haşuri
orizontale, verticale sau pe diagonală) sau o imagine bitmap repetată pe verticală sau pe orizontală.
Imagini bitmap. Imaginile bitmap sunt matrice dreptunghiulare de biţi, care corespund pixelilor unui
dispozitiv de afişare. În general, acestea sunt folosite pentru afişarea imaginilor complexe (deseori
preluate din lumea reală) pe ecran sau pentru tipărirea acestora la imprimantă. De asemenea,
imaginile bitmap sunt folosite pentru afişarea unor mici imagini (cum ar fi pictograme, indicatoare de
mouse şi butoane de pe barele cu instrumente de lucru ale aplicaţiilor) care trebuie afişate foarte
rapid.
Text. Textul este mai puţin „matematic" decât alte aspecte ale graficii pe calculator. Structurile create
pentru definirea fonturilor şi pentru obţinerea informaţiilor despre fonturi sunt printre cele mai mari
din Windows. Începând cu versiunea Windows 3.1, interfaţa GDI acceptă fonturile TrueType, bazate
pe contururi umplute, care pot fi manipulate de alte funcţii GDI. Windows 95 acceptă în continuare şi
fonturile mai vechi, de tip bitmap (cum este fontul sistem prestabilit) pentru compatibilitate şi pentru
economisirea spaţiului de memorie.
Alte aspecte ale interfeţei GDI nu sunt la fel de uşor de clasificat. Printre acestea se numără:
Moduri de mapare şi transformări. Modurile de mapare GDI vă permit să desenaţi folosind ca unitate
de măsură inci (sau fracţiuni de inci), milimetri sau orice altă unitate de măsură. De asemenea.
Windows 95 asigură suportul pentru o „transformare reală" exprimată printr-o matrice 3x3. Această
transformare permite deformarea şi rotirea obiectelor grafice. Din păcate, această transformare nu
este acceptată sub Windows 95.
Metafişiere (metafiles). Un metafişier este o colecţie de comenzi GDI stocate într-o formă binară.
Metafişierele sunt folosite pentru transferarea reprezentărilor unor elemente grafice vectoriale prin
intermediul memoriei temporare (clipboard).
Regiuni (regions). O regiune este o suprafaţă complexă de orice formă, definită ca o combinaţie
booleană de regiuni mai simple. În general, regiunile sunt stocate intern de GDI ca o serie de linii de
scanare, diferite de combinaţia de linii folosită iniţial pentru definirea regiunii. Puteţi să folosiţi
regiunile pentru contururi, pentru umplere sau pentru decupare.
Căi (paths). O cale este o colecţie de linii drepte şi curbe stocate intern de GDI. Căile pot fi folosite
pentru desenare, pentru umplere sau pentru decupare. De asemenea, căile pot fi transformate în
regiuni.
Decupare (clipping). Desenarea poate fi limitată la o anumită secţiune a zonei client, numită zonă de
decupare, care poate fi dreptunghiulară sau poate avea o altă formă, definită printr-o serie de linii.
Zona de decupare este definită, în general, de o cale sau de o regiune.
Palete (palettes). Folosirea paletelor proprii este limitată, în general, numai la monitoarele care pot
reda 256 de culori. Windows rezervă 20 dintre aceste culori pentru sistemul de operare. Celelalte 236
de culori pot fi modificate pentru afişarea corespunzătoare a imaginilor din lumea reală, stocate ca
imagini bitmap.
Tipărire (printing). Deşi discuţiile din acest capitol sunt limitate doar la afişarea pe ecran, tot ceea ce
învăţaţi în acest capitol poate fi aplicat şi operaţiilor de tipărire. (Vezi Capitolul 15 pentru alte
informaţii despre tipărire.)
Contextul de dispozitiv
Atunci când vreţi să desenaţi la un dispozitiv de ieşire grafic (cum ar fi ecranul sau imprimanta) trebuie să
obţineţi mai întâi o variabilă handle a contextului de dispozitiv (DC - device context). Variabila handle este
apoi inclusă ca parametru în apelul unei funcţii GDI, identificând dispozitivul Ia care vreţi să desenaţi.
Contextul de dispozitiv conţine mai multe atribute curente, care specifică modul de lucru al funcţiilor GDI
pentru dispozitivul respectiv. Aceste atribute permit ca la apelarea funcţiilor GDI să fie specificate numai
coordonatele de început sau dimensiunea, nu şi toate celelalte informaţii de care sistemul de operare are
nevoie pentru desenarea obiectelor pe dispozitivul folosit. Atunci când doriţi să modificaţi unul dintre aceste
atribute ale contextului de dispozitiv, apelaţi o funcţie specializată.
Obţinerea variabilei handle a contextului de dispozitiv
Sistemul de operare Windows vă pune la dispoziţie mai multe metode pentru obţinerea variabilei handle a
contextului de dispozitiv. Dacă obţineţi o variabilă handle a contextului de dispozitiv în timpul prelucrării
unui mesaj, ar trebui să ştergeţi această variabilă înainte de ieşirea din procedura de fereastră. După ce este
ştearsă, variabila handle nu mai poate fi folosită (nu mai este validă).
Cea mai cunoscută metodă de obţinere şi de ştergere a variabilei handle a contextului de dispozitiv implică
folosirea funcţiilor BeginPaint şi EndPaint în timpul prelucrării mesajului WM_PAINT:
Variabila ps este o structură de tip PAINTSTRUCT. Câmpul hdc al acestei structuri conţine variabila handle
a contextului de dispozitiv. Folosind variabila handle a contextului de dispozitiv, obţinută prin apelarea
funcţiei BeginPaint, nu puteţi să desenaţi decât în regiunea invalidă a ferestrei. Funcţia BeginPaint validează
regiunea invalidă.
Programele Windows pot să obţină variabila handle a contextului de dispozitiv şi în timpul prelucrării altor
mesaje decât WM_PAINT:
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 funcţiilor BeginPaint şi EndPaint este că variabila handle
returnată de funcţia GetDC vă permite să desenaţi în toată zona client a ferestrei. În plus, funcţiile GetDC şi
ReleaseDC nu validează eventualele regiuni invalide ale zonei client.
Un program Windows poate să obţină şi o variabilă handle a unui context de dispozitiv care se aplică întregii
ferestre, nu numai zonei client a ferestrei:
DeleteDC (hdc);
Apelul următor returnează numărul de biţi de culoare folosiţi pentru fiecare pixel:
Majoritatea adaptoarelor video care pot afişa culori folosesc fie mai multe planuri de culoare, fie mai mulţi
biţi de culoare pentru fiecare pixel, dar nu pe amândouă; cu alte cuvinte, unul dintre cele două apeluri de mai
sus va returna valoarea 1. Numărul de culori care pot fi redate de o placă video se poate calcula cu formula
următoare:
Această valoare poate să nu fie identică cu numărul de culori obţinut prin apelarea funcţiei GetDeviceCaps cu
parametrul NUMCOLORS:
Windows foloseşte pentru reprezentarea culorilor o valoare întreagă fără semn, pe 32 de biţi. Tipul de date
folosit pentru culori se numeşte COLORREF. Ultimii trei octeţi ai numărului (cei mai puţin semnificativi)
specifică valorile pentru culorile roşu, verde şi albastru, de la O la 255, aşa cum se poate vedea în Figura 4-3.
Rezultă o paletă potenţială de 224 culori (aproximativ 16 milioane de culori).
Valoarea pe 32 de biţi de mai sus e numită deseori „culoare RGB". În fisierele antet din Windows sunt
definite mai multe macroinstrucţiuni pentru lucrul cu valorile RGB. Macroinstructiunea RGB acceptă trei
argumente, care reprezintă valorile pentru culorile roşu, verde şi albastru şi le combină într-o valoarea
întreagă pe 32 de biţi, fără semn.
Astfel, valoarea
este de fapt 0x00FF00FF, valoarea RGB pentru magenta. Dacă toate cele trei argumente au valoarea 0, se
obţine negrul, iar dacă au valoarea 255, se obţine albul. Macroinstrucţiunile GetRValue, GetGValue şi
GetBValue extrag valorile pentru culorile primare, sub forma unor octeţi fără semn, din valoarea RGB a
culorii. Aceste macroinstructiuni sunt utile atunci când apelaţi funcţii Windows care returnează culori RGB.
În mod normal, Windows creează un nou context de dispozitiv cu valori prestabilite atunci când apelaţi una
dintre funcţiile GetDC sau BeginPaint. Toate modificările făcute în atributele contextului de dispozitiv se
pierd atunci când contextul de dispozitiv este şters din memorie prin apelarea funcţiei ReleaseDC sau a
funcţiei EndPaint. Dacă programul trebuie să folosească un atribut cu o valoarea diferită de cea prestabilită
va trebui să iniţializaţi contextul de dispozitiv de fiecare dată când obţineţi o variabilă handle:
caseWM_Paint:
return 0;
Deşi această abordare este în general satisfăcătoare, s-ar putea să preferaţi să salvaţi modificările făcute
asupra contextului de dispozitiv ia distrugerea acestuia, astfel încât valorile salvate să redevină active la
apelarea funcţiilor GetDC sau BeginPaint.
Raspunsuri la intrebari:
Linii şi curbe. Liniile reprezintă baza oricărui 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 reprezentând porţiuni din circumferinţa 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
peniţa curentă selectată în contextul de dispozitiv.
Suprafeţe 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 (haşuri orizontale, verticale
sau pe diagonală) sau o imagine bitmap repetată pe verticală sau pe orizontală.
Imagini bitmap. Imaginile bitmap sunt matrice dreptunghiulare de biţi, care corespund pixelilor unui
dispozitiv de afişare. Imaginile bitmap sunt instrumente de bază pentru sistemele grafice de tip rastru. În
general, acestea sunt folosite pentru afişarea imaginilor complexe (deseori preluate din lumea reală) pe
ecran sau pentru tipărirea acestora la imprimantă. De asemenea, imaginile bitmap sunt folosite pentru
afişarea unor mici imagini (cum ar fi pictograme, indicatoare de mouse şi butoane de pe barele cu
instrumente de lucru ale aplicaţiilor) care trebuie afişate foarte rapid. Interfaţa 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 fişiere.
Text. Textul este mai puţin „matematic" decât alte aspecte ale graficii pe calculator. Textul, aşa cum îl
ştim, este legat de sute de ani de tipografia tradiţională, apreciată adesea ca adevărată 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 obţinerea informaţiilor despre fonturi
sunt printre cele mai mari din Windows. Începând cu versiunea Windows 3.1, interfaţa GDI acceptă
fonturile TrueType, bazate pe contururi umplute, care pot fi manipulate de alte funcţii GDI. Windows 95
acceptă în continuare şi fonturile mai vechi, de tip bitmap (cum este fontul sistem prestabilit) pentru
compatibilitate şi pentru economisirea spaţiului de memorie.
Variabila ps este o structură de tip PAINTSTRUCT. Câmpul hdc al acestei structuri conţine variabila handle
a contextului de dispozitiv. Structura PAINTSTRUCT conţine şi o structură de tip RECT numită rcPaint,
care defineşte dreptunghiul ce cuprinde regiunea invalidă a zonei client a ferestrei. Folosind variabila handle
a contextului de dispozitiv, obţinută prin apelarea funcţiei BeginPaint, nu puteţi să desenaţi decât în regiunea
invalidă a ferestrei. Funcţia BeginPaint validează regiunea invalidă.
Programele Windows pot să obţină variabila handle a contextului de dispozitiv şi în timpul prelucrării altor
mesaje decât WM_PAINT:
Un program Windows poate să obţină şi o variabilă handle a unui context de dispozitiv care se aplică întregii
ferestre, nu numai zonei client a ferestrei:
Funcţiile BeginPaint, GetDC şi GetWindowDC obţin variabila handle a contextului de dispozitiv asociat unei
anumite ferestre de pe ecran. O funcţie mai generală pentru obţinerea variabilei handle a unui context de
dispozitiv este CreateDC:
Aşa cum am menţionat mai devreme, un metafişier este o colecţie de apeluri GDI codificate într-o formă
binară. Puteţi să creaţi un metafişier prin obţinerea unui context de dispozitiv pentru metafişiere:
Un context de dispozitiv se referă, de obicei, la un dispozitiv fizic de ieşire, cum ar fi un monitor video
sau o imprimantă. Dacă aveţi nevoie de anumite informaţii despre acest dispozitiv, cum ar fi dimensiunile
ecranului (dimensiunile în pixeli şi cele fizice) sau posibilităţile de folosire a culorilor, puteţi să le obţineţi
prin apelarea funcţiei GetDeviceCaps („get device capabilities"):
Parametrul iIndex este unul dintre cei 28 de identificatori definiţi în fişierele antet din Windows. De
exemplu, dacă iIndex are valoarea HORZRES funcţia GetDeviceCaps returnează lăţimea dispozitivului în
pixeli; VERTRES returnează înălţimea dispozitivului în pixeli. Dacă hdc este o variabilă handle a contextului
de dispozitiv pentru un monitor video, informaţiile obţinute sunt aceleaşi cu cele returnate de funcţia
GetSystemMetrics. Dacă hdc este o variabilă handle a contextului de dispozitiv pentru o imprimantă, funcţia
GetDeviceCaps returnează înălţimea şi lăţimea zonei pe care imprimantă o poate tipări.
Puteţi să folosiţi funcţia GetDeviceCaps şi ca să obţineţi informaţii despre posibilităţile 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 tipări imagini bitmap - iar funcţia
GetDeviceCaps vă poate comunica acest lucru
Listingul programului
#include <Windows.h>
#include <Math.h>
#include <stdio.h>
wndCls.style = 0;
wndCls.lpfnWndProc = (WNDPROC) WndProc;
wndCls.cbClsExtra = 0;
wndCls.cbWndExtra = 0;
wndCls.hInstance = hInstance;
wndCls.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
wndCls.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndCls.lpszMenuName = NULL;
wndCls.lpszClassName = "WndClass";
if (!RegisterClass(&wndCls))
return FALSE;
hwndMain = CreateWindow(
"WndClass",
"Laboratorul nr 2",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,760,350,
(HWND) NULL,(HMENU) NULL,hInstance,(LPVOID) NULL);
if (!hwndMain)
return FALSE;
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
char sir[150];
short lungime=sprintf(sir, "Lucrarea de laborator nr.2 a studentului TI-122 Cobilas Adrian");
switch(uMsg){
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&rect);
//------------------------------------------------------------------------------
//Desenam linii dreapte
//
//crearea a doua penite noi
pen = CreatePen(PS_SOLID,2,RGB(255,100,100));
pen2 = CreatePen(PS_SOLID,2,RGB(20,60,50));
//pastrarea penitei vechi
old_pen=(HPEN)SelectObject(hdc,pen);
MoveToEx(hdc,50,50,NULL);
LineTo(hdc,150,150);
MoveToEx(hdc,150,150,NULL);
LineTo(hdc,50,150);
//stergerea penitei pen
DeleteObject(pen);
//------------------------------------------------------------------------------
//Desenam o elipsa impluta
//
//crearea unei noi pensule
//brush=CreateSolidBrush(RGB(0,33,33));
brush=CreateHatchBrush(HS_DIAGCROSS, RGB(33,200,230));
//pastrarea pensulei vechi
old_br=(HBRUSH)SelectObject(hdc,brush);
SelectObject(hdc,pen2);
//------------------------------------------------------------------------------
//Afisam text
//
SetTextColor(hdc, RGB(60,100,220));
//SetBkColor(hdc, RGB(60,100,100));
TextOut(hdc,150,200,sir,lungime);
//------------------------------------------------------------------------------
EndPaint(hwnd,&ps);
return 0;
case WM_CLOSE:
PostMessage(hwnd, WM_QUIT, 0L, 0L);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
Rezultatul rulării
Concluzii
In urma efectuarii acestei lucrari de laborator am studiat bazele şi principiile de functionare a functiilor
GDI.Am invatat sa folosim resursele acestei biblioteci pentru a desena diferite figuri utilizind primitivele
GDI.
Bibliografie
http://www.miv.ro/isip2009/ISIP2009_Lab1.pdf
http://www.infoap.utcluj.ro/wincpp/cap02/Cap2.pdf