Sunteți pe pagina 1din 68

Capitolul 4.

Noiuni elementare de grafic

Programarea n
Windows

3/20/2017 4:21:17 AM
Filozofia GDI

Elementele grafice sunt manipulate, n principal, prin funcii din GDI32.DLL


Acestea 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
Unul dintre scopurile GDI:
- S permit manipularea elementelor grafice independent de dispozitiv.

3/20/2017 4:21:17 AM
Filozofia GDI

Dispozitivele grafice de ieire rastru i vectoriale.

Majoritatea limbajelor de programare cu posibiliti


grafice tradiionale se bazeaz pe vectori.

GDI este pentru limbajele tradiionale ceea ce este C


pentru alte limbaje de programare:
aa cum C este numit uneori limbaj de asamblare de
nivel nalt", GDI este o interfa de nivel nalt ctre
componentele hardware ale dispozitivelor grafice.

3/20/2017 4:21:17 AM
Filozofia GDI

Limbajul grafic trebuie s furnizeze programului posibilitatea de


determinare a caracteristicilor hardware ale dispozitivului.
Monitoarele video: s nu folosim aceste dispozitive orbete -
programul are posibilitatea foloseasc toate avantajele oferite de
componentele hardware.
GDI are limite: GDI este un sistem de afiare static, ce permite
numai animaii limitate, nu asigur un suport direct pentru afiarea
tridimensional sau pentru rotirea obiectelor.

3/20/2017 4:21:17 AM
Structura interfeei GDI

Structura general
Tipuri de funcii
Funcii care obin (creeaz) i elibereaz (distrug) un DC
Funcii care obin informaii despre contextul de dispozitiv
Funcii care deseneaz ceva
Funcii care stabilesc sau obin atribute ale DC
Funcii care lucreaz cu obiecte GDI

3/20/2017 4:21:17 AM
Primitive GDI

Linii i curbe
Suprafee pline
Imagini bitmap
Text

3/20/2017 4:21:17 AM
Alte aspecte

Moduri de mapare i transformri


Metafiiere (metafiles) - colecie de comenzi GDI
Regiuni - suprafa complex de orice form
Ci (paths) - colecie de linii drepte i curbe
Clipping limitarea desenrii la o anumit seciune
Palete
Tiprire - totul aplicat i operaiilor de tiprire.

3/20/2017 4:21:17 AM
CONTEXTUL DE DISPOZITIV

Atunci cnd vrem s desenm trebuie


Contextul de dispozitiv conine mai multe atribute

TextOut - specificm numai hdc, coordonatele de nceput,


textul i lungimea acestuia.
Atunci cnd dorim s modificm unul dintre atributele
contextului de dispozitiv, apelm o funcie specializat.
Urmtoarele apeluri ale funciei TextOut pentru acelai
context de dispozitiv vor folosi atributul modificat.

3/20/2017 4:21:17 AM
Obinerea unei variabile handle DC

WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
[alte linii de program]
EndPaint (hwnd, &ps);

n timpul prelucrrii altor mesaje:

hdc = GetDC (hwnd);


(alte linii de program]
ReleaseDC (hwnd, hdc);

Se aplic zonei client a ferestrei care are variabila hwnd.


3/20/2017 4:21:17 AM
Obinerea unei variabile handle DC
Context de dispozitiv care se aplic ntregii ferestre
hdc = GetWindowDC (hwnd);
[alte linii de program]
ReleaseDC (hwnd, hdc);

O funcie mai general pentru obinerea hdc este CreateDC:


hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData);
[alte linii de program]
DeleteDC (hdc);

Obinem hdc pentru tot spaiul de afiare:


hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
Scrierea n afara ferestrei proprii nu este n general recomandat
3/20/2017 4:21:17 AM
Obinerea unei variabile handle DC

Variabila handle a contextului de informaii (information context"):


hdclnfo = CreatelC ("DISPLAY", NULL, NULL, NULL);
[alte linii de program]
DeleteDC (hdclnfo);
Nu putem executa operaii de scriere
Cnd lucrm cu imagini bitmap:
hdcMem = CreateCompatibleDC (hdc);
[alte linii de program]
DeleteDC (hdcMem)
Crem un metafiier - context de dispozitiv pentru metafiiere:
hdcMeta = CreateMetaFile(pszFilename);
[alte linii de program]
hmf = CloseMetaFile (hdcMeta);
3/20/2017 4:21:17 AM
Obinerea informaiilor despre DC

Un context de dispozitiv se refer la un dispozitiv fizic de ieire, un


monitor video sau o imprimant: GetDeviceCaps:
iValue = GetDeviceCaps (hdc, iIndex) ;

iIndex - unul dintre cei 28 de identificatori definii n fiierele antet din


Windows: HORZRES funcia GetDeviceCaps returneaz limea
dispozitivului n pixeli; VERTRES - nlimea dispozitivului n pixeli.

Folosim funcia GetDeviceCaps i ca s obinem informaii despre


posibilitile dispozitivului.

3/20/2017 4:21:17 AM
Programul DEVCAPS1
#include <windows.h>
#include <string.h>
#define NUMLINES ((int) (sizeof devcaps / sizeof devcaps [0]))
struct {
int iIndex ;
char *szLabel ;
char *szDesc ; }
devcaps [] = {
HORZSIZE, "HORZSIZE", "Width in millimeters:",
VERTSIZE, "VERTSIZE", "Height in millimeters:",
HORZRES, "HORZRES", "Width in pixels:",
VERTRES, "VERTRES", "Height in raster lines:",

COLORRES, "COLORRES", "Actual color resolution: } ;

3/20/2017 4:21:17 AM
Programul DEVCAPS1
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int
iCmdShow)
{
static char szAppName[] = "DevCaps1" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx (&wndclass) ;

3/20/2017 4:21:17 AM
Programul DEVCAPS1

hwnd = CreateWindow (szAppName, "Device Capabilities",


WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, iCmdShow) ;


UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
} 3/20/2017 4:21:17 AM
Programul DEVCAPS1
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam,
LPARAM lParam)
{
static int cxChar, cxCaps, cyChar ;
char szBuffer[10] ;
HDC hdc ;
int i;
PAINTSTRUCT ps ;
TEXTMETRIC tm ;
switch (iMsg)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
3/20/2017 4:21:17 AM
Programul DEVCAPS1
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
for (i = 0 ; i < NUMLINES ; i++)
{
TextOut (hdc, cxChar, cyChar * (1 + i), devcaps[i].szLabel, strlen (devcaps[i].szLabel)) ;
TextOut(hdc,cxChar+22*cxCaps, cyChar*(1+i),devcaps[i].szDesc,strlen (devcaps[i].szDesc)) ;
SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;
TextOut(hdc,cxChar+22*cxCaps+40*cxChar,cyChar*(1+i),szBuffer,wsprintf(szBuffer,"%5d",
GetDeviceCaps (hdc, devcaps[i].iIndex))) ;
SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
3/20/2017 4:21:17 AM
Programul DEVCAPS1

3/20/2017 4:21:17 AM
Dimensiunea dispozitivului

GetDeviceCaps - dimensiunea ecranului i proporia dimensiunilor unui


pixel - pot fi folosite pentru scalarea imaginilor

HORZSIZE i VERTSIZE - limea i nlimea n milimetri


HORZRES i VERTRES - limea i nlimea n pixeli
ASPECTX, ASPECTY i ASPECTXY - dimensiunile aproximative
ale unui pixel, rotunjite la cel mai apropiat numr ntreg.
LOGPIXELSX i LOGPIXELSY - numrul pixeli pe un inchi logic"

3/20/2017 4:21:17 AM
Obinerea informaiilor despre culori

GetDeviceCaps - modul de organizare a memoriei i numrul de culori.


iPlanes = GetDeviceCaps (hdc, PLANES);
iBitsPixel = GetDeviceCaps (hdc, BITSPIXEL)
Numrul de culori care pot fi redate de o plac video:
iColors = GetDeviceCaps (hdc, NUMCOLORS);
Funcia GetDeviceCaps apelat cu parametrul NUMCOLORS
Tipul de date folosit pentru culori se numete COLORREF:

RGB (255, 0, 255) - 0x00FF00FF magenta. 0 - negrul, 255 - albul.


GetRValue, GetGValue i GetBValue extrag valorile pentru culorile
primare, sub forma unor octei fr semn, din valoarea RGB a culorii.
3/20/2017 4:21:17 AM
Atributele contextului de dispozitiv
Atributul contextului de Valoare Funcia folosit pentru Funcia folosit pentru
dispozitiv prestabilit modificarea atributului obinerea atributului
Mod de MM_TEXT SetMapMode GetMapMode
mapare
Originea ferestrei (0,0) SetWindowOrgEx GetWindowOrgEx
OffsetWindowOrgEx
Originea vizorului (0,0) SetViewportOrgEx GetViewportOrgEx
OffsetViewportOrgEx
Extensia ferestrei (1,1) SetWindowExtEx GetWindowExtEx
SetMapMode
ScaleWindowExtEx
Extensia vizorului (1,1) SetViewportExtEx GetViewportExExt
SetMapMode
ScaleViewportExtEx
Peni (pen) BLACK_PEN SelectObject SelectObject
Pensul (brush) WHITE_BRUSH SelectObject SelectObject
Font SYSTEM_FONT SelectObject SelectObject
Bitmap Nu exist SelectObject SelectObject
Poziia curent a (0,0) MoveToEx GetCurrentPositionEx
peniei LineTo PolylineTo
PolyBezierTo
3/20/2017 4:21:17 AM
Atributele contextului de dispozitiv
Modul de afiare a OPAQUE SetBkMode GetBkMode
fondului
Culoarea Alb SetBkColor GetBkColor
fondului
Culoarea textului Negru SetTextColor GetTextColor
Mod de R2COPYPEN SetROPZ GetROP2
desenare
Mod de BLACKONWHITE SetStretchBltMode GetStretchBltMode
ntindere
Mod de umplere a ALTERNATE SetPolyFillMode GetPolyFillMode
prigoanelor
Spaiu ntre 0 SetTextCharacterExtra GetTextCharacterExtra
caractere
Originea pensulei (0,0) n coordonate SetBrushOrgEx GetBrushOrgEx
ecran
Regiune de decupare Nu exist SelectObject SelectClipRgn GetClipBox

3/20/2017 4:21:17 AM
Salvarea contextului de dispozitiv
Windows creeaz un nou context de dispozitiv cu valori prestabilite:
case WM_Paint:
hdc = BeginPaint (hwnd, &ps);
[iniializeaz atributele contextului de dispozitiv]
[deseneaz zona client a ferestrei]
EndPaint (hwnd, &ps);
return 0;
Salvm modificrile fcute asupra DC la distrugerea acestuia, astfel nct valorile salvate
s redevin active la apelarea funciilor GetDC sau BeginPaint :
wndclass.style = CS_HREDRAW | CS_VREDRAH | CS_OWNDC;
Cnd folosim stilul de fereastr CS_OWNDC, trebuie s iniializm DC o singur dat:
case WM_CREATE:
hdc = GetDC (hwnd);
[iniiallzeaz atributele contextului de dispozitiv]
ReleaseDC (hwnd, hdc);
Atributele sunt valide pn cnd le modificm n mod explicit.

3/20/2017 4:21:17 AM
Salvarea contextului de dispozitiv

Dezavantaj: Windows consum aproximativ 800 de octei pentru salvarea


contextului de dispozitiv al fiecrei ferestre create cu acest stil. Chiar dac
folosim stilul de fereastr CS_OWNDC, trebuie s distrugem contextul de
dispozitiv nainte de ieirea din procedura de fereastr.
De asemenea, putem folosi i stilul CS_CLASSDC:
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
Acest stil face ca fiecare clas de fereastr s aib un context de dispozitiv,
folosit n comun de toate ferestrele create pe baza clasei respective.
Dac dorim s modificm unele dintre atributele contextului de dispozitiv, s
desenm ceva folosind noile atribute i apoi s revenim la vechile valori, salvm
starea curent a DC prin urmtorul apel: iSavedID = SaveDC (hdc); Modificm
atributele dorite. Atunci cnd vrem s revenim la starea contextului de dispozitiv
dinaintea apelrii funciei SaveDC, folosim funcia RestoreDC: RestoreDC (hdc,
iSavedID);
3/20/2017 4:21:17 AM
Desenarea liniilor

Teoretic, SetPixel (i, n unele situaii, GetPixel)


Manipularea operaiilor de desenare la nivelul driverului dispozitivului.
Plcile specializate conin coprocesoare tot mai performante, care
permit chiar componentelor video hardware s fac desenarea figurilor.
Windows deseneaz drepte, elipse i curbe Bezier.
apte funcii pentru desenarea liniilor sunt
LineTo (linii drepte),
Polyline i PolylineTo (o serie de linii drepte conectate),
PolyPolyline (mai multe linii poligonale),
Arc (linii eliptice),
PolyBezier i PolyBezierTo.
Trei funcii pentru desenarea liniilor: ArcTo, AngleArc i PolyDraw.

3/20/2017 4:21:17 AM
Desenarea liniilor

Aspectul liniilor desenate cu aceste funcii poate fi influenat de cinci


atribute ale contextului de dispozitiv:
poziia curent a peniei (numai pentru funciile LineTo,
PolylineTo i PolyBezierTo),
penia selectat,
modul de afiare a fondului,
culoarea fondului (pentru modul OPAQUE de afiare a fondului)
modul de desenare.

Tot aici i funciile


Rectangle, Ellipse, RoundRect, Chord i Pie, folosite i pentru
desenarea suprafeelor pline.

3/20/2017 4:21:17 AM
Desenarea liniilor

LineTo nu are nevoie de dimensiunile complete


ale obiectului ce urmeaz s fie desenat.
Deseneaz o linie de la poziia curent a
peniei, definit n DC pan la punctul specificat
la apelarea funciei (exclusiv acest punct).
Apelul de mai jos deseneaz o linie pn n punctul
(xEnd, yEnd), exclusiv acest punct.
Dup apelul funciei LineTo, poziia curent devine
(xEnd, yEnd).
LineTo(hdc, xEnd, yEnd);
3/20/2017 4:21:17 AM
Desenarea liniilor
Dac dorii s desenai o linie din punctul (xStart, yStart) pan n
punctul (xEnd, yEnd) trebuie s apelai mai nti funcia MoveToEx
pentru a s stabili ca poziie curent punctul (xStart, yStart):

MoveToEx(hdc, xStart, yStart, &pt);


unde pt este o structur de tip POINT, definit astfel:
typedef struct tag POINT
{
LONG x ;
LONG y ;
}
POINT ;

3/20/2017 4:21:17 AM
Desenm o gril

n zona client desenm o gril ncepnd din colul


din stnga-sus:
GetClientRect (hwnd, &rect);
for (x = 0 ; x < rect.right ; x +=100)
{
MoveToEx (hdc, x, 0, NULL) ;
LineTo (hdc, x, rect.bottom) ;
}
for (y = 0 ; y < rect.bottom ; y +=100)
{
MoveToEx (hdc, 0, y, NULL) ;
LineTo (hdc, rect.right, y) ;
}
3/20/2017 4:21:17 AM
Polyline i PolylineTo
Poziia curent devine util atunci cnd trebuie s desenm o serie de linii
conectate. De exemplu, s presupunem c definim o matrice de cinci
puncte (10 valori) care marcheaz un dreptunghi:
POINT pt [5] = { 100, 100, 200, 100, 200, 200, 100, 200, 100, 100 };
Remarcai faptul c ultimul punct este acelai cu primul.
Acum trebuie doar s folosii funcia MoveToEx pentru primul punct i
apoi funcia LineTo pentru punctele urmtoare:

MoveToEx (hdc, pt[0].x, pt[0].y, NULL);


for (i = 1; i < 5; i++) LineTo (hdc, pt[i].x, pt[i].y);

Polyline (hdc, pt, 5) realizeaz acelai lucru, dar nu schimb poziia curent
PolylineTo este puin diferit. Aceasta folosete ca punct de plecare
poziia curent i stabilete ca poziie curent sfritul ultimei linii desenate:
MoveToEx (hdc, pt[0].x, pt[0].y, NULL);
PolylineTo (hdc, pt + 1,4);

3/20/2017 4:21:17 AM
SINEWAVE
#include <windows.h> wndclass.hbrBackground = (HBRUSH) GetStockObject
#include <math.h> (WHITE_BRUSH) ;
#define NUM 1000 wndclass.lpszMenuName = NULL ;
#define TWOPI (2 * 3.14159) wndclass.lpszClassName = szAppName ;
LRESULT CALLBACK WndProc (HWND, UINT, wndclass.hIconSm = LoadIcon (NULL,
WPARAM, LPARAM) ; IDI_APPLICATION) ;
int WINAPI WinMain (HINSTANCE hInstance, RegisterClassEx (&wndclass) ;
HINSTANCE hPrevInstance,
hwnd = CreateWindow (szAppName, "Sine Wave Using
PSTR szCmdLine, int iCmdShow)
Polyline",
{
WS_OVERLAPPEDWINDOW,
static char szAppName[] = "SineWave" ;
CW_USEDEFAULT, CW_USEDEFAULT,
HWND hwnd ;
CW_USEDEFAULT, CW_USEDEFAULT,
MSG msg ;
NULL, NULL, hInstance, NULL) ;
WNDCLASSEX wndclass ;
ShowWindow (hwnd, iCmdShow) ;
wndclass.cbSize = sizeof (wndclass) ;
UpdateWindow (hwnd) ;
wndclass.style = CS_HREDRAW |
CS_VREDRAW ; while (GetMessage (&msg, NULL, 0, 0))
wndclass.lpfnWndProc = WndProc ; {
wndclass.cbClsExtra = 0 ; TranslateMessage (&msg) ;
wndclass.cbWndExtra = 0 ; DispatchMessage (&msg) ;
wndclass.hInstance = hInstance ; }
wndclass.hIcon = LoadIcon (NULL, return msg.wParam ;
IDI_APPLICATION) ; }
wndclass.hCursor = 3/20/2017
LoadCursor4:21:17
(NULL, AM
IDC_ARROW) ;
SINEWAVE
LRESULT CALLBACK WndProc (HWND case WM_PAINT:
hwnd, UINT iMsg, WPARAM wParam, hdc = BeginPaint (hwnd, &ps) ;
LPARAM lParam) MoveToEx (hdc, 0, cyClient / 2, NULL) ;
{ LineTo (hdc, cxClient, cyClient / 2) ;
static int cxClient, cyClient ; for (i = 0 ; i < NUM ; i++)
HDC hdc ; {
int i; pt[i].x = i * cxClient / NUM ;
pt[i].y = (int) (cyClient/2*(1-sin(TWOPI*i/NUM))) ;
PAINTSTRUCT ps ;
}
POINT pt [NUM] ; Polyline (hdc, pt, NUM) ;
switch (iMsg) return 0 ;
{ case WM_DESTROY:
case WM_SIZE: PostQuitMessage (0) ;
cxClient = LOWORD (lParam) ; return 0 ;
cyClient = HIWORD (lParam) ; }
return DefWindowProc(hwnd, iMsg,wParam, lParam) ;
return 0 ;
}

3/20/2017 4:21:17 AM
SINEWAVE

3/20/2017 4:21:17 AM
Dreptunghiuri de ncadrare
Funcia Arc - funcie care deseneaz o curb eliptic. Nu prea are sens
dac nu discutm mai nti despre funcia Ellipse, nu are sens fr o xLeft xRight
xTop
discuie despre funcia Rectangle. Si dac discutm despre funciile
Rectangle i Ellipse, putem la fel de bine s discutm i despre funciile
RoundRect, Chord i Pie.

Funciile Rectangle, Ellipse, RoundRect, Chord i Pie nu sunt tocmai nite


funcii de desenare a liniilor. Desigur, ele deseneaz i linii, dar i xBotto
coloreaz zona nchis, cu pensula curent de colorare a suprafeelor. m

n sens strict, aparin unei alte seciuni Desenarea suprafeelor pline".


Asemntoare - sunt construite pe baza unui dreptunghi de ncadrare"
Definim o caset care ncadreaz obiectul - dreptunghiul de ncadrare
i Windows deseneaz obiectul n acest dreptunghi.

Cea mai simpl dintre aceste funcii deseneaz un dreptunghi:


Rectangle (hdc, xLeft, yTop, xRight, yBottom) ;

Problema pixelului suplimentar:


Rectangle (hdc, 1,3/20/2017
1, 5, 4) ; 4:21:17 AM
Ellipse, RoundRect
Ellipse (hdc, xLeft, yTop, xRight, yBottom) ; RoundRect(hdc,xLeft,yTop,xRight,yBottom,xCornerEllipse,
yCornerEllipse) ;

3/20/2017 4:21:17 AM
Funciile Arc, Chord i Pie

Arc (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
Pie (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;

3/20/2017 4:21:17 AM
LINEDEMO

LRESULT CALLBACK WndProc (HWND case WM_PAINT:


hwnd, UINT iMsg, WPARAM wParam, hdc = BeginPaint (hwnd, &ps) ;
LPARAM lParam)
Rectangle(hdc,cxClient/8,cyClient/8,7*cxClient/8,7*cyClient/8);
{
static int cxClient, cyClient ; MoveToEx(hdc, 0, 0, NULL) ;
HDC hdc ; LineTo(hdc, cxClient, cyClient) ;
PAINTSTRUCT ps ; MoveToEx (hdc, 0, cyClient, NULL) ;
switch (iMsg) LineTo(hdc, cxClient, 0) ;
{
Ellipse(hdc,cxClient/8,cyClient/8,7*cxClient/8,7*cyClient/8);
case WM_SIZE:
cxClient = LOWORD (lParam) ; RoundRect
cyClient = HIWORD (lParam) ; (hdc,cxClient/4,cyClient/4,3*cxClient/4,3*cyClient/4,cxClient/4,cyClient/4);
return 0 ; EndPaint (hwnd, &ps) ;
return 0 ;

3/20/2017 4:21:17 AM
LINEDEMO

3/20/2017 4:21:17 AM
Curbe Bezier
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:

x(t) = (1-t)3x0 + 3t(1-t)2x1 + 3t2(1-t)x2 + t3x3


pt este o matrice de structuri POINT. PolyBezier primele patru
y(t) = (1-t)3y0 + 3t(1-t)2y1 + 3t2(1-t)y2 + t3y3
puncte specific: nceput, primul punct de control, al doilea punct de
control i punctul final Urmtoarele curbe Bezier au nevoie doar de
trei puncte, deoarece punctul de nceput al urmtoarei curbe Bezier
PolyBezier (hdc, pt, iCount) ; este punctul de sfrit al primei curbe, i aa mai departe. Parametrul
iCount reprezint numrul de puncte din matrice, adic unu plus de
sau instruciunea: trei ori numrul curbelor pe care vrei s le desenai.
PolyBezierTo (hdc, pt, iCount) 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
3/20/2017 4:21:17 AM
este punctul final al ultimei curbe desenate.
Programul Bezier
void DrawBezier (HDC hdc, POINT apt[]) case WM_MOUSEMOVE:
{ if (wParam & MK_LBUTTON || wParam & MK_RBUTTON)
PolyBezier (hdc, apt, 4) ;
{
MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ;
LineTo (hdc, apt[1].x, apt[1].y) ; hdc = GetDC (hwnd) ;
MoveToEx (hdc, apt[2].x, apt[2].y, NULL) ; SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
LineTo (hdc, apt[3].x, apt[3].y) ; DrawBezier (hdc, apt) ;
} if (wParam & MK_LBUTTON)
{
{ apt[1].x = LOWORD (lParam) ;
static POINT apt[4] ;
HDC hdc ; apt[1].y = HIWORD (lParam) ; }
int cxClient, cyClient ; if (wParam & MK_RBUTTON)
PAINTSTRUCT ps ; { apt[2].x = LOWORD (lParam) ;
apt[2].y = HIWORD (lParam) ; }
case WM_PAINT:
SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
InvalidateRect (hwnd, NULL, TRUE) ;
DrawBezier (hdc, apt) ;
hdc = BeginPaint (hwnd, &ps) ;
ReleaseDC (hwnd, hdc) ;
DrawBezier (hdc, apt) ;
}
EndPaint (hwnd, &ps) ;
return 0 ;
return 0 ;

3/20/2017 4:21:17 AM
Caracteristicile funciilor Bezier

1. Putei s manipulai curba pn ajunge la o form apropiat de cea


dorit. CB sunt foarte uor de controlat.
2. CB sunt ntotdeauna ancorate n cele dou puncte finale.
3. CB sunt ntotdeauna limitate de un patrulater (numit carcas
convex") format prin unirea punctelor finale i a punctelor de
control (nu au puncte de singularitate, din care curba se ntinde la
infinit).
4. Curba este ntotdeauna tangent la linia trasat de la primul punct
final la primul punct de control i are ntotdeauna aceeai direcie
cu aceast linie. De asemenea, curba este ntotdeauna tangent la
linia trasat de la al doilea punct final la al doilea punct de control i
are ntotdeauna aceeai direcie cu aceast linie.
5. CB sunt satisfctoare i din punct de vedere estetic.
3/20/2017 4:21:17 AM
Folosirea penielor de stoc

Penia determin culoarea, limea i tipul de linie


Windows furnizeaz trei penie de stoc: BLACK_PEN,
WHITE_PEN i NULL_PEN. Pot fi create penie proprii
tipul de date HPEN reprezint o variabil handle a unei
penie HPEN hPen;
hPen = GetStockObject (WHITE_PEN);
SelectObject (hdc, hPen);
SelectObject (hdc, GetStockObject (WHITE_PEN));
Funcia SelectObject returneaz variabila handle a peniei
selectate anterior n contextul de dispozitiv
3/20/2017 4:21:17 AM
Crearea, selectarea i tergerea penielor

Procedura general: creai mai nti o peni logic" care este doar o
descriere a unei penie, folosind funciile CreatePen sau
CreatePenIndirect. Aceste funcii returneaz o variabil handle a
peniei logice. Selectai penia n contextul de dispozitiv apelnd
funcia SelectObject.
Dup ce tergei contextul de dispozitiv putei s tergei penia logic
pe care ai creat-o apelnd funcia DeleteObject.
Penia - unul dintre cele ase obiecte GDI pe care putem s le crem
Celelalte: pensulele, imaginile bitmap, regiunile, fonturile i paletele.
Exceptnd paletele, toate celelalte obiecte pot fi selectate n contextul
de dispozitiv folosind funcia SelectObject.

3/20/2017 4:21:17 AM
Reguli pentru folosirea obiectelor GDI:

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.

3/20/2017 4:21:17 AM
Sintaxa funciei CreatePen:

hPen = CreatePen (iPenStyle, iWidth, rgbColor);


stilul de linie:

Pentru stilurile PS_SOLID,


PS_NULL i PS_INSIDEFRAME,
parametrul iWidth grosimea liniei

3/20/2017 4:21:17 AM
Exemplu
Crearea, selectarea i tergerea penielor. Programul folosete trei penie: una neagr cu
grosimea de un pixel, una roie cu grosimea de trei pixeli i una neagr cu linie
punctat.
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) ;
3/20/2017 4:21:17 AM
Umplerea golurilor
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 - Windows umple
spaiile cu culoarea fondului, care n mod prestabilit este alb.
Putei s schimbai culoarea fondului pentru completarea spaiilor goale dintre
linii, prin apelarea funciei SetBkColor:
SetBkColor (hdc, rgbColor) ;
Putei s obinei culoarea definit 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.
3/20/2017 4:21:17 AM
Moduri de desenare

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

Desenarea unei linii implic 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.
3/20/2017 4:21:17 AM
16 moduri de desenare ROP2
Peni (P): 1 1 0 0 Operaia Mod de desenare
Destinaie (D): 1 0 1 0 boolean
SetROP2(hdc, iDrawMode);
Rezultate: 0 0 0 0 0 R2_BLACK

0 0 0 1 ~(P | D) R2_NOTMERGEPEN
0 0 1 0 ~P & D R2_MASKNOTPEN
0 0 1 1 ~P R2_NOTCOPYPEN
0 1 0 0 P & ~D R2_MASKPENNOT
0 1 0 1 ~D R2_NOT
0 1 1 0 P^D R2_XORPEN
0 1 1 1 ~(P & D) R2_NOTMASKPEN
1 0 0 0 P&D R2_MASKPEN
1 0 0 1 ~(P ^ D) R2_NOTXORPEN
1 0 1 0 D R2_NOP
1 0 1 1 ~P | D R2_MERGENOTPEN
1 1 0 0 P 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
3/20/2017 4:21:17 AM
Desenarea suprafeelor pline
apte funcii Windows pentru desenarea figurilor
Funcie Figura

Rectangle Dreptunghi cu coluri drepte


Ellipse Elips
RoundRect Dreptunghi cu coluri rotunjite
Chord Arc pe circumferina unei elipse, avnd capetele unite printr-o coard
Pie Suprafa de forma unei felii de plcint, reprezentnd un segment de
elips.
Polygon Figur geometric avnd mai multe laturi
PolyPolygon Mai multe figuri geometrice cu mai multe laturi

Conturul figurilor - penia curent. Atributele stabilite pentru modul de desenare a fondului,
culoarea fondului i modul de desenare.
Figurile sunt umplute folosind pensula selectat n contextul de dispozitiv. n mod prestabilit,
aceasta este pensula de stoc WHITE_BRUSH.
Windows definete ase pensule de stoc:
WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH, DKGRAY_BRUSH,
BLACK_BRUSH 3/20/2017
i NULL_BRUSH
4:21:17 AM(sau HOLLOW_BRUSH).
Modul de umplere a poligoanelor

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.
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) ;
3/20/2017 4:21:17 AM
ALTERNATE i WINDING

3/20/2017 4:21:17 AM
Umplerea suprafeelor interioare
Interiorul Rectangle, RoundRect, Ellipse, Chord, Pie, Polygon i PollyPolygon este umplut
cu pensula - numit model" (pattern") - selectat n contextul de dispozitiv. O
pensul este o imagine bitmap 8x8 repetat pe vertical i pe orizontal, pentru
umplerea unei suprafee.
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 SelectObject.
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.
3/20/2017 4:21:17 AM
Pensule haurate"

Putei s creai i o pensul haurat" cu linii orizontale, verticale sau


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

3/20/2017 4:21:17 AM
Alte
Pensule proprii, bazate pe o imagine bitmap
hBrush = CreatePatternBrush (hBitmap) ;
Funcia 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

3/20/2017 4:21:17 AM
Modurile de mapare
Majoritatea funciilor GDI primesc coordonate sau dimensiuni ca parametri
n toate funciile GDI, coordonatele sunt furnizate n uniti logice". Windows transform
unitile logice" n uniti de dispozitiv", adic n pixeli.
Transformarea 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.
Windows definete opt moduri de mapare:
Mod de mapare Uniti logice Creterea valorilor
axaX axaY
MM_TEXT Pixel Spre dreapta n jos
MM_LOMETRIC 0,1 mm Spre dreapta n sus
MM_HIMETRIC 0,01mm Spre dreapta n sus
MM_LOENGLISH 0,01 inci Spre dreapta n sus
MM_HIENGLISH 0,001 inci Spre dreapta nsus
MM_TWIPS 1/1440 inci Spre dreapta n sus
MM_ISOTROPIC Arbitrar (x = y) Selectabil Selectabil
MM_ANISOTROPIC Arbitrar (x != y) Selectabil Selectabil
3/20/2017 4:21:17 AM
Exemple

Putei s selectai modul de mapare folosind funcia SetMapMode:


SetMapMode (hdc, iMapMode) ;
Putei s obinei modul de mapare curent folosind funcia GetMapMode:
iMapMode = GetMapMode (hdc) ;
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:
SetMapMode (hdc, HM_LOENGLISH) ;
Acum apelul de mai sus al funciei TextOut trebuie s arate astfel:
TextOut (hdc, 50, -100, szBuffer, iLength) ;
3/20/2017 4:21:17 AM
Coordonate de dispozitiv i
coordonate logice

Windows va folosi 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 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.
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 cnd4:21:17
3/20/2017 afiaiAM
textul pe baza acestor dimensiuni.
Sistemele de coordonate ale
dispozitivului

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 i n urmtoarele funcii Windows: CreateWindow i
MoveWindow, GetMessagePos, GetCursorPos, SetCursorPos, GetWindowRect,
WindowFromPoint i SetBrushOrgEx. Acestea sunt funcii care fie nu au o fereastr
asociat, fie trebuie s mute (sau s gseasc) o fereastr pe baza unui punct de pe
ecran.
Coordonatele de fereastr" se refer la ntreaga fereastr, inclusiv bara de titlu,
meniu, barele de derulare i chenarul ferestrei. Pentru o fereastr, punctul (0, 0) este
colul din stnga-sus al chenarului de redimensionare.
Al treilea sistem de coordonate de dispozitiv 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.3/20/2017 4:21:17 AM
Vizorul i fereastra
Precizare: se spune c modul de mapare definete maparea coordonatelor de
fereastr" (window) - coordonate logice - la coordonatele vizorului (viewport) -
coordonate de dispozitiv.
Pentru vizor se folosesc coordonatele de dispozitiv (pixeli). De cele mai multe ori,
vizorul coincide cu zona client a ferestrei, dar poate s nsemne i coordonatele
ntregii ferestre sau coordonatele ntregului ecran, dac ai obinut contextul de
dispozitiv prin apelarea funciilor GetWindowDC sau CreateDC.
Pentru fereastr se utilizeaz coordonatele logice, care pot fi exprimate n pixeli,
milimetri, inci sau orice alt unitate de msur dorii. Coordonatele logice ale
ferestrei sunt specificate la apelarea funciilor GDI.
Pentru toate modurile de mapare, Windows transform coordonatele ferestrei
(coordonate logice) n coordonate ale vizorului (coordonate de dispozitiv) folosind
dou formule:
unde (xWindow, yWindow) este
punctul n coordonate logice
care trebuie translatat iar
(xViewport, yViewport) este
punctul n coordonate de
dispozitiv.
3/20/2017 4:21:17 AM
Originile i extensiile

Formulele de mai sus folosesc dou puncte corespunztoare originii ferestrei i


a vizorului: (xWinOrg, yWinOrg) reprezint originea ferestrei n coordonate
logice, iar (xViewOrg, yViewOrg) reprezint originea vizorului n coordonate de
dispozitiv. n contextul de dispozitiv prestabilit, aceste puncte au valoarea (0,
0), dar pot fi modificate. Formulele de mai sus implic faptul c punctul
(xWinOrg, yWinOrg) este ntotdeauna mapat la punctul (xViewOrg, yViewOrg).
De asemenea, formulele de mai sus folosesc dou puncte, pentru specificarea
extensiilor" ferestrei i vizorului: (xWinExt, yWinExt) reprezint extensia,
ferestrei n coordonate logice, iar (xViewExt, yViewExt) reprezint extensia
vizorului n coordonate de dispozitiv. n majoritatea modurilor de mapare,
extensiile sunt implicate de modul de mapare i nu pot fi modificate. Extensia n
sine nu are nici o semnificaie, dar raportul ntre extensia vizorului i extensia
ferestrei reprezint un factor de scalare folosit pentru convertirea unitilor
logice n uniti de dispozitiv. Extensiile pot avea valori negative: aceasta
nseamn c nu este obligatoriu ca valorile pe axa x s creasc spre dreapta i
valorile pe axa y s creasc n jos.

3/20/2017 4:21:17 AM
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: (0, 0) Poate fi modificat
Extensia ferestrei: (1, 1) Nu poate fi modificat
Extensia vizorului: (1, 1) 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 .
3/20/2017 4:21:17 AM
Modificarea originii vizorului i a
ferestrei

Funciile SetViewportOrgEx i SetWindowOrgEx - 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.
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).
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.
3/20/2017 4:21:17 AM
Modurile de mapare metrice"

Windows include dou moduri de mapare n care coordonatele logice sunt


exprimate n uniti fizice, respectiv cinci moduri de mapare metrice" 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):
Mod de mapare Uniti logice Inci Milimetri
MM_LOENGLISH 0,01 in. 0,001 0,254
MM_LOMETRIC 0,1 mm 0,00394 0,1
MM_HIENGLISH 0,001 in. 0,001 0,0254
MM_TWIPS* 1/1440 in. 0,000694 0,0176
MM_HIMETRIC 0,01 mm 0,000394 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, 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 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,
3/20/2017 4:21:17MM_TWIPS
AM i MM_HIMETRIC.
Modurile de mapare metrice"
Originile i extensiile prestabilite sunt urmtoarele:
Originea ferestrei: (0,0) Poate fi modificat
Originea vizorului: (0,0) Poate fi modificat
Extensia ferestrei: (?, ?) Nu poate fi modificat
Extensia vizorului: (?, ?) Nu poate fi modificjat
Extensiile ferestrei i ale vizorului depind de modul de mapare i de raportul
de afiare a dispozitivului. Extensiile nu sunt importante ca atare, avnd o
semnificaie numai exprimate ca rapoarte. Iat care sunt formulele de
transformare a coordonatelor:

3/20/2017 4:21:17 AM
Moduri de mapare proprii

MM_ISOTROPIC i MM_ANISOTROPIC - moduri de mapare care permit s modificm


extensiile ferestrei i ale vizorului - factorul de scalare pe care Windows l folosete pentru
convertirea coordonatelor logice i a coordonatelor de dispozitiv.
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. Un program Windows poate s manipuleze redimensionarea
unei imagini prin ajustarea extensiilor ferestrei i ale vizorului.
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.

3/20/2017 4:21:17 AM
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. 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.
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, MM_ISOTROPIC) ;
SetWindowExtEx (hdc, 32767, 32767, NULL) ;
SetViewportExtEx (hdc, cxClient,
3/20/2017 4:21:17 AM-cyClient, NULL) ;
SetViewportOrgEx (hdc, 0, cyClient, NULL) ;
Modul de mapare MM_ANISOTROPIC

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
3/20/2017 (hdc,
4:21:170,
AMcyClient, NULL) ;