Download - GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

Transcript
Page 1: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

1

GDI Biblioteca GDI32.DLL GDI = permite manipularea elementelor grafice independente de dispozitiv, este un sistem de afisare static, ce permite numai animatii simple; Dipozitive grafice de iesire:

1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, imprimante matriciale, laser);

2. dispozitive vectoriale = deseneaza imaginile prin linii = plottere; Sistem de coordonate virtual, sistem de coordonate al dispozitivului; W95 foloseste coordonate in numere intregi pe 16 biti, W_NT foloseste coordonate pe 32 biti; Din pdv al programatorului, interfata GDI este formata din citeva sute de rutine si unele tipuri de date, macroinstructiuni si structuri de date; Tipuri de apeluri de functii

• Functii care obtin (sau creaza) si elibereaza (sau distrug) un context de

dispozitiv; (in API: BeginPaint ... EndPaint, GetDc,

ReleaseDC; in MFC (clase): CDC, CPaintDC, CClientDC,

CMetaFileDC, CWindowDC) • Functii care obtin informatii despre contextul de dispozitiv - structura

TEXTMETRICS, GetTextMetrics; • Functii care deseneaza ceva (TextOut, DrawText, desenarea liniilor, a

zonelor colorate si a imaginilor bitmap...); • Functii care stabiliesc sau obtin atribute ale contextului de dispozitiv - 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 lucreaza cu obiecte GDI; Primitive GDI

• Linii si curbe: linii drepte, dreptunghiuri, elipse, arce. Liniile sint desenate folosind penita (HPEN, clasa CPen) curenta selectata in DC

• Suprafete pline: Suprafata poate fi umpluta folosind pensula GDI curenta (HBRUSH, clasa CBrush)

• Imagini bitmap: matrici dreptunghiulare de biti, care corespund pixelilor unui dispozitiv de afisare - pt. sisteme grafice de tip rastru. Imagini bitmap - dependente de dispozitiv si imagini bitmap independente de dispozitiv (DIB = Device Independent Bitmap) care pot fi stocate in fisiere.

• Text: afisarea textului este legata de fonturi (HFONT, clasa CFont). Alte aspecte ale GDI:

• Moduri de mapare si transformari: sitem de coordonate in pixeli, inci, mm • Metafisiere (metafiles): o colectie de comenzi GDI stocate intr-o forma binara;

sint folosite pentru transferarea reprezentarilor unor elemente grafice vectoriale prin intermediul memoriei temporare (clipboard).

Page 2: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

2

• Cai (paths): colectie de linii drepte si curbe stocate intern de GDI; pot fi folosite pt. desenare, umplere sau decupare.

• Decupare (clipping): desenarea poate fi limitata la o anumita sectiune a zonei client, numita zona de decupare - definita in general de o cale sau de o regiune.

• Tiparire (printing):

Contextul de dispozitiv (DC): Modalitati de obtinere a variabilei handle a DC:

• Varainata 1(putem desena numai in regiunea invalida a ferestrei): la tratarea mesajului WM_PAINT:

PAINTSTRUCT ps;

hdc = BeginPaint (hwnd, &ps);

...

EndPaint(hwnd, &ps);

structura PAINTSTRUCT contine o structura de tip RECT rcPaint; care defineste dreptunghiul ce cuprinde regiunea invalida a zonei client a ferestrei; se valideaza regiunea invalida.

• Varianta 2 (putem desena in toata zona client a ferestrei; nu se valideaza regiunea invalida ale zonei client):

hdc = GetDC(hwnd);

...

ReleaseDC(hwnd, hdc);

• Varianta 3: (DC cuprinde in plus bara de titlu a ferestrei, barele de derulare si chenarul)

hdc = GetWindowDC(hwnd);

...

ReleaseDC(hwnd, hdc);

Pentru folosirea acestei functii trebuie interceptat mesajul WM_NCPAINT ( non client paint).

• Varianta 4: CreateDC

hdc = CreateDC(pszDriver, pszDevice, pszOutput,

pData);

...

DeleteDC(hdc);

Pentru a obtine o variabila handle a DC pt. spatiul de afisare: hdc = CreateDC(“DISPLAY”, NULL, NULL, NULL);

Page 3: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

3

• Varianta 5: Obtinere informatii despre DC - CreateIC care are aceeasi parametri ca si CreateDC

hdc = CreateIC(pszDriver, pszDevice, pszOutput,

pData);

...

DeleteDC(hdc);

• Varianta 6: context de dispozitiv in memorie - necesar la lucrul cu imagini

bitmap:

hdcmem = CreateCompatibleDC (hdc)

...

DeleteDC(hdcMem);

• Crearea unui metafisier:

hdcMeta = CreateMetaFile(pszFileName);

...

hmf = CloseMetaFile(hdcMeta);

Obtinere informatii despre contextul de dispozitiv: dimensiuni ecran (pixeli, fizice) posibilitati de folosire a culorilor, etc. cu functia GetDeviceCaps (get device capabilities); ivalue = GetDeviceCaps(hdc, iIndex);

Atributele Contextului de Dispozitiv

Cele mai uzuale atribute ale DC sunt date in urmatorul tabel:

Attribute Default Set with Get with Text color Black CDC::SetTextColor CDC::GetTextColor Background color White CDC::SetBkColor CDC::GetBkColor Background mode OPAQUE CDC::SetBkMode CDC::GetBkMode Mapping mode MM_TEXT CDC::SetMapMode CDC::GetMapMode Drawing mode R2_COPYPEN CDC::SetROP2 CDC::GetROP2 Current position (0,0) CDC::MoveTo CDC::GetCurrentPosition Current pen BLACK_PEN CDC::SelectObject CDC::SelectObject Current brush WHITE_BRUSH CDC::SelectObject CDC::SelectObject Current font SYSTEM_FONT CDC::SelectObject CDC::SelectObject

GDI Moduri de desenare – functia SetROP2 Mod de desenare Operatii executate

R2_NOP dest = dest R2_NOT dest = NOT dest

Page 4: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

4

R2_BLACK dest = BLACK R2_WHITE dest = WHITE R2_COPYPEN dest = src R2_NOTCOPYPEN dest = NOT src R2_MERGEPENNOT dest = (NOT dest) OR src R2_MASKPENNOT dest = (NOT dest) AND src R2_MERGENOTPEN dest = (NOT src) OR dest R2_MASKNOTPEN dest = (NOT src) AND dest R2_MERGEPEN dest = dest OR src R2_NOTMERGEPEN dest = NOT (dest OR src) R2_MASKPEN dest = dest AND src R2_NOTMASKPEN dest = NOT (dest AND src) R2_XORPEN dest = src XOR dest R2_NOTXORPEN dest = NOT (src XOR dest)

Moduri de mapare – functia SetMapMode Mod de mapare Distanta ce corespunde la o

unitate logica Axa x Axa y

MM_TEXT Pixel spre dreapta in jos MM_LOMETRIC 0,1 mm spre dreapta in sus MM_HIMETRIC 0,01 mm spre dreapta in sus MM_LOENGLISH 0.01 inci spre dreapta in sus MM_HIENGLISH 0.001 inci spre dreapta in sus MM_TWIPS 1/1440 inci spre dreapta in sus MM_ISOTROPIC arbitrar (x = y) Selectabil selectabil MM_ANISOTROPIC Arbitrar (x!=y) Selectabil Selectabil

Vizorul si fereastra SetWindowExt – seteaza “extensia ferestrei” – marimea dorita a ferestrei in unitati logice. SetViewportExt – seteaza “extensia vizorului” – marimea in pixeli a ferestrei in care desenam.. Marimea fereastrei este masurata in unitati logice. Marimea viewport-ului este masurata in unitati de dispozitiv, sau pixeli. In modul MM_ISOTROPIC ordinea de apel este SetWindowExt si apoi SetViewportExt. Exemple de cod CRect rect;

GetClientRect (&rect);

dc.SetMapMode (MM_ANISOTROPIC);

dc.SetWindowExt (500, 500);

Page 5: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

5

dc.SetViewportExt (rect.Width (), rect.Height ());

dc.Ellipse (0, 0, 500, 500); Originea este in coltul din stanga sus. CRect rect;

GetClientRect (&rect);

dc.SetMapMode (MM_ANISOTROPIC);

dc.SetWindowExt (500, -500);

dc.SetViewportExt (rect.Width (), rect.Height ());

dc.Ellipse (0, 0, 500, -500); Modul MM_ISOTROPIC CRect rect;

GetClientRect (&rect);

dc.SetMapMode (MM_ISOTROPIC);

dc.SetWindowExt (500, 500);

dc.SetViewportExt (rect.Width (), rect.Height ());

dc.Ellipse (0, 0, 500, 500); Pentru vizor se folosesc coordonatele de dispozitiv (pixeli). Pentru toate modurile de mapare, Windows transforma coordonatele ferestrei (coordonate logice) in coordonate ale vizorului (coordonate de dispozitiv) folosind doua formule: xViewport = (xWindow - xWinOrg) * (xViewExt / xWinExt) + xViewOrg yViewport = (yWindow - yWinOrg) * (yViewExt / yWinExt) + yViewOrg unde (xWindow, yWindow) este punct in coordonate logice care trebuie translatat; (xViewport, yViewport) este punct in coordonate de dispozitiv; (xWinOrg, yWinOrg) = originea ferestrei in coordonate logice; (xViewOrg, yViewOrg) = originea vizorului in coordonate dispozitiv. Formulele de mai sus implica faptul ca punctul (xWinOrg, yWinOrg) este intotdeauna mapat la punctul (xViewOrg, yViewOrg). (xWinExt, yWinExt) = extensia ferestrei in coordonate logice; (xViewExt, yViewExt) = extensia vizorului in coordonate de dispozitiv; In majoritatea modurilor de mapare aceste extensii sint prestabilite si nu pot fi modificate. Raportul intre extensia vizorului si extensia ferestrei reprezinta un factor de scalare folosit pentru convertirea unitatilor logice in unitati de dispozitiv. Extensiile pot avea valori negative: aceasta inseamna ca nu este obligatoriu ca valorile pe axa x sa creasca spre dreapta si valorile pe axa y sa creasca in jos.

Page 6: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

6

Functiile folosite pentru a realiza conversia intre puncte reprezentate in coordonate de dispozitiv in puncte reprezentate in coordonate logice si invers sunt:

DPtoLP(hdc, pPoints, iNumber);

LPtoDP(hdc, pPoints, iNumber);

pPoints = matrice de structuri POINT iNumber = numarul de puncte care urmeaza a fi convertite. Daca dorim sa stim unde este punctul din centru in unitati MM_LOENGLISH, trebuie sa folosim DPtoLP : CRect rect;

GetClientRect (&rect);

CPoint point (rect.Width () / 2, rect.Height () / 2);

CClientDC dc (this);

dc.SetMapMode (MM_LOENGLISH);

dc.DPtoLP (&point);

DPtoLP va returna coordonatele punctului central in coordonate logice. Daca dorim sa stim coordonatele in pixeli al punctului de coordonate logice (100,100) in modul de mapare MM_LOENGLISH vom folosi LPtoDP: CPoint point (100, 100);

CClientDC dc (this);

dc.SetMapMode (MM_LOENGLISH);

dc.LPtoDP (&point);

Modul MM_TEXT Functiile SetViewportOrgEx si SetWindowOrgEx modifica originea vizorului si a ferestrei. Aceste functii au ca efect deplasarea axelor astfel incit punctul de coordonate (0,0) nu se mai refera la coltul din stanga sus al ecranului. In general se foloseste doar una din cele doua functii. Explicati asupra lucrului cu aceste functii:

• daca schimbam originea vizorului la (xViewOrg, yViewOrg) atunci punctul logic de coordonate (0,0) va fi mapat la punctul de coordonate de dispozitiv (xViewOrg, yViewOrg).

• daca schimbam originea ferestrei la (xWinOrg, yWinOrg) atunci acest punct logic va fi mapat la punctul de coordonate de dispozitiv (0,0) care este intotdeauna coltul din stinga sus al zonei client.

Exemplu – Mutare origine

Page 7: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

7

Sa presupunem ca zona client are latimea cxClient si inaltimea cyClient. Daca dorim ca punctul de coordonate logice (0,0) sa se afle in centrul zonei client, atunci: SetViewportOrgEx(hdc, cxClient/2, cyClient/2, NULL);

Valorile logice ale axei x sint cuprinse in intervalul [-cxClient/2, cxClient/2], iar

cele ale axei y in intervalul [-cyClient/2, cyClient/2]. Afisarea de text incepind cu coltul din stanga sus, care are coordonatele de dispozitiv (0,0) inseamna folosirea urmatoarelor coordonate logice:

TextOut(hdc, -cxClient/2, -cyClient/2, “...”,...);

Acelasi rezultat poate fi obtinut si cu functia SetWindowOrgEx in locul

functiei SetViewportOrgEx:

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

Setarea extent-ului O aplicatie poate modifica in mod direct extentul ferestrei sau al vizorului numai daca modul de mapare este MM_ISOTROPIC sau MM_ANISOTROPIC. Modficarea extentului ferestrei se face cu ajutorul functiei SetWindowExt, iar extentul vizorului se modifica cu functia SetViewportExt. Valorile se dau totdeauna in unitati absolute, nu in unitati logice si nu sunt afectate de modul curent de mapare. Setarea unui extent la valoarea zero nu este permisa. Din cauza ca perechea de extent-uri stabileste un factor de scalare ce va fi folosit in conversii, marimea extentului ar trebui sa fie cat mai mica posibila pentru a simplifica calculele, de exemplu folosirea de extent-uri de 400 si 300 este echivalent cu exetent-uri de 4 si 3. Pentru a schimba orientarea unei axe (fata de orientarea implicita data de Windows), factorul de scalare trebuie sa fie negativ. Urmatorul cod are ca efect schimbarea orientarii axei y, y

pozitiv va fi “in sus”.

SetMapMode(hDC, MM_ANISOTROPIC);

SetViewportExt(hDC, 1, -1);

SetWindowExt(hDC, 1, 1);

Page 8: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

8

Setarea originilor

Functiile folosite sunt: SetWindowOrg, OffsetWindowOrg, SetViewportOrg si OffsetViewportOrg. Originile sunt independente de extent. Originile sunt specificate in unitati absolute ce nu sunt afectate de modul curent de mapare.

Exemple Setam un mod de mapare in care la o unitate logica ii corespund trei unitati de dispozitiv:

SetMapMode(hDC, MM_ANISOTROPIC);

SetWindowOrg(hDC, 0, 0);

SetWindowExt(hDC, 1, 1);

SetViewportOrg(hDC, 0, 0);

SetViewportExt(hDC, 3, 3); Urmatorul cod deseneaza un dreptunghi de 1 pe 2 mm.

SetMapMode(hDC, MM_HIMETRIC);

SetViewportOrg(hDC, 0, 100); // Ce ...?

SetWindowOrg(hDC, 0, 0);

Rectangle(hDC, 0, 0, 100, 200); Unitatile de dispozitiv sunt mapate la rezolutia dispozitivului fizic:

SetMapMode(hDC, MM_ANISOTROPIC);

SetWindowOrg(hDC, 0, 0);

SetWindowExt(hDC, 600, 600); // logical window is 600 dpi

SetViewportOrg(hDC, 0, 0);

// Device viewport is dpi of actual output device.

SetViewportExt(hDC, GetDeviceCaps(hDC, LOGPIXELSX),

GetDeviceCaps(hDC, LOGPIXELSY));

Page 9: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

9

Obtinerea informatiilor despre un periferic Functia CDC::GetDeviceCaps Urmatorul cod obtine rezolutia ecranului, in pixeli: CClientDC dc (this);

int cx = dc.GetDeviceCaps (HORZRES);

int cy = dc.GetDeviceCaps (VERTRES);

Functia GetDeviceCaps va returna totdeauna valori fizice corecte pentru imprimanta sau orice alt periferic hardcopy (de exemplu LOGPIXELSX si LOGPIXELSY). Pentru o imprimanta laser cu 600 dpi, LOGPIXELSX si LOGPIXELSY vor avea valoarea 600. Useful GetDeviceCaps Parameters

Parameter Returns HORZRES Width of the display surface in pixels VERTRES Height of the display surface in pixels HORZSIZE Width of the display surface in millimeters VERTSIZE Height of the display surface in millimeters LOGPIXELSX Number of pixels per logical inch horizontally LOGPIXELSY Number of pixels per logical inch vertically NUMCOLORS For a display device, the number of static colors; for a printer or

plotter, the number of colors supported BITSPIXEL Number of bits per pixel PLANES Number of bit planes RASTERCAPS Bit flags detailing certain characteristics of the device, such as

whether it is palettized and whether it can display bitmapped images TECHNOLOGY Bit flags identifying the device type—screen, printer, plotter, and so

on

Page 10: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

10

Desenarea pe ecran (Exemple de cod)

Windows este un SO independent de dispozitiv. Pentru că nu ştim niciodată dinainte ce tipuri de periferice pot fi conectate la sistemul utilizatorului, nu putem face presupuneri despre posibilităţile de afişare ale acestora. Funcţiile care desenează pe ecran, trebuie să facă acest lucru indirect prin intermediul aşa numitelor contexte de dispozitiv (DC). Windows manipulează perifericele cu ajutorul driver-elor instalate de utilizator pe sistem. Aceste drivere interceptează datele pe care aplicaţiile doresc să le afişeze şi apoi translatează aceste date pentru perifericul respectiv pentru a fi reprezentate cât mai corect. Driverele de dispozitiv trebuie să ia cerinţele de afişare să le ajusteze (fine tuning) funcţie de perifericul (dispozitivul) pe care vor apărea. Există o structură de date, cunoscută sub numele de context de dispozitiv, care leagă aplicaţia de driverul dispozitivului. Un context de dispozitiv este mai mult decât o structură de date în memorie care păstrează atributele suprafeţei de desenare a ferestrei. Aceste atribute includ: peniţa, pensula, fontul, etc. Un DC conţine la un moment dat o singură peniţă (de exemplu). Pentru a folosi diverse peniţe, trebuie să le creăm şi apoi selectăm în cadrul DC. Zona client este suprafaţa în care un program poate desena orice. Afişarea în zona client se face cu ajutorul funcţiilor din GDI.

Construirea unei aplicatii pentru exemplificarea folosirii penitelor, pensulelor si fonturilor

Vom construi o aplicaţie cu arhitectura Document/View şi de tip SDI, în care vom exemplifica folosirea peniţelor, fonturilor şi a pensoanelor. Vom afişa text cu diverse fonturi, vom desena linii de diferite grosimi (cu peniţe diferite), vom desena dreptunghiuri sau zone închise umplute cu pensule diferite.

WM_PAINT Un mesaj important pe care fiecare program Windows, cu o fereastră, trebuie să-l trateze este WM_PAINT. Windows trimite mesajul WM_PAINT ferestrei aplicaţiei când fereastra trebuie să se redeseneze. Mai multe evenimente fac ca Windows să trimită acest mesaj: � Când utilizatorul lansează programul în execuţie pentru prima dată, fereastra

aplicaţiei primeşte acest mesaj imediat după începerea execuţiei, pentru a afişa informaţiile necesare pentru început.

Page 11: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

11

� Cănd fereastra a fost redimensionată sau a fost descoperită (total sau parţial) de o altă fereastră. Partea din fereastră care a fost acoperită trebuie acum redesenată şi actualizată.

� Când un program îşi trimite indirect mesajul WM_PAINT prin invalidarea zonei client. Această funcţionalitate asigură faptul că o aplicaţie poate schimba conţinutul ferestrei aproape în orice moment doreşte. De exemplu, un procesor de texte poate invalida fereastra sa după ce utilizatorul a copiat tet din Clipboard.

Macroul din harta de mesaje pentru WM_PAINT este ON_WM_PAINT(), iar funcţia ce corespunde tratării acestui mesaj este OnPaint(). Posibil cod în OnPaint():

void CView::OnPaint()

{

// rutina standard de desenare

CPaintDC dc(this);

OnPrepareDC(&dc);

OnDraw(&dc);

}

CPaintDC este o clasă specială pentru gestionarea DC-ului folosit numai când se răspunde la mesajul WM_PAINT. Un obiect al clasei CPaintDC în afară de faptul că crează DC apelează şi funcţia BeginPaint() în constructorul clasei şi apelează funcţia EndPaint() în destructor. Constructorul CPaintDC ia un singur argument, care este un pointer la fereastra pentru care am creat DC. Pointer-ul this punctează la vederea curentă, deci putem să-l pasăm în constructor pentru a crea un DC pentru vederea curentă. OnPrepareDC() este o funcţie din CView care pregăteşte DC-ul pentru a fi folosit. OnDraw() afişează documentul în zona client.

Schimbarea afisarii

Logica aplicaţiei este următoarea: la apăsarea butonului stâng al mouse-ului se va afişa fie text cu un anumit font, fie o linie cu o anumită peniţă, fie un dreptunghi umplut cu o anumita pensula. Comutarea afişării se face cu ajutorul unei variabile m_Display definită în clasa derivată din CView. Valoarea implicită a acestei variabile este Fonts şi se actualizează circular pe mesajul WM_LBUTTONDOWN, cu valorile Pens şi apoi Brushes, samd. În definiţia clasei: protected:

enum {Fonts, Pens, Brushes} m_Display;

Page 12: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

12

În constructor:

m_Display = Fonts; iar desenarea in void CXView::OnDraw(CDC* pDC)

{

CPaint1Doc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

switch (m_Display)

{

case Fonts:

ShowFonts(pDC);

break;

case Pens:

ShowPens(pDC);

break;

case Brushes:

ShowBrushes(pDC);

break;

}

}

Vom scrie funcţiile ShowFonts(), ShowPens() şi ShowBrushes(). Vom adăuga funcţiile în definiţia clasei şi apoi vom scrie codul în implementarea clasei. void CXView::OnLButtonDown(UINT nFlags, CPoint point)

{

if (m_Display == Fonts)

m_Display = Pens;

else if (m_Display == Pens)

m_Display = Brushes;

else

m_Display = Fonts

Invalidate(); // generează mesajul WM_PAINT

CView::OnLButtonDown(nFlags, point);

}

Folosirea fonturilor

Trebuiesc cercetate fonturile care sunt instalate în sistem. Un font Windows este descris într-o structură LOGFONT.

Page 13: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

13

LOGFONT Fields and Their Descriptions

Field Description lfHeight Font height in logical units lfWidth Font width in logical units lfEscapement Angle at which to draw the text lfOrientation Character tilt in tenths of a degree lfWeight Font weight lfItalic A nonzero value indicates italics lfUnderline A nonzero value indicates an underlined font lfStrikeOut A nonzero value indicates a strikethrough font lfCharSet Font character set lfOutPrecision How to match requested font to actual font lfClipPrecision How to clip characters that run over clip area lfQuality Print quality of the font lfPitchAndFamily Pitch and font family lfFaceName Typeface name Unitatea logică (logical units) depinde de modul de mapare folosit. Modul de mapare implicit este MM_TEXT care înseamnă că o unitate logică este egală cu un pixel.

Moduri de mapare

Mode Unit MM_HIENGLISH 0.001 inch

MM_HIMETRIC 0.01 millimeter

MM_ISOTROPIC Arbitrary MM_LOENGLISH 0.01 inch

MM_LOMETRIC 0.1 millimeter MM_TEXT Device pixel

MM_TWIPS 1/1440 inch

Escapement se referă la a scrie text de-a lungul unei linii ce face cu orizontala un anumit unghi. Orientation se referă la a scrie text de-a lungul unei linii (flat line). Ponderea (weight) fontului se referă la (thickness) subţirimea literelor. Au fost definite un număr de constante pentru a fi utilizate cu acest câmp: FW_DONTCARE, FW_THIN, FW_EXTRALIGHT, FW_ULTRALIGHT, FW_LIGHT, FW_NORMAL, FW_REGULAR, FW_MEDIUM, FW_SEMIBOLD, FW_DEMIBOLD, FW_BOLD, FW_EXTRABOLD, FW_ULTRABOLD, FW_BLACK, şi FW_HEAVY. Nu toate fonturile sunt disponibile în toate ponderile. Sunt disponibile patru mulţimi de caractere (ANSI_CHARSET, OEM_CHARSET, SYMBOL_CHARSET, şi UNICODE_CHARSET), dar pentru a scrie text în engleză vom folosi totdeauna ANSI_CHARSET.

Page 14: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

14

Ultimul câmp din structură reprezintă numele fontului (de ex. Helvetica, Times New Roman, etc.) void CXView::ShowFonts(CDC * pDC)

{

// Initializare structura LOGFONT pentru fonturi

LOGFONT logFont;

logFont.lfHeight = 8;

logFont.lfWidth = 0;

logFont.lfEscapement = 0;

logFont.lfOrientation = 0;

logFont.lfWeight = FW_NORMAL;

logFont.lfItalic = 0;

logFont.lfUnderline = 0;

logFont.lfStrikeOut = 0;

logFont.lfCharSet = ANSI_CHARSET;

logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;

logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;

logFont.lfQuality = PROOF_QUALITY;

logFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;

strcpy(logFont.lfFaceName, "Times New Roman");

// Initializare pozitie text in fereastra.

UINT position = 0;

// Creaza si afiseaza 8 exemple de fonturi.

for (UINT x=0; x<8; ++x)

{

// Setam inaltimea noului font.

logFont.lfHeight = 16 + (x * 8);

// Cream un nou font si-l selectam intr-un

// context de dispozitiv.

CFont font;

font.CreateFontIndirect(&logFont);

CFont* oldFont = pDC->SelectObject(&font);

// Tiparim textul cu noul font.

position += logFont.lfHeight;

pDC->TextOut(20, position, "Exemplu de font.");

// Restauram vechiul font in DC.

pDC->SelectObject(oldFont);

}

Page 15: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

15

}

Explicaţii la acest cod. Se va rula aplicaţia în acest moment. Se va constata că nu pot fi afişate toate informaţiile în zona client.

Marire si pozitionare fereastra

Informaţiile nu pot fi afişate în zona client la o rezolutie a ecranului de 800*600. Acest lucru se corectează prin mărirea ferestrei, care se face în funcţia PreCreateWindow() din CMainFrame. Această funcţie este apelată înainte ca fereastra să fie creată. PreCreateWindow() are un singur parametru, o referinţă la o structură CREATESTRUCT. Această structură conţine informaţii despre fereastra care va fi creată.

CREATESTRUCT Structure

typedef struct tagCREATESTRUCT {

LPVOID lpCreateParams;

HANDLE hInstance;

HMENU hMenu;

HWND hwndParent;

int cy;

int cx;

int y;

int x;

LONG style;

LPCSTR lpszName;

LPCSTR lpszClass;

DWORD dwExStyle;

} CREATESTRUCT;

cx şi cy menţin lăţimea şi înălţimea ferestrei, iar x şi y poziţia acesteia. Se inhibă redimensionarea ferestrei (style). BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

cs.cx = 440;

cs.cy = 480;

cs.style &= ~WS_SIZEBOX;

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE;

return TRUE;

}

Majoritatea funcţiilor rescrise şi apelate de cadrul de lucru trebuie să apeleze în final versiunea din clasa de bază.

Page 16: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

16

Folosirea penitelor

Vezi clasa CPen.

void CXView::ShowPens(CDC * pDC)

{

// Initializam pozitia liniei

UINT position = 10;

// Desenam 16 linii in fereastra

for (UINT x=0; x<16; ++x)

{

// Cream o noua penita si o

// selctam in contextul de dispozitiv

CPen pen(PS_SOLID, x*2+1, RGB(0, 0, 255));

CPen* oldPen = pDC->SelectObject(&pen);

// Desenam o linie cu noua penita

position += x * 2 + 10;

pDC->MoveTo(20, position);

pDC->LineTo(400, position);

// Repunem vechea penita in DC

pDC->SelectObject(oldPen);

}

} Explicaţii la acest cod.

Stiluri penita

Style Description PS_DASH A pen that draws dashed lines PS_DASHDOT A pen that draws dash-dot patterned lines PS_DASHDOTDOT A pen that draws dash-dot-dot patterned lines PS_DOT A pen that draws dotted lines

PS_INSIDEFRAME A pen that's used with shapes, in which the line's thickness must not extend outside the shape's frame

PS_NULL A pen that draws invisible lines PS_SOLID A pen that draws solid lines

Folosirea pensulelor

Cu ajutorul unei pensule desenam interiorul unei figuri de pe ecra. Putem crea pensule solide, pensule cu un anumit şablon şi chiar pensule din bitmap-uri.

Page 17: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

17

void CXView::ShowBrushes(CDC * pDC)

// Initializam dreptunghiul de pozitionare

UINT position = 0;

// Selectam penita ce va fi folosita pentru

// a desena conturul dreptunghiului

CPen pen(PS_SOLID, 5, RGB(255, 0, 0));

CPen* oldPen = pDC->SelectObject(&pen);

// Desenam 7 dreptunghiuri.

for (UINT x=0; x<7; ++x)

{

CBrush* brush;

// Cream o pensula

if (x == 6)

brush = new CBrush(RGB(0,255,0));

else

brush = new CBrush(x, RGB(0,160,0));

// Selectam noua pensula in DC

CBrush* oldBrush = pDC->SelectObject(brush);

// Desenam dreptunghiul

position += 50;

pDC->Rectangle(20, position, 400, position + 40);

// Restauram vechea pensula si o stergem pe cea

noua

pDC->SelectObject(oldBrush);

delete brush;

}

// Restauram vechea penita

pDC->SelectObject(oldPen);

} Stiluri pentru pensoane:

• HS_HORIZONTAL--Horizontal

• HS_VERTICAL--Vertical

• HS_CROSS--Horizontal and vertical

• HS_FDIAGONAL--Forward diagonal

• HS_BDIAGONAL--Backward diagonal

Page 18: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

18

• HS_DIAGCROSS--Diagonal in both directions

Observaţie: Trebuie să apelăm Invalidate() în OnLButtonDown(). Invalidate() are un singur argument (Boolean) cu valoarea implicită TRUE. Acest argument are ca efect ştergerea sau nu a background-ului. Dacă valoarea este FALSE, backgroundul nu va fi şters.

Ferestre cu bare de navigare

(scrolling Windows – ferestre cu derulare) Ferestrele ne permit de a partiţiona ecranul între diverse aplicaţii şi documente. Dacă folosim MFC şi derivăm clasa de vizualizare din CScrollView, atunci fereastra are posibilităţi de derulare.

Indicatii de construire a unei aplicatii cu ferestre cu

derulare Vom construi o aplicaţie pentru a exemplifica posibilităţile de derulare. În cadrul aplicaţiei iniţial se vor afişa 5 linii de text, iar pe mesajul WM_LBUTTONDOWN vom adăuga de fiecare dată încă 5 linii te text, astfel că la un moment dat textul nu va mai încăpea în fereastră. Numărul liniilor de text care sunt afişate în zona client le vom gestiona cu ajutorul unei variabile din clasa derivata din CDocument public:

int m_NumLines; pe care o iniţializăm în constructorul clasei:

m_NumLines = 5; Această variabilă o putem serializa: void CScrollDoc::Serialize(CArchive& ar)

{

if (ar.IsStoring())

{

ar << m_NumLines;

}

else

{

ar >> m_NumLines;

}

}

Page 19: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

19

În vizualizare: void CMyScrollView::OnDraw(CDC* pDC)

{

CScrollDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// obtinem numarul de linii din document

int numLines = pDoc->m_NumLines;

// Initializam o structura LOGFONT pentru fonturi.

LOGFONT logFont;

logFont.lfHeight = 24;

logFont.lfWidth = 0;

logFont.lfEscapement = 0;

logFont.lfOrientation = 0;

logFont.lfWeight = FW_NORMAL;

logFont.lfItalic = 0;

logFont.lfUnderline = 0;

logFont.lfStrikeOut = 0;

logFont.lfCharSet = ANSI_CHARSET;

logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;

logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;

logFont.lfQuality = PROOF_QUALITY;

logFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;

strcpy(logFont.lfFaceName, "Times New Roman");

// Cream un nou font si il selectam in DC

CFont* font = new CFont();

font->CreateFontIndirect(&logFont);

CFont* oldFont = pDC->SelectObject(font);

// Initializam pozitia textului in fereastra

UINT position = 0;

// Cream si afisam 8 linii de text

for (int x=0; x<numLines; ++x)

{

// Cream sirul de caractere ce va fi afisat

char s[25];

wsprintf(s, "Linia numarul: #%d", x+1);

// Tiparim textul cu noul font

pDC->TextOut(20, position, s);

// Trecem pe linia urmatoare

position += logFont.lfHeight;

}

// Restauram vechiul font in DC si stergem fontul creat de program

pDC->SelectObject(oldFont);

delete font;

}

Page 20: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

20

Explicaţie cod. Se va rula aplicaţia.

Modificarea codului pentru a creste numarul de linii afisate pe ecran

Pe mesajul WM_LBUTTONDOWN

void CMyScrollView::OnLButtonDown(UINT nFlags, CPoint

point)

{

CScrollDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// Marim numarul liniilor de afisat

//(cu 5 la fiecare clic stanga mouse)

pDoc->m_NumLines += 5;

// Redesenam fereastra

Invalidate();

CScrollView::OnLButtonDown(nFlags, point);

}

Micsorarea numarului de linii

void CMyScrollView::OnRButtonDown(UINT nFlags, CPoint point)

{

CScrollDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// Micsoram numarul liniilor de afisat

// (cu 5 la fiecare clic dreapa mouse)

pDoc->m_NumLines -= 5;

if (pDoc->m_NumLines < 0)

{

pDoc->m_NumLines = 0;

}

// Redesenam fereastra.

Invalidate();

CScrollView::OnRButtonDown(nFlags, point);

}

Dacă rulăm aplicaţia vom observa că barele de derulare nu apar. Trebuie modificată funcţia OnDraw().

Linii de cod ce se vor adauga la OnDraw()

// Calculam marimea documentului

CSize docSize(100, numLines*logFont.lfHeight);

// Calculam marimea paginii

CRect rect;

GetClientRect(&rect);

CSize pageSize(rect.right, rect.bottom);

Page 21: GDI Biblioteca GDI32 - profs.info.uaic.roiasimin/pw/CDC_2006.pdf · 1. dispozitive rastru = reprezentare imagine prin matrice de puncte (placi video, ... • Linii si curbe: linii

21

// Calculam marimea liniei

CSize lineSize(0, logFont.lfHeight);

// Ajustam barele de navigare

SetScrollSizes(MM_TEXT, docSize, pageSize, lineSize);