Sunteți pe pagina 1din 9

Ministerul Educaţiei al Republicii Moldova

Universitatea Tehnică a Moldovei

Facultatea Calculatoare Informatica si Microelectronica

RAPORT
Lucrarea de laborator nr.2
Programarea in Windows

A efectuat:

A verificat:
lect., univ. Lisnic Inga

Chisinau 2017

Tema: Interfaţa GDI


Scopul lucrarii: De a studia primitivele oferite de interfaţa GDI

Sarcina de lucru: Scrieţi un program care afişează în zona client un desen animat, utilizând toate
primitivele GDI.

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

1. Descrieţi principalele primitive ale interfeţei grafice.


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

1
*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.

2. Enumeraţi metodele de obţinere a variabilei handle a dispozitivului de context.


Sistemul de operare Windows pune la dispoziţie mai multe metode pentru obţinerea variabilei handle a contextului
de dispozitiv.
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:
hdc - BeginPaint (hwnd, &ps);
[alte Unii de program] EndPaint (hwnd, &ps);
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:
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 funcţiilor BeginPaint şi EndPaint este că variabila

2
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:
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. Funcţia GetWindowDC este rareori folosită de aplicaţii. Dacă vreţi să experimentaţi folosirea
acestei funcţii, trebuie să interceptaţi mesajele WM_NCPAINT („nonclient paint"), împiedicând sistemul
de operare să redeseneze porţiunile din fereastră care nu fac parte din zona client.
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:
hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData);
[alte linii de program] DeleteDC (hdc);
De exemplu, puteţi să obţineţi variabila handle a contextului de dispozitiv pentru tot spaţiul de afişare, cu
următorul apel:
hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
Scrierea în afara ferestrei proprii nu este în general recomandată, dar poate fi convenabilă pentru unele
aplicaţii speciale. (Deşi această metodă nu e documentată, se poate obţine o variabila handle a contextului
de dispozitiv pentru întregul ecran şi prin apelarea funcţiei GetDC, cu parametrul NULL.) În Capitolul 15
vom folosi funcţia CreateDC pentru a obţine o variabilă handle a contextului de dispozitiv pentru o
imprimantă.
Uneori aveţi nevoie de unele informaţii despre un context de dispozitiv fără să desenaţi nimic. În această
situaţie puteţi să obţineţi o variabila handle a contextului de informaţii („information context") folosind
funcţia CreateIC. Parametrii sunt aceiaşi ca şi pentru funcţia CreateDC:
hdclnfo = CreatelC ("DISPLAY", NULL, NULL, NULL);
[alte linii de program] DeleteDC (hdclnfo);
Nu puteţi să executaţi operaţii de scriere la un dispozitiv folosind această variabilă handle. Atunci când
lucraţi cu imagini bitmap, poate fi uneori utilă obţinerea unui „context de dispozitiv în memorie":
hdcMem = CreateCompatibleDC (hdc);
[alte linii de program] DeleteDC (hdcHem)
Acesta este un concept destul de abstract. În esenţă, puteţi să selectaţi o imagine bitmap într-un context de
dispozitiv în memorie şi apoi să desenaţi peste folosind funcţiile GDI. Vom discuta mai târziu despre
această tehnică şi o vom folosi în programul GRAFMENU din Capitolul 10.

3
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:
hdcMeta = CreateMetaFile (pszFilename);
[alte linii de program] hmf = CloseMetaFile (hdcMeta);
Cât timp acest context este valid, nici un apel GDI pe care îl faceţi folosind parametrul hdcMeta nu
afişează nimic pe ecran, ci devine parte a metafişierului. Apelaţi apoi funcţia CloseMetaFile şi contextul
de dispozitiv este invalidat. Funcţia returnează o variabilă handle a metafişierului (hmf).

3. Ce sisteme de coordonate ale dispozitivului de context cunoaşteţi?


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"):
iValue = GetDeviceCaps (hdc, iIndex) ;
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

4
Listingul programului

#include <windows.h>
#include <string.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine,
int iCmdShow){
static char szAppName[] = "Window";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
// #Inregistrarea clasei ferestrei
wndclass.cbSize = sizeof(wndclass); //cbSize reprezinta dimensiunea
structurii
wndclass.style = CS_HREDRAW | CS_VREDRAW;//se restabileste de fiecare data
cand fereastra este redimensionata, fie pe orizontala sau pe verticala
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_INFORMATION);
wndclass.hCursor = LoadCursor(NULL, IDC_HAND);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
//GetStockObject obtine un obiect grafic (in acest caz o pensula folosita pentru
desenarea fondului ferestrei)
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL, IDI_INFORMATION);
if(!RegisterClassEx(&wndclass)){ //inregistreaza o clasa de fereastra
pentru fereastra programului
MessageBox(NULL, "Inregistrarea ferestrei a esuat!", "Eroare!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// #Crearea ferestrei
hwnd = CreateWindow(szAppName, // numele clasei de fereastra
(creaza o fereastra pe baza unei clase de fereastra )
"Laborator nr.1", // titlul ferestrei
WS_TILEDWINDOW, // stilul ferestrei
CW_USEDEFAULT, // pozitia initiala pe axa x
CW_USEDEFAULT, // pozitia initiala pe axa y
650, // dimensiunea initiala pe axa x
585, // dimensiunea initiala pe axa y
NULL, // variabila handle a ferestrei parinte
NULL, // variabila handle a meniului
hInstance, // variabila handle a instantei programului
NULL); // parametri de creare
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
// #Bucla de mesaje
while (GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);

}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam){
HDC hdc,hCompatibleDC;

5
PAINTSTRUCT ps;
RECT rect;
HPEN pen,pen2,old_pen;
HBRUSH brush,old_br;
HANDLE hOldBitmap;
HANDLE hBitmap;
BITMAP Bitmap;
char sir[100];
char lungime=sprintf(sir, "Lucrarea de laborator a studentului grupei TI-
154 Popusoi Victor");
// #Procedura ferestrei
switch (iMsg){
case WM_CREATE :
PlaySound ("vista.wav", NULL, SND_FILENAME | SND_ASYNC);
return 0 ;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
//------------------------------------------------------------------------
------
//Desenam linii dreapte
//------------------------------------------------------------------------
-------
//crearea a doua penite noi
MoveToEx(hdc,500,0,NULL);// punctul initial (x,y)
LineTo(hdc,500,760); // punctul final (x,y)
MoveToEx(hdc,0,35,NULL);
LineTo(hdc,1368,35);
MoveToEx(hdc,0,175,NULL);
LineTo(hdc,1368,175);
MoveToEx(hdc,0,325,NULL);
LineTo(hdc,1368,325);
pen = CreatePen(PS_SOLID,2,RGB(255,100,100)); // crearea penitei pen
pen2 = CreatePen(PS_SOLID,2,RGB(20,60,50)); // crearea penitei pen2
//pastrarea penitei vechi
old_pen=(HPEN)SelectObject(hdc,pen);

MoveToEx(hdc,50,65,NULL);
LineTo(hdc,80,145);
MoveToEx(hdc,80,145,NULL);
LineTo(hdc,110,65);
MoveToEx(hdc,110,65,NULL);
LineTo(hdc,140,145);
MoveToEx(hdc,140,145,NULL);
LineTo(hdc,170,65);
//stergerea penitei pen
DeleteObject(pen);
//------------------------------------------------------------------------
------
// Desenam un dreptunghi
//------------------------------------------------------------------------
------
//crearea unei noi pensule
brush=CreateSolidBrush(RGB(0,0,255));// coloreaza toata figura
//brush=CreateHatchBrush(HS_BDIAGONAL,RGB(0,0,255)); // hasureaza figura
//pastrarea pensulei vechi
old_br=(HBRUSH)SelectObject(hdc,brush);
SelectObject(hdc,pen2);
Rectangle(hdc,50, 200, 250, 300); //Dreptunghi (50,200 virful sting de
sus) (250,300 virful drept de jos)

6
//stergerea obiectelor create
DeleteObject(pen2); // stergerea penitei pen2
DeleteObject(brush); // stergerea suprafetei colorate a figurii
//restaurarea obiectelor anterioare
SelectObject(hdc,old_pen); //selectam penita old_pen
SelectObject(hdc,old_br);
//------------------------------------------------------------------------
------
// Incarcam o imagine BITMAP
//------------------------------------------------------------------------
------
hBitmap
=(HBITMAP)LoadImage(NULL,"image.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
GetObject(hBitmap,sizeof(BITMAP),&Bitmap); //Obtinem marimea imaginii
bitmap
hCompatibleDC = CreateCompatibleDC(hdc); //Cream o noua variabila handle a
contextului de dispozitiv
hOldBitmap = SelectObject(hCompatibleDC,hBitmap);//Pastram imaginea veche
bitmap

StretchBlt(hdc,50,350,200,175,hCompatibleDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,S
RCCOPY); //Copiem imaginea bitmap si o deplasam
SelectObject(hCompatibleDC,hOldBitmap); //Restauram obiectul anterior
DeleteObject(hBitmap); //Stergem imaginea bitmap incarcata
DeleteDC(hCompatibleDC); //Stergem variabila handle a contextului de
dispozitiv
//------------------------------------------------------------------------
------
// Afisam text
//------------------------------------------------------------------------
------
SetTextColor(hdc, RGB(50,150,100));
TextOut(hdc,50,10,sir,lungime);
char sir2[50];
char lungime2=sprintf(sir2, "1. Text");
SetTextColor(hdc, RGB(50,50,50));
TextOut(hdc,510,10,sir2,lungime2);
char sir3[50];
char lungime3=sprintf(sir3, "2. Line");
SetTextColor(hdc, RGB(50,50,50));
TextOut(hdc,510,90,sir3,lungime3);
char sir4[50];
char lungime4=sprintf(sir4, "3. Figure");
SetTextColor(hdc, RGB(50,50,50));
TextOut(hdc,510,240,sir4,lungime4);
char sir5[50];
char lungime5=sprintf(sir5, "4. Image");
SetTextColor(hdc, RGB(50,50,50));
TextOut(hdc,510,420,sir5,lungime5);
//------------------------------------------------------------------------
------
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

7
Rezultatele obtinute

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.

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