Documente Academic
Documente Profesional
Documente Cultură
RAPORT
Lucrarea de laborator nr.2
Programarea in Windows
A efectuat:
A verificat:
lect., univ. Lisnic Inga
Chisinau 2017
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
*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
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).
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