PW 66-80.docx

22
66. Modurile de mapare. Coordonate de dispozitiv şi coordonate logice. Sistemele de coordonate ale dispozitivului. Vizorul şi fereastra. Folosirea modului de mapare MM_TEXT. Modurile de mapare Un atribut al contextului de dispozitiv care afectează aproape toate operaţiile de desenare din zona client este „modul de mapare" („mapping mode"). Alte patru atribute ale contextului de dispozitiv - originea ferestrei, originea vizorului (viewport), extensia ferestrei şi extensia vizorului - sunt strâns legate de modul de mapare. Majoritatea funcţiilor GDI primesc coordonate sau dimensiuni ca parametri. Iată, ca exemplu, funcţia TextOut: TextOut (hdc, x, y, szBuffer, iLength) ; Parametrii x şi y indică poziţia în care începe textul. Parametrul x reprezintă poziţia pe axa orizontală, iar parametrul y reprezintă poziţia pe axa verticală. Deseori, pentru indicarea acestui punct este folosită notaţia (x, y). În funcţia TextOut şi, de fapt, în toate funcţiile GDI, coordonatele sunt furnizate în „unităţi logice". Windows trebuie să transforme „unităţile logice" în „unităţi de dispozitiv", adică în pixeli. Această transformare este guvernată de modul de mapare, de originile ferestrei, ale vizorului şi de extensiile ferestrei şi ale vizorului. De asemenea, modul de mapare stabileşte şi orientarea axelor x şi y, adică determină sensul în care cresc valorile coordonatelor x şi y. Windows defineşte opt moduri de mapare. Acestea sunt prezentate în tabelul următor, folosind identificatorii definiţi în fişierele antet din Windows: Mod de mapare Unităţi logice Creşterea 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 mei 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 Puteţi să selectaţi modul de mapare folosind funcţia SetMapMode: SetMapMode (hdc, iMapHode) ; unde iMapMode este unul dintre cei opt identificatori definiţi pentru modurile de mapare. Puteţi să obţineţi modul de mapare curent folosind funcţia GefMapMode: iMapMode = GetMapMode (hdc) ; Modul de mapare prestabilit este MM_TEXT. În acest mod de mapare unităţile logice sunt aceleaşi cu unităţile fizice, ceea ce vă permite (sau, privind dintr-o altă perspectivă, vă forţează) să lucraţi în pixeli. Într-un apel al funcţiei TextOut care arată astfel: TextOut (hdc, 8, 16, szBuffer, iLength) ; textul începe la o distanţă de opt pixeli faţă de marginea din stânga a zonei client şi de 16 pixeli faţă de marginea de sus a acesteia.

Transcript of PW 66-80.docx

Page 1: PW 66-80.docx

66. Modurile de mapare. Coordonate de dispozitiv şi coordonate logice. Sistemele de coordonate ale dispozitivului. Vizorul şi fereastra. Folosirea modului de mapare MM_TEXT.

Modurile de mapareUn atribut al contextului de dispozitiv care afectează aproape toate operaţiile de desenare din

zona client este „modul de mapare" („mapping mode"). Alte patru atribute ale contextului de dispozitiv - originea ferestrei, originea vizorului (viewport), extensia ferestrei şi extensia vizorului - sunt strâns legate de modul de mapare.

Majoritatea funcţiilor GDI primesc coordonate sau dimensiuni ca parametri. Iată, ca exemplu, funcţia TextOut:

TextOut (hdc, x, y, szBuffer, iLength) ;Parametrii x şi y indică poziţia în care începe textul. Parametrul x reprezintă poziţia pe axa

orizontală, iar parametrul y reprezintă poziţia pe axa verticală. Deseori, pentru indicarea acestui punct este folosită notaţia (x, y).

În funcţia TextOut şi, de fapt, în toate funcţiile GDI, coordonatele sunt furnizate în „unităţi logice". Windows trebuie să transforme „unităţile logice" în „unităţi de dispozitiv", adică în pixeli. Această transformare este guvernată de modul de mapare, de originile ferestrei, ale vizorului şi de extensiile ferestrei şi ale vizorului. De asemenea, modul de mapare stabileşte şi orientarea axelor x şi y, adică determină sensul în care cresc valorile coordonatelor x şi y.

Windows defineşte opt moduri de mapare. Acestea sunt prezentate în tabelul următor, folosind identificatorii definiţi în fişierele antet din Windows:

Mod de mapare Unităţi logice Creşterea valorilor axax axayMM_TEXT Pixel Spre dreapta În josMM_LOMETRIC 0,1 mm Spre dreapta În susMM_HIMETRIC 0,01mm Spre dreapta În susMM_LOENGLISH 0,01 mei Spre dreapta În susMM_HIENGLISH 0,001 inci Spre dreapta ÎnsusMM_TWIPS 1/1440 inci Spre dreapta În susMM_ISOTROPIC Arbitrar (x = y) Selectabil SelectabilMM_ANISOTROPIC Arbitrar (x != y) Selectabil Selectabil

Puteţi să selectaţi modul de mapare folosind funcţia SetMapMode:SetMapMode (hdc, iMapHode) ;

unde iMapMode este unul dintre cei opt identificatori definiţi pentru modurile de mapare. Puteţi să obţineţi modul de mapare curent folosind funcţia GefMapMode:

iMapMode = GetMapMode (hdc) ;Modul de mapare prestabilit este MM_TEXT. În acest mod de mapare unităţile logice sunt aceleaşi

cu unităţile fizice, ceea ce vă permite (sau, privind dintr-o altă perspectivă, vă forţează) să lucraţi în pixeli. Într-un apel al funcţiei TextOut care arată astfel:

TextOut (hdc, 8, 16, szBuffer, iLength) ;textul începe la o distanţă de opt pixeli faţă de marginea din stânga a zonei client şi de 16 pixeli faţă de marginea de sus a acesteia.

Coordonate de dispozitiv şi coordonate logicemodul de mapare fiind un atribut al contextului de dispozitiv, are efect numai atunci când folosiţi

funcţii GDI care primesc o variabilă handle a contextului de dispozitiv ca parametru. GetSystemMetrics nu este o funcţie GDI, aşa că va returna în continuare dimensiunile în unităţi de dispozitiv, adică în pixeli. Deşi GetDeviceCaps este o funcţie GDI care primeşte ca parametru o variabilă handle a contextului de dispozitiv, Windows continuă să returneze unităţi de dispozitiv pentru identificatorii HORZRES şi VERTRES, deoarece unul dintre scopurile acestei funcţii este să furnizeze programului dimensiunea în pixeli a dispozitivului.

Totuşi, valorile din structura TEXTMETRIC pe care le obţineţi prin apelarea funcţiei GetTextMetrics sunt furnizate în unităţi logice. Dacă modul de mapare este MM_LOENGLISH în momentul apelării

Page 2: PW 66-80.docx

funcţiei, GetTextMetrics returnează lăţimea şi înălţimea caracterelor, în sutimi de inci. Atunci când apelaţi funcţia GetTextMetrics ca să obţineţi înălţimea şi lăţimea caracterelor, modul de mapare trebuie să fie acelaşi cu cel pe care îl veţi folosi atunci când afişaţi textul pe baza acestor dimensiuni

Sistemele de coordonate ale dispozitivuluiAtunci când folosim întregul ecran, spunem că lucrăm în „coordonate ecran". Colţul din stânga-sus

este punctul de coordonate (0, 0). Coordonatele ecran sunt folosite în mesajul WM_MOVE (pentru alte ferestre decât ferestrele descendent) şi în următoarele funcţii Windows: CreateWinriow şi MoveWindow (ambele pentru alte ferestre decât ferestrele descendent), GetMessagePos, GetCursorPos, SetCursorPos, GetWindowRect, WindowFromPoint şi SetBrushOrgEx.

Coordonatele de fereastră" se referă la întreaga fereastră a ecranului, inclusiv bara de titlu, meniu, barele de derulare şi chenarul ferestrei. Pentru o fereastră normală, punctul (0, 0) este colţul din stânga-sus al chenarului de redimensionare. Coordonatele de fereastră sunt folosite mai rar în Windows, dar dacă obţineţi un context de dispozitiv cu ajutorul funcţiei GetWindowDC, atunci coordonatele logice specificate la apelarea funcţiilor GDI vor fi mapate la coordonatele ferestrei.

Al treilea sistem de coordonate de dispozitiv -foloseşte „coordonatele zonei client". Punctul (0,0) este colţul din stânga-sus al zonei client. Dacă obţineţi un context de dispozitiv cu ajutorul funcţiei GetDC sau al funcţiei BeginPaint, atunci coordonatele logice specificate Ia apelarea funcţiilor GDI vor fi mapate la coordonatele zonei client.

Puteţi să transformaţi coordonatele zonei client în coordonatele ecranului şi invers folosind funcţiile ClientToScreen şi ScreenToClient. De asemenea, puteţi şă obţineţi poziţia şi dimensiunea întregii ferestre în coordonate ecran folosind funcţia GetWindowRect.

Vizorul şi fereastraModurile de mapare definite în Windows stabilesc modul în care sunt mapate coordonatele logice

specificate în funcţiile GDI la coordonatele de dispozitiv, pe baza faptului că sistemul de coordonate de dispozitiv folosit depinde de funcţia folosită pentru obţinerea contextului de dispozitiv. se spune că modul de mapare defineşte maparea coordonatelor „de fereastră" (window) -coordonate logice - la coordonatele vizorului (viewport) - coordonate de dispozitiv.

În alte limbaje pentru interfeţele grafice, termenul viewport se referă la o regiune de decupare (clipping region). Termenul window defineşte, în general, zona pe care o ocupă un program pe ecran. În timpul discuţiilor de faţă va trebui să renunţăm la vechile definiţii ale acestor termeni.

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ă aţi obţinut contextul de dispozitiv prin apelarea funcţiilor GetWindowDC sau CreateDC. Punctul de coordonate (0, 0) este colţul din stânga-sus al zonei client (sau al ferestrei, ori al ecranului). Valorile coordonatei x cresc către dreapta, iar valorile coordonatei y cresc în jos.

Pentru fereastră se utilizează coordonatele logice, care pot fi,exprimate în pixeli, milimetri, inci sau orice altă unitate de măsură doriţi. Coordonatele logice ale ferestrei sunt specificate la apelarea funcţiilor GDI.

Pentru toate modurile de mapare, Windows transformă coordonatele ferestrei (coordonate logice) în coordonate ale vizorului.

Windows poate să transforme şi coordonatele vizorului (coordonate de dispozitiv) în coordonate ale ferestrei (coordonate logice.

Windows include două funcţii care vă permit să convertiţi punctele de dispozitiv în puncte logice şi invers. Funcţia următoare converteşte punctele de dispozitiv în puncte logice:

DPtoLP (hdc, pPoints, iNumber) ;Variabila pPoints este o matrice de structuri POINT, iar iNumber este numărul de puncte ce

urmează să fie convertite. Veţi vedea că această funcţie este foarte utilă pentru convertirea dimensiunii zonei client obţinute prin apelarea funcţiei GetClientRect (care returnează valorile în unităţi de dispozitiv) în coordonate logice:

GetClientRect (hwnd, &rect);DPtoLP (hdc, (PPoint) &rect, 2);

Funcţia următoare converteşte punctele logice în puncte de dispozitiv:LPtoDP (hdc, pPoints, iNumber) ;

Folosirea modului de mapare MM_TEXT

Page 3: PW 66-80.docx

Pentru modul de mapare MM_TEXT, originile şi extensiile prestabilite sunt următoarele: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, aşa că nu este necesară nici o operaţie de scalare pentru transformarea coordonatelor logice în coordonate de dispozitiv.

Acest mod de mapare se numeşte „mapare de tip text", nu fiindcă este cea mai potrivită pentru text, ci datorită orientării axelor. În general, citim textul de la stânga spre dreapta şi de sus în jos, iar în modul de mapare MM_TEXT, valorile cresc în acelaşi sens:

Windows furnizează funcţiile SetViewportOrgEx şi SetWindowOrgEx pentru modificarea originii vizorului şi a ferestrei. Aceste funcţii au ca efect deplasarea axelor, astfel încât punctul de coordonate (0, 0) nu se mai referă la colţul din stânga-sus al ecranului. În general, veţi folosi ori funcţia SetViewportOrgEx, ori SetWindowOrgEx, dar nu pe amândouă.

De exemplu, să presupunem că zona client are lăţimea cxClient şi înălţimea cyClient. Dacă vreţi ca punctul logic de coordonate (0, 0) să se afle în centrul zonei client, puteţi să apelaţi funcţia următoare:

SetViewportOrgEx (hdc, cxClient/2, cyClient/2, NULL) ;Argumentele funcţiei SetViewportEx sunt exprimate întotdeauna în unităţi de dispozitiv. Punctul

logic (0, 0) va fi acum mapat la punctul .de dispozitiv (cxClient/2, cyClient/2). Din acest moment folosiţi zona client ca şi cum ar avea următorul 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. Colţul din dreapta-jos al zonei client are coordonatele (cxClient/2, cyClient/2). Dacă vreţi să afişaţi text începând din colţul din stânga-sus al zonei client, care are coordonatele de dispozitiv (0, 0), trebuie să folosiţi coordonate logice negative:

TextOut (hdc, -cxClient/2, -cyClient/2, "Hello", 5) ;

67. Obţinerea informaţiilor despre culori. PLANES, BITSPIXEL, NUMCOLORS: Tipul COLORREF.

Page 4: PW 66-80.docx

Obţinerea informaţiilor despre culoriPentru afişarea culorilor este nevoie de mai mulţi biţi. Cu cât se folosesc mai mulţi biţi, cu atât pot

fi afişate mai multe culori. Sau, mai precis, numărul culorilor care pot fi afişate simultan este egal cu 2 la o putere egală cu numărul de biţi folosiţi. De obicei, biţii sunt organizaţi în planuri de culori - un plan pentru roşu, un plan pentru verde, unul pentru albastru şi unul pentru intensitatea culorii. Adaptoarele video cu 8, 16 sau 24 de biţi pentru fiecare pixel au un singur plan de culoare, în care un număr de biţi adiacenţi reprezintă culoarea fiecărui pixel.

Funcţia GetDeviceCaps vă permite să determinaţi modul de organizare a memoriei în adaptoarele video şi numărul de culori care pot fi reprezentate. Apelul de mai jos returnează numărul de planuri de culoare:

iPlanes = GetDeviceCaps (hdc, PLANES);Apelul următor returnează numărul de biţi de culoare folosiţi pentru fiecare pixel:iBitsPixel = GetDeviceCaps (hdc, BITSPIXEL)Majoritatea adaptoarelor video care pot afişa culori folosesc fie mai multe planuri de culoare, fie

mai mulţi biţi de culoare pentru fiecare pixel, dar nu pe amândouă; cu alte cuvinte, unul dintre cele două apeluri de mai sus va returna valoarea 1. Numărul de culori care pot fi redate de o placă video se poate calcula cu formula următoare:

iColors = 1<<(iPlanes * iBitsPixel);Această valoare poate să nu fie identică cu numărul de culori obţinut prin apelarea funcţiei

GetDeviceCaps cu parametrul NUMCOLORS:iColors = GetDeviceCaps (hdc, NUMCOLORS);Aceste valori pot fi diferite şi în cazul adaptoarelor video care permit încărcarea paletelor de culori.

Funcţia GetDeviceCaps apelată cu parametrul NUMCOLORS returnează numărul de culori rezervate de Windows, adică 20. Celelalte 236 de culori pot fi stabilite de program folosind un manager de palete.

Windows foloseşte pentru reprezentarea culorilor o valoare întreagă fără semn, pe 32 de biţi. Tipul de date folosit pentru culori se numeşte COLORREF. Ultimii trei octeţi ai numărului (cei mai puţin semnificativi) specifică valorile pentru culorile roşu, verde şi albastru, de la 0 la 255. Rezultă o paletă potenţială de 224 culori (aproximativ 16 milioane de culori).

Valoarea pe 32 de biţi de mai sus e numită deseori „culoare RGB". În fişierele antet din Windows sunt definite mai multe macroinstrucţiuni pentru lucrul cu valorile RGB. Macroinstrucţiunea RGB acceptă trei argumente, care reprezintă valorile pentru culorile roşu, verde şi albastru şi le combină într-o valoarea întreagă pe 32 de biţi, fără semn:

Dacă toate cele trei argumente au valoarea 0, se obţine negrul, iar dacă au valoarea 255, se obţine albul.

Numărul de culori returnat de funcţia GetDeviceCaps reprezintă numărul de culori pure pe care le poate afişa dispozitivul respectiv.

68. Obţinerea variabilei handle a contextului de dispozitiv. Obţinerea informaţiilor despre contextul de dispozitiv.

Obţinerea variabilei handle a contextului de dispozitivSistemul de operare Windows vă pune la dispoziţie mai multe metode pentru obţinerea variabilei

handle a contextului de dispozitiv. Cea mai cunoscută metodă de obţinere şi de ştergere a variabilei handle a contextului de

dispozitiv implică folosirea funcţiilor BeginPaint şi EndPaint în timpul prelucrării mesajului WM_PAINT:hdc - BeginPaint (hwnd, &ps);[alte Unii de program] EndPaint (hwnd, &ps);Variabila ps este o structură de tip PAINTSTRUCT. Câmpul hdc al acestei structuri conţine variabila

handle a contextului de dispozitiv. Structura PAINTSTRUCT conţine şi o structură de tip RECT numită rcPaint, care defineşte dreptunghiul ce cuprinde regiunea invalidă a zonei client a ferestrei.

Programele Windows pot să obţină variabila handle a contextului de dispozitiv şi în timpul prelucrării altor mesaje decât WM_PAINT:

hdc = GetDC (hwnd);(alte linii de program] ReleaseDC (hwnd, hdc);Acest context de dispozitiv se aplică zonei client a ferestrei care are variabila handle hwnd.

Principala diferenţă între apelul de mai sus şi metoda folosirii funcţiilor BeginPaint şi EndPaint este că

Page 5: PW 66-80.docx

variabila handle returnată de funcţia GetDC vă permite să desenaţi în toată zona client a ferestrei. În plus, funcţiile GetDC şi ReleaseDC nu validează eventualele regiuni invalide ale zonei client.

Un program Windows poate să obţină şi o variabilă handle a unui context de dispozitiv care se aplică întregii ferestre, nu numai zonei client a ferestrei:

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

Obţinerea informaţiilor despre contextul de dispozitivGetDeviceCaps („get device capabilities"):iValue = GetDeviceCaps (hdc, iIndex) ;Parametrul iIndex este unul dintre cei 28 de identificatori definiţi în fişierele antet din Windows. De

exemplu, dacă iIndex are valoarea HORZRES funcţia GetDeviceCaps returnează lăţimea dispozitivului în pixeli; VERTRES returnează înălţimea dispozitivului în pixeli.

69. Parametrul PitchAndFamily. Funcţia SetTextAlign.Pentru fonturile cu dimensiune fixă, cxCaps este egală cu cxChar. Pentru fonturile cu dimensiune

variabilă, cxCaps este 150% din cxChar. Bitul cel mai puţin semnificativ al câmpului tmPitchAndFamily din structura TEXTMETRIC are valoarea 1 pentru fonturile cu dimensiune variabilă şi valoarea 0 pentru fonturile cu dimensiune fixă. Programul SYSMETS1 foloseşte acest bit ca să calculeze valoarea cxCaps din cxChar:

cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;Toate operaţiile de desenare în fereastră sunt făcute în timpul prelucrării mesajului WM_PAINT. Nu ar fi mai simplu dacă am putea să afişăm o coloană de numere aliniate la dreapta prin

specificarea poziţiei în care se termină numerele, în locul poziţiei la care încep acestea? După ce programul SYSMETS apelează funcţia:

SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;coordonatele transmise funcţiilor TextOut care urmează specifică localizarea colţului din dreapta-sus al şirului de caractere, în locul colţului din stânga-sus.

Funcţia TextOut care afişează coloana de numere are ca al doilea parametru următoarea expresie:cxChar + 22 * cxCaps + 40 * cxChar

Page 6: PW 66-80.docx

Valoarea 40 x cxChar reprezintă lăţimea însumată a coloanelor doi şi trei. După apelarea funcţiei TextOut este apelată din nou funcţia SetTextAlign, pentru a readuce la normal modul de aliniere a textului.

70. Pensule „haşurate". Stiluri de haşura. Funcţia CreatePatternBrush.

Puteţi să creaţi şi o pensulă „haşurată" cu linii orizontale, verticale sau oblice. Acest stil de pensule este folosit frecvent pentru colorarea barelor din diagrame sau grafice şi pentru desenele executate de plottere. Funcţia care creează o pensulă haşurată este:

hBrush = CreateHatchBrush (iHatchStyle, rgbColor) ;Parametrul iHatchStyle precizează aspectul haşurii şi poate avea una dintre următoarele valori:

HS_HORIZONTAL, HS_VERTICAL, HS_FDIAGONAL, HS_BDIAGONAL, HS_CROSS şi HS_DIAGCROSS. Parametrul rgbColor din funcţia CreateHatchBrush reprezintă culoarea liniilor cu care se face haşurarea. Atunci când selectaţi pensula în contextul de dispozitiv, Windows converteşte această culoare în cea mai apropiată culoare pură. Spaţiul dintre liniile de haşură sunt colorate în funcţie de modul de desenare a fondului şi de culoarea fondului, definite în contextul de dispozitiv. Dacă modul de desenare a fondului este OPAQUE, culoarea fondului este folosită pentru umplerea spaţiilor dintre linii, în acest caz, nici liniile de haşură, nici culoarea de umplere nu pot fi culori amestecate. Dacă modul de desenare a fondului este TRANSPARENT, Windows desenează liniile de haşura fără să umple spaţiile dintre acestea.Deoarece pensulele sunt întotdeauna imagini bitmap 8x8, aspectul pensulelor haşurate va depinde de rezoluţia dispozitivului pe care se face afişarea.

Cu ajutorul funcţiei CreatePatternBrush puteţi să creaţi pensule proprii, bazate pe o imagine bitmap:

hBrush = CreatePatternBrush (hBitmap) ;

71. Redesenarea zonei client. Ciclul de mesaje. Structura de tip MSG. Funcţiile GetMessage, TranslateMessage, DispatchMessage.

Afişarea ferestreiDupă executarea funcţiei CreateWindow, fereastra a fost creată de Windows, dar încă nu este

afişată pe ecran. Pentru aceasta mai sunt necesare încă două apeluri de funcţii. Primul este:ShowWindow (hwnd, iCmdShow) ;Primul parametru este o variabilă handle a ferestrei create de funcţia CreateWindow. Al doilea

parametru este variabila iCmdShow, transmisă funcţiei WinMain. Dacă iCmdShow este SW_SHOWNORMAL (egal cu 1), fereastra este afişată normal. Dacă iCmdShow este SW_SHOWMINNOACTIVE (egal cu 7), atunci fereastra nu este afişată, dar numele şi pictograma acesteia apar pe bara de taskuri.

În programul HELLOWIN funcţia ShowWindow afişează fereastra pe ecran. Dacă al doilea parametru al funcţiei este SW_SHOWNORMAL, Windows şterge zona client a ferestrei folosind pensula specificată în clasa ferestrei. Apelul:

UpdateWindow (hwnd) ;determină redesenarea zonei client. Acest lucru se face prin trimiterea către procedura de

fereastră (funcţia WndProc din HELLOWIN.C) a unui mesaj WM_PAINT. Vom vedea imediat cum tratează funcţia WndProc aceste mesaje.Ciclul de mesaje

După apelarea funcţiei UpdateWindow, fereastra devine vizibilă pe ecran. Programul trebuie să fie acum pregătit să citească intrările de la mouse şi de la tastatură. Windows formează o „coadă de mesaje" pentru fiecare program rulat concurenţial. Atunci când apare un eveniment exterior, Windows converteşte acest eveniment într-un mesaj pe care îl plasează în coada de aşteptare.

Un program preia mesajele din coada de aşteptare prin executarea unei secvenţe de cod numită „ciclu de mesaje" („message loop"):

while (GetMessage (&msg, NULL, 0, 0)){TranslateMessage (&msg) ;DispatchMessage (&msg) ;} return msg.wParam ;

Variabila msg este o structură de tip MSG, definită în fişierele antet din Windows astfel:

typedef struct tagMSG {

Page 7: PW 66-80.docx

HWND hwnd ;UINT message ;WPARAM wParam ;LPARAM lParam ;DWORD time ;POINT pt ;}MSG ,Tipul de date POINT este tot o structură, definită astfel:typedef struct tagPOINT { LONG x ;LONG y ;} POINT ;

Funcţia GetMessage apelată la începutul ciclului de mesaje preia un mesaj din coada de aşteptare:GetMessage (&msg, NULL, 0, 0)Acest apel transmite sistemului de operare un pointer, numit msg, la o structură de tip MSG. Al

doilea, al treilea şi al patrulea parametru au valoarea NULL sau 0, ceea ce indică faptul că programul vrea să preia toate mesajele, pentru toate ferestrele create de program. Windows completează câmpurile structurii de mesaje cu următorul mesaj din coada de aşteptare. Câmpurile acestei structuri sunt: hwnd - variabila handle a ferestrei căreia îi este destinat mesajul. În programul HELLOWIN, aceasta

este aceeaşi cu valoarea hwnd returnată de funcţia CreateWindow, deoarece aceasta este singura fereastră a programului.

message - identificatorul mesajului. Acesta este un număr folosit pentru identificarea mesajului. Pentru fiecare mesaj în fişierele antet din Windows este definit un identificator care începe cu prefixul WM_ („window message"). De exemplu, dacă poziţionaţi indicatorul mouse-ului în zona client a programului HELLOWIN şi apăsaţi butonul din stânga, Windows va insera în coada de aşteptare un mesaj pentru care câmpul message conţine identificatorul WM_LBUTTONDOWN, adică valoarea 0x0201.

wParam - un parametru pe 32 de biţi a cărui valoare depinde de mesajul trimis. lParam - un alt parametru pe 32 de biţi dependent de mesaj. time - momentul inserării mesajului în coada de mesaje. pt - coordonatele poziţiei mouse-ului în momentul inserării mesajului în coada de mesaje.

Instrucţiunea:TranslateMessage (&msg) ;

retransmite structura msg sistemului de operare, pentru convertirea unor mesaje de la tastatură. Instrucţiunea:DispatchMessage (&msg) ;

ca şi funcţia TranslateMessage, retransmite structura msg sistemului de operare. Windows trimite apoi mesajul către procedura de fereastră corespunzătoare, în vederea prelucrării - cu alte cuvinte, Windows apelează procedura de fereastră. În programul HELLOWIN, procedura de fereastră este WndProc. După ce prelucrează mesajul, funcţia WndProc predă controlul sistemului de operare, care încă elaborează răspunsul la apelul DispatchMessage. Atunci când Windows returnează controlul programului HELLOWIN, după executarea apelului DispatchMessage, ciclul de tratare a mesajelor continuă cu următorul apel al funcţiei GetMessage.

Funcţia DispatchMessage transmite mesajul procedurii de fereastră corespunzătoare. Între cele două funcţii este apelată funcţia TranslateMessage, care transformă mesajele generate de acţionarea tastelor în mesaje caracter. Dacă mesajul este WM_KEYDOWN sau WM_SYSKEYDOWN şi dacă tasta apăsată, în funcţie de starea tastelor de modificare, generează un caracter, atunci funcţia TranslateMessage inserează un mesaj caracter în coada de aşteptare. 72. Sistemul și cronometrul. Timpul Windows standard. Sistemul şi cronometrul

Cronometrul din Windows este o extensie relativ simplă a logicii de ceas implementată hardware în calculatoarele personale şi în sistemul ROM BIOS. Sistemul ROM BIOS iniţializează un circuit de ceas care generează o întrerupere de ceas, numită uneori „tact de ceas" sau „tact de cronometru". Aceste întreruperi sunt generate la fiecare 54,925 milisecunde, adică de 18,2 ori pe

Page 8: PW 66-80.docx

secundă. Unele programe scrise pentru MS DOS interceptează această întrerupere pentru implementarea unor ceasuri sau a unor cronometre.

Programele Windows nu fac acest lucru. Întreruperile hardware sunt tratate chiar de sistemul de operare, aşa că aplicaţiile nu mai trebuie să facă acest lucru. Pentru fiecare program care creează un cronometru, Windows tratează întreruperile de ceas decrementând contorul transmis prin apelarea funcţiei SetTimer. Atunci când această valoare ajunge la 0, Windows plasează în coada de aşteptare a aplicaţiei un mesaj WM_TIMER şi atribuie contorului valoarea originală.

Deoarece programele Windows preiau mesajele WM_TIMER din coada de aşteptare nu trebuie să vă faceţi probleme privind întreruperea unei operaţii de prelucrare prin sosirea unui mesaj WM_TIMER. Din acest punct de vedere, cronometrul se aseamănă cu tastatura şi cu mouse-ul: driverul tratează evenimentele asincrone generate de ceasul hardware, iar Windows transformă aceste evenimente în mesaje structurate şi serializate.

Cronometrul Windows are aceeaşi rezoluţie de 54,925 milisecunde ca şi ceasul hardware al calculatorului, pe care de fapt se bazează. Acest lucru are două implicaţii importante:■ O aplicaţie Windows nu poate să primească mesaje WM_TIMER cu o rată mai mare de 18,2

ori/secundă dacă foloseşte un singur cronometru.■ Intervalul de timp pe care îl specificaţi la apelarea funcţiei SetTimer este rotunjit la un

multiplu întreg de tacturi de ceas.

73. Tipul PAINTSTRCUT, MM_TEXT. Regiuni de decupare (clipping region). Fontul sistem SYSTEM_FONT.

Structura de informaţii pentru desenareAm vorbit anterior despre „structura de informaţii pentru desenare" („paint information structure")

păstrată de Windows pentru fiecare fereastră. Această structură este definită astfel:typedef struct tagPAINTSTRUCT {

HDC hdc;BOOL fErase;RECT rcPaint;BOOL fRestore;BOOL fIncUpdate;BYTE rgbReserved[32];

} PAINTSTRCUT;

Windows completează câmpurile acestei structuri atunci când programul dumneavoastră apelează funcţia BeginPaint. Programul poate să folosească numai primele trei câmpuri, celelalte fiind folosite intern de sistemul de operare.

Câmpul hdc reprezintă variabila handle a contextului de dispozitiv. Deoarece redundanţa este tipică pentru sistemul de operare Windows, valoarea returnată de funcţia BeginPaint este aceeaşi variabilă handle.

În majoritatea cazurilor, câmpul fErase va avea valoarea TRUE (diferită de zero), ceea ce înseamnă că Windows a şters fondul dreptunghiului invalid. Pentru ştergerea fondului, Windows foloseşte pensula specificată în câmpul hbrBackground al structurii WNDCLASSEX, pe care aţi folosit-o la înregistrarea clasei în timpul iniţializărilor, din funcţia WinMain. Multe programe Windows folosesc o pensulă de culoare albă:

wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);Totuşi, dacă programul invalidează un dreptunghi din zona client apelând funcţia InvalidateRect,

ultimul parametru al funcţiei specifică dacă vreţi ca fondul să fie şters. Dacă acest parametru este FALSE (0), Windows nu va şterge fondul şi câmpul fErase va avea valoarea FALSE.

Câmpul rcPaint al structurii PAINTSTRUCT este o structură de tip RECT. Aşa cum aţi aflat din Capitolul 2, structura RECT defineşte un dreptunghi. Cele patru câmpuri ale structurii sunt left, top, right şi bottom. Câmpul rcPaint al structurii PAINTSTRUCT defineşte limitele unui dreptunghi invalid, aşa cum se poate vedea în figura 3.1. Valorile sunt date în pixeli, şi se raportează la colţul din stânga-sus al zonei client a ferestrei. Dreptunghiul invalid este suprafaţa pe care ar trebui să o redesenaţi. Deşi un program Windows ar putea să redeseneze întreaga zonă client a ferestrei de fiecare dată când primeşte un mesaj WM_PAINT, redesenând numai porţiunea ferestrei definită de dreptunghi programul economiseşte timp.

Dreptunghiul rcPaint din structura PAINTSTRUCT nu este un simplu dreptunghi invalid, ci un dreptunghi „de decupare" (clipping rectangle). Aceasta înseamnă că Windows restricţionează desenarea în interiorul dreptunghiului. Atunci când folosiţi variabila handle a contextului de dispozitiv din structura PAINTSTRUCT, Windows nu desenează în afara dreptunghiului rcPaint.

Pentru desenarea în afara dreptunghiului rcPaint în timpul prelucrării mesajului WM_PAINT, faceţi următorul apel: InvalidateRect (hWnd, NULL, TRUE); înaintea apelării funcţiei BeginPaint. Apelul de

Page 9: PW 66-80.docx

mai sus invalidează întreaga zonă client şi şterge fondul acesteia. Dacă ultimul parametru are valoarea FALSE, fondul nu este şters şi desenul va fi făcut peste ceea ce există deja.

în Windows există diferite moduri de mapare care controlează transformarea coordonatelor logice transmise funcţiilor GDI în coordonate fizice ale pixelilor afişaţi pe ecran. Modul de mapare este definit în contextul de dispozitiv. Modul de mapare prestabilit este MM_TEXT (folosind identificatorul definit în fişierele antet Windows). În modul de mapare MM_TEXT, unităţile logice sunt aceleaşi cu unităţile fizice, adică pixelii; ele se raportează la colţul din stânga-sus al zonei client, iar valorile coordonatei y cresc pe măsură ce coborâţi în zona client a ferestrei (vezi Figura 3.2). Sistemul de coordonate MM_TEXT este acelaşi cu sistemul de coordonate folosit de Windows pentru definirea dreptunghiului invalid din structura PAINTSTRUCT.

Contextul de dispozitiv defineşte şi o regiune de decupare (clipping region). Aşa cum aţi văzut, regiunea prestabilită de decupare este întreaga zonă client, pentru o variabilă handle a contextului de dispozitiv obţinută prin apelarea funcţiei GetDC, sau numai regiunea invalidă, pentru o variabilă handle a contextului de dispozitiv obţinută prin apelarea funcţiei BeginPaint. Windows nu afişează partea care se află în afara regiunii de decupare şi care aparţine şirului de caractere, ci numai porţiunile care sunt cuprinse în regiunea de decupare. Scrierea în afara zonei client a unei ferestre este o operaţiune dificilă, aşa că nu vă speriaţi - nu este posibil să faceţi acest lucru din greşeală.

Fontul sistemTot în contextul de dispozitiv este definit şi fontul pe care sistemul de operare Windows îl foloseşte

pentru scrierea textului în zona client. Fontul prestabilit este numit „font sistem" sau (folosind identificatorul definit în fişierele antet Windows) SYSTEM_FONT. Fontul sistem este fontul pe care Windows îl foloseşte pentru textul din barele de titlu, barele de meniu şi casetele de dialog.

La începuturile sistemului de operare Windows, fontul sistem era un font cu dimensiune fixă, ceea ce înseamnă că toate caracterele aveau aceeaşi lăţime, ca la maşinile de scris. Începând cu versiunea Windows 3.0 şi continuând pană la Windows 95, fontul sistem este un font cu dimensiune variabilă, ceea ce înseamnă că fiecare caracter are o altă dimensiune. De exemplu, „W" este mai lat decât „i". Este foarte clar că un text scris cu un font având dimensiune variabilă este mai uşor de citit decât un font cu dimensiune fixă.

Fontul sistem este un font de tip „rastru", ceea ce înseamnă că fiecare caracter este definit ca un bloc de pixeli. Fontul sistem trebuie proiectat astfel încât pe ecran să încapă cel puţin 25 de linii cu câte 80 de caractere. Aceasta este singura garanţie privind compatibilitatea între dimensiunea ecranului şi dimensiunea fontului.

74. Umplerea golurilor. Modul de desenare a fondului OPAQUE. Funcţiile SetBkColor, SetBkMode.

Umplerea golurilorFolosirea peniţelor pentru linii punctate sau pentru linii întrerupte ridică o întrebare interesantă: ce

se întâmplă cu pauzele dintre puncte sau dintre liniuţe? Culoarea acestor spaţii 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, ceea ce înseamnă că Windows umple spaţiile cu culoarea fondului, care în mod prestabilit este alb. Rezultatele sunt aceleaşi în cazul pensulei WHITE_BRUSH, folosită de majoritatea programelor în clasa ferestrei pentru ştergerea fondului.

Puteţi să schimbaţi culoarea fondului pentru completarea spaţiilor goale dintre linii, prin apelarea funcţiei SetBkColor:

SetBkColor (hdc, rgbColor) ;Ca şi în cazul valorii rgbColor folosită pentru culoarea peniţei, Windows converteşte valoarea

specificată într-o culoare pură. Puteţi să obţineţi culoarea definîtă în contextul de dispozitiv prin apelarea funcţiei GetBkColor.

De asemenea, puteţi să împiedicaţi colorarea spaţiilor stabilind modul TRANSPARENT de desenare a fondului:

SetBkMode (hdc, TRANSPARENT) ;Windows va ignora culoarea fondului şi nu va mai colora spaţiile goale. Modul de desenare a

fondului (TRANSPARENT sau OPAQUE) poate fi obţinut cu ajutorul funcţiei GetBkMode.

75. Utilizarea cronometrului pentru a realiza un ceas. Obţinerea orei şi a datei

Page 10: PW 66-80.docx

În funcţia WndPaint, programul DIGCLOCK foloseşte funcţiile C time şi localtime ca să determine data şi ora curente. Funcţia localtime stochează toate informaţiile de care avem nevoie într-o structură; mai multe macroinstrucţiuni definite în partea superioară a programului fac apelurile funcţiei wsprintf mai uşor de citit.

Internaţionalizarea programuluiWindows asigură suportul pentru internaţionalizarea programelor. Fişierul WIN .INI - creat în timpul instalării sistemului de operare - conţine o secţiune cu titlul [intl]. în această secţiune sunt incluse informaţii legate de formatul datei, al orei, al monedei naţionale şi al numerelor. Puteţi să afişaţi data în unul dintre următoarele trei formate: lună-zi-an, an-lună-zi sau zi-lună-an. Separatorul dintre cele trei numere poate fi caracterul slash, liniuţa de despărţire, punctul sau orice alt caracter doriţi. Puteţi să afişaţi ora în formatul pe 12 sau pe 24 de ore; de obicei, pentru separarea orelor, minutelor sau a secundelor este folosit caracterul două puncte.

Funcţia Setlnternational din programul DIGCLOCK obţine informaţii de formatare din fişierul WIN.INI folosind funcţiile GetProfilelnt (pentru numere întregi) şi GetProfileString (pentru şiruri de caractere). La apelarea acestor funcţii trebuie să fie incluse valori prestabilite, pentru cazurile în care Windows nu poate găsi valorile căutate în fişierul WIN.INI. Funcţia Setlnternational stochează valorile obţinute în variabile globale care au ca nume şirurile de caractere folosite în fişierul WIN.INI pentru identificarea valorilor respective. Funcţia WndPaint foloseşte valorile obţinute din fişierul WIN.INI pentru formatarea datei şi a orei afişate, apoi apelează funcţia DrawText pentru centrarea celor două linii de text în fereastră.

Aşa cum este de aşteptat, de fiecare dată când procedura de fereastră primeşte un mesaj WM_TIMER, programul DIGCLOCK invalidează fereastra pentru generarea unui mesaj WM_PAINT. Dar funcţia WndProc invalidează fereastra şi atunci când primeşte un mesaj WM_WININICHANGE. Orice program care modifică fişierul WIN.INI trimite mesaje WM_WININICHANGE tuturor aplicaţiilor Windows active. Atunci când primeşte un mesaj WM_TIMER, programul DIGCLOCK invalidează fereastra astfel:

InvalidateRect (hwnd, NULL, FALSE) ;Valoarea TRUE folosită pentru ultimul parametru al funcţiei InvalidateRect determină ştergerea fondului ferestrei înainte de redesenare. Dacă acest parametru are valoarea FALSE, Windows desenează peste fondul existent. Am folosit valoarea FALSE în timpul prelucrării mesajului WMTIMER pentru reducerea efectului de licărire a imaginii afişate.

La recepţionarea unui mesaj WM_TIMER, cea mai mare modificare a lungimii este de două caractere - de exemplu, atunci când data se schimbă de la 12/31 /96 la 1 /1 /97 - aşa că şirul de caractere formatat folosit pentru afişare de funcţia WndPaint are la fiecare capăt două spaţii suplimentare, acoperitoare pentru această modificare în lungime şi pentru diferenţele datorate folosirii unui font proporţional. Am putea să includem în programul DIGCLOCK şi logica de prelucrare a mesajelor WM TIMECHANGE, care informează aplicaţiile privind modificarea datei sau a orei sistemului. Deoarece informaţiile deţinute de programul DIGCLOCK sunt actualizate la fiecare secundă prin mesaje WM_TIMER, acest lucru nu este necesar. Prelucrarea mesajelor WM_TIMECHANGE ar avea sens pentru un ceas actualizat la fiecare minut.

76. Utilizarea cronometrului pentru animații. ANIMAŢII

Programul BOUNCE reconstruieşte mingea de fiecare dată când programul primeşte un mesaj WM_SIZE. Pentru aceasta este nevoie de un context de dispozitiv compatibil cu monitorul video:

hdcMem = CreateCompatibleDC (hdc) ;Diametrul mingii este 1/16 din minimul dintre lăţimea şi înălţimea zonei client a ferestrei. Totuşi, programul construieşte o imagine bitmap mai mare decât mingea: pe fiecare dintre cele patru laturi imaginea bitmap este mai mare decât mingea, cu jumătate din raza acesteia:

hBitmap = CreateCompatibleBitmap (hdc, cxTotal, cyTotal) ;După ce este selectată în contextul de dispozitiv din memorie, întreaga imagine bitmap este colorată cu alb, pentru obţinerea fondului:

Rectangle (hdcMem, -1, -1, xTotal + 1, yTotal + 1) ;în contextul de dispozitiv din memorie este selectată o pensulă cu haşură diagonală, apoi este desenată mingea, în centrul imaginii bitmap:

Ellipse (hdcMem, xMove, yMove, xTotal - xMove, yTotal - yMove) ;

Page 11: PW 66-80.docx

Spaţiile libere păstrate în imaginea bitmap în jurul mingii şterg imaginea anterioară a mingii atunci când mingea este mutată. Pentru redesenarea mingii într-o altă poziţie este nevoie doar de apelarea funcţiei BitBlt folosind codul ROP2RCCOPY:

BitBlt (hdc, xCenter - xTotal / 2, yCenter - yTotal / 2, xTotai, yTotal, hdcMem, 0, 0, SRCCOPY) ;Programul BOUNCE ilustrează cea mai simplă cale de deplasare a unei imagini pe ecran, dar

acest mod de abordare nu este satisfăcător în toate situaţiile. Dacă vă interesează animaţiile, v-ar fi de folos examinarea celorlalte coduri ROP (cum ar fi SRCINVERT) care efectuează operaţii SAU EXCLUSIV între sursă şi destinaţie. Alte tehnici de animaţie implică folosirea paletei Windows (şi a funcţiei AnimatePalette) precum şi a funcţiei CreateDIBSection.

77. Utilizarea cronometrului. Prima metodă. Prima metodăPrima metodă (şi cea mai simplă) determină sistemul de operare să trimită mesajele WM_TIMER

către procedura de fereastră normală a aplicaţiei. Apelul funcţiei SetTimer arată astfel:SetTimer (hwnd, 1, iMsecInterval, NULL);

Primul parametru este o variabilă handle pentru fereastra a cărei procedură de fereastră va primi mesajele WM_TIMER. Al doilea parametru este identificatorul cronometrului, care trebuie să fie o valoare diferită de zero şi care în acest exemplu este în mod arbitrar 1. Al treilea parametru este o valoare întreagă fără semn pe 32 de biţi, care specifică intervalul de timp în milisecunde. Dacă acest parametru are valoarea 60000, programul va primi un mesaj WM_TIMER la fiecare minut. Puteţi să opriţi generarea mesajelor WM_TIMER în orice moment, chiar şi în timpul prelucrării unui mesaj WM_TIMER, apelând funcţia:

KillTimer (hwnd, 1);Al doilea parametru al funcţiei KillTimer este acelaşi identificator cu cel folosit la apelarea funcţiei

SetTimer. Înaintea terminării programului, ca răspuns la mesajul WM_DESTROY, este recomandat să distrugeţi toate cronometrele active din program.

Atunci când procedura de fereastră primeşte un mesaj WM_TIMER, parametrul wParam conţine identificatorul cronometrului (care în acest caz este 1) iar parametrul lParam este 0. Dacă aveţi nevoie de mai multe cronometre, folosiţi un identificator unic pentru fiecare. Valoarea parametrului wParam va diferenţia mesajele WM_TIMER trimise ferestrei. Pentru ca programul să fie mai uşor de citit, puteţi să folosiţi instrucţiuni define pentru definirea identificatorilor fiecărui cronometru:

Dacă vreţi să schimbaţi intervalul de timp al unui cronometru existent, opriţi cronometrul şi apelaţi din nou funcţia SetTimer:KillTimer (hwnd, 1);SetTimer (hwnd, 1, iMsecInterval, NULL);

78. Utilizarea cronometrului. Metoda a doua. A doua metodă

A doua metodă vă permite să folosiţi un cronometru astfel încât Windows să trimită mesajele WM_TIMER către o altă funcţie din program.

Funcţia care recepţionează mesajele de cronometru este numită funcţie cu apel invers (callback). Aceasta este o funcţie din program care poate fi apelată direct de sistemul de operare. Programul comunică sistemului de operare adresa funcţiei, iar sistemul de operare Windows apelează ulterior funcţia.

Ca şi procedurile de fereastră, funcţiile cu apel invers trebuie să fie definite de tipul CALLBACK, deoarece sunt apelate de Windows din afara spaţiului de cod al programului. Parametrii transmişi funcţiilor cu apel invers şi valoarea returnată de acestea depind de scopul funcţiei. În cazul unei funcţii cu apel invers asociate unui cronometru, parametrii de intrare sunt aceiaşi cu parametrii de intrare ai unei proceduri de fereastră. Funcţiile cu apel invers folosite pentru cronometre nu returnează nici o valoare către sistemul de operare.Presupunem că funcţia cu apel invers se numeşte TimerProc. (Puteţi să daţi orice nume doriţi.) Această funcţie va prelucra numai mesajele WM_TIMER.

VOID CALLBACK TimerProc (HWND hwnd, UINT iMsg, UINT iTimerlD, DWORD dwTime) [prelucrează mesajele WM_TIMER]

Parametrul de intrare hwnd reprezintă variabila handle a ferestrei specificate la apelarea funcţiei SetTimer. Windows va trimite funcţiei TimerProc numai mesajele WM_TIMER, aşa că parametrul iMsg va avea întotdeauna valoarea WM_TIMER. Parametrul iTimerlD conţine identificatorul cronometrului, iar parametrul dwTime reprezintă timpul sistemului.

Aşa cum am menţionat anterior, prima metodă de pornire a unui cronometru impune apelarea funcţiei SetTimer în felul următor:

Page 12: PW 66-80.docx

SetTimer (hwnd, iTimerlD, iHsednterval, NULL) ;Atunci când folosiţi o funcţie cu apel invers pentru prelucrarea mesajelor WM_ TIMER, al patrulea parametru al funcţiei SetTimer trebuie să conţină adresa funcţiei cu apel invers, ca în exemplul următor:

SetTimer (hwnd, iTimerlD, iHsednterval, (TIMERPROC) TimerProc) ;

79. Utilizarea cronometrului. Metoda a treia. A treia metodă

A treia metodă este asemănătoare cu cea de-a doua, cu diferenţa că parametrul hwnd din apelul funcţiei SetTimer are valoare NULL, iar al doilea parametru (care ar fi trebuit sa fie identificatorul cronometrului) este ignorat. Rezultatul este faptul că funcţia SetTimer returnează un identificator al cronometrului:

iTimerID = SetTimer (NULL, 0, iMsecInterval, (TIMERPROC) TimerProc) ;Variabila iTimerID returnată de funcţia SetTimer va avea valoarea NULL dacă nu este disponibil nici un cronometru.

Primul parametru al funcţiei KillTimer (de obicei folosit pentru transmiterea variabilei handle a ferestrei) trebuie să aibă valoarea NULL. Al doilea parametru (identificatorul cronometrului) trebuie să fie valoarea returnată de funcţia SetTimer:

KillTimer (NULL, iTimerlD) ;Parametrul hwnd transmis funcţiei TimerProc trebuie să aibă tot valoarea NULL.

Această metodă de pornire a cronometrelor este rareori folosită. Se poate dovedi totuşi utilă dacă folosiţi în program mai multe cronometre în diferite puncte, şi nu vreţi să ţineţi socoteala identificatorilor pe care deja i-aţi folosit.

Acum ştiţi să folosiţi cronometrele din Windows, aşa că este timpul să vedeţi câteva programe utile.

80. Variabilele handle. Notaţia ungară. Punctul de intrare în program. Înregistrarea clasei de fereastră. Crearea ferestrei. Afişarea ferestrei.

Mulţi programatori Windows folosesc „notaţia ungară", o convenţie de denumire a variabilelor. Convenţia este foarte simplă - fiecare nume de variabilă începe cu una sau mai multe litere mici care specifică tipul de date al variabilei. De exemplu, prefixul sz al variabilei szCmdLine semnifică „şir de caractere terminat cu zero". Prefixul h al variabilelor hInstance şi hPrevInstance înseamnă „variabilă handle"; prefixul i al variabilei iCmdShow înseamnă „întreg". De exemplu, în funcţia WinMain din programul HELLOWIN.C, variabila msg este o structură de tip MSG iar wndclass este o variabilă de tip WNDCLASSEX. În funcţia WndProc, ps este o structură de tip PAINTSTRUCT iar rect este o structură de tip RECT.

Prefix Tip de datec charby BYTE (unsigned char)i intx, y int (folosit pentru coordonate)cx, cy int (folosit pentru dimensiuni pe axele x si y, c vine de la „contor")b sau f BOOL (int); f vine de la „flag" (indicator)w WORD (unsigned short)l LONG (long)fn funcţies şir de caracteresz sir de caractere terminat cu zeroh variabilă handlep pointer

În sfârşit, în program sunt folosiţi trei identificatori cu majuscule pentru diferite tipuri de variabile handle:

Identificator SemnificaţieHINSTANCE Variabilă handle a unei „instanţe" - programul însuşiHWND Variabilă handle a unei ferestreHDC Variabilă handle a unui context de dispozitiv

Page 13: PW 66-80.docx

O variabilă handle este pur şi simplu un număr (de obicei pe 32 de biţi) care face trimitere la un obiect. Un program obţine aproape întotdeauna o variabilă apelând o funcţie Windows. Programul foloseşte apoi variabila handle obţinută pentru trimiterea la obiect în alte funcţii. Valoarea reală a variabilei handle nu este importantă pentru program, dar modulul Windows care o furnizează programului ştie cum să îl manipuleze pentru trimiterea la obiect.

Punctul de intrare într-un program Windows este o funcţie numită WinMain. Funcţia WinMain este întotdeauna definită astfel:

int WINAPI WinMain (HINSTANCE hinstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

Această funcţie foloseşte secvenţa de apelare WINAPI şi la terminare returnează sistemului de operare o valoare întreagă. Numele funcţiei trebuie să fie WinMain. Această funcţie are patru parametri:

Parametrul hlnstance este numit „variabilă handle a instanţei" („instance handle"). Acesta este un număr care identifică în mod unic toate programele rulate în Windows. Utilizatorul poate rula simultan mai multe copii ale aceluiaşi program. Aceste copii se numesc „instanţe" şi fiecare are o valoare diferită pentru parametrul hlnstance.

hPrevInstance („previous instance" - instanţa anterioară) este un parametru învechit. În versiunile Windows anterioare acest parametru conţinea variabila handle a celei mai recente instanţe încă activă a aceluiaşi program. Dacă nu erau încărcate alte instanţe ale programului, hPrevInstance avea valoarea 0 sau NULL.

Parametrul szCmdLine este un pointer la un şir de caractere terminat cu zero care conţine eventualii parametri transmişi programului în linia de comandă.

Parametrul iCmdShow este un număr care indică modul iniţial de afişare a ferestrei în Windows. În majoritatea cazurilor, iCmdShow are valoarea 1 sau 7. Mai sugestivi sunt identificatorii SW_SHOWNORMAL (definit în Windows ca 1) şi SW_SHOWMINNOACTIVE (definit cu valoarea 7). Prefixul SW vine de la „show window" (afişare fereastră). Acest parametru specifică dacă fereastra programului este afişată normal sau dacă este afişată iniţial doar ca o pictogramă.

Înregistrarea clasei de fereastrăO fereastră este întotdeauna creată pe baza unei clase de fereastră. Aceasta identifică procedura

de fereastră care prelucrează toate mesajele trimise către fereastră.Pe baza aceleiaşi clase pot fi create mai multe ferestre. De exemplu, toate butoanele din Windows

sunt create pe baza unei singure clase de fereastră. Aceasta defineşte procedura de fereastră şi alte caracteristici ale ferestrei create pe baza clasei respective. Atunci când creaţi o fereastră, definiţi şi atributele suplimentare ale acesteia, care sunt unice pentru fereastra respectivă.

Înainte de a crea fereastra programului trebuie să înregistraţi o clasă de fereastră, apelând funcţia RegisterClassEx.

Funcţia RegisterClassEx acceptă un singur parametru: un pointer la o structură de tipul WNDCLASSEX. Structura WNDCLASSEX este definită în fişierele antet din Windows astfel:

typedef struct tagWNDCLASSEX{UINT cbSize ;UINT style ;WNDPROC lpfnWndProc ;int cbClsExtra ;int cbWnExtra ;HINSTANCE hinstance ;HICON hicon ;HCURSOR hCursor ;HBRUSH hbrBackground ;LPCSTR lpszMenuName ;LPCSTR lpszClassName ;HICON hIconSm ;} WNDCLASSEX ;

În funcţia WinMain trebuie să definiţi o structură de tipul WNDCLASSEX, cum ar fi:

WNDCLASSEX wndclass ;

Apoi definiţi cele 12 câmpuri ale structurii şi apelaţi funcţia RegisterClassEx:

Page 14: PW 66-80.docx

RegisterClassEx (&wndclass) ;

Cele mai importante câmpuri ale structurii sunt al treilea şi penultimul. Penultimul câmp conţine numele clasei de fereastră. Al treilea câmp (lpfnWndProc) este adresa procedurii de fereastră folosită pentru toate ferestrele create pe baza acestei clase. Celelalte câmpuri descriu caracteristicile tuturor ferestrelor create pe baza acestei clase.

cbSize reprezintă dimensiunea structurii. wndclass.style = CS_HREDRAW | CS_VREDRAW ; combină doi identificatori pentru „stilul de clasă".

Acestea sunt constante pe 32 de biţi în care un singur bit are valoarea 1. Cei doi identificatori pentru stilul clasei indică faptul că toate ferestrele create pe baza acestei clase sunt redesenate complet, ori de câte ori se modifică dimensiunea pe orizontală (CS_HREDRAW) sau cea pe verticală (CS_VREDRAW) a ferestrei

wndclass.lpfnWndProc = WndProc ; Această instrucţiune stabileşte ca procedură de fereastră funcţia WndProc. Această procedură va prelucra toate mesajele trimise către toate ferestrele create pe baza acestei clase de fereastră. Aşa cum am arătat mai sus, prefixul lpfn înseamnă, în notaţia ungară, „pointer de tip long la o funcţie".

wndclass.cbClsExtra = 0 ;wndclass.cbWndExtra = 0 ; rezervă un spaţiu suplimentar în structura clasei şi în structura

ferestrei, păstrată în interiorul sistemului de Windows. Un program poate să utilizeze spaţiul suplimentar în scopuri proprii.

wndclass.hInstance = hinstance ; variabila handle a instanţeiwndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ; definesc o pictogramă pentru ferestrele

create pe baza acestei clase. Pictograma este o mică imagine de tip bitmap care apare în bara de taskuri a sistemului de operare şi în bara de titlu a ferestrei. Pentru obţinerea unei variabile handle a unei pictograme predefinite apelaţi funcţia LoadIcon cu primul parametru având valoarea NULL. Nu ne interesează valoarea reală a acestei variabile, ci doar o stocăm în câmpurile hIcon şi hIconSm.

wndclass.hCursor = LoadCursor (NULL, IDC_ ARROW) ; Funcţia LoadCursor încarcă un cursor predefinit pentru mouse, numit IDC_ARROW, şi returnează o variabilă handle a acestui cursor. Atunci când este deplasat deasupra zonei client a ferestrei create pe baza acestei clase, indicatorul mouse-ului este afişat sub forma unei săgeţi.

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); precizează culoarea fondului zonei client a ferestrelor create pe baza acestei clase. Prefixul hbr al numelui hbrBackground vine de la „handle to a brush".

Funcţia GetStockObject returnează o variabilă handle a unei pensule albe.wndclass.lpszMenuName = NULL ; meniul ferestreiwndclass.IpszClassName = szAppName ;Se înregistrează clasa de ferestre prin apelarea funcţiei RegisterClassEx. Singurul parametru al

funcţiei este un pointer către structura WNDCLASSEX:RegisterClassEx (&wndclass) ;

Crearea ferestreiClasa de fereastră defineşte caracteristicile generale ale unei ferestre, permiţând astfel folosirea

aceleiaşi clase pentru crearea mai multor ferestre.

hwnd =CreateWindow (szAppName, // numele clasei de fereastra"The Hello Program", // titlul ferestreiWS_OVERLAPPEDWINDOW, // stilul ferestreiCW_USEDEFAULT, // poziţia iniţiala pe axa xCW_USEDEFAULT, // poziţia iniţiala pe axa yCW_USE DEFAULT, // dimensiunea iniţiala pe axa xCW_USEDEFAULT, // dimensiunea iniţiala pe axa yNULL, // variabila handle a ferestrei părinteNULL, // variabila handle a meniuluihlnstance, // variabila handle a instanţei programuluiNULL) ; // parametri de creare

Fereastra creată de acest program este o fereastră normală suprapusă, cu o bară de titlu; în partea stângă a barei de titlu se află caseta cu meniul sistem; în partea dreaptă se află butoanele de mărire, de micşorare şi de închidere; fereastra are un chenar îngroşat, care permite redimensionarea. Acesta este stilul standard al ferestre lor, numit WS_OVERLAPPEDWINDOW; în funcţia CreateWindow îi corespunde comentariul „stilul ferestrei". „Titlul ferestrei" este textul afişat în bara de titlu.

Parametrii notaţi cu „poziţia iniţială pe axa x" şi „poziţia iniţială pe axa y" specifică poziţia iniţială a colţului din stânga-sus al ferestrei, relativ la colţul din stânga-sus al ecranului. Prin folosirea identificatorului CW_USEDEFAULT pentru aceşti para metri indicăm sistemului de operare să

Page 15: PW 66-80.docx

folosească valorile prestabilite pentru o fereastră suprapusă. Parametrii „dimensiunea iniţială pe axa x" şi „dimensiunea iniţială pe axa y" specifică dimensiunile iniţiale ale ferestrei. Identificatorul CW_USEDEFAULT indică sistemului de operare să folosească valorile prestabilite.

Parametrul indicat ca „variabilă handle a ferestrei părinte" are valoarea NULL, deoarece această fereastră nu are nici o fereastră părinte. Atunci când între două ferestre există o relaţie părinte-descendent, fereastra descendent este afişată întotdeauna pe suprafaţa ferestrei părinte. Parametrul indicat ca „variabilă handle a meniului" are tot valoarea NULL, deoarece fereastra nu are meniu. Parametrul indicat ca „variabilă handle a instanţei programului" are ca valoare variabila handle transmisă programului ca parametru la apelarea funcţiei WinMain. În sfârşit, „parametrul de creare" are valoarea NULL.

Funcţia Create Window returnează o variabilă handle a ferestrei create. Aceasta este salvată în variabila hwnd, definită ca fiind de tipul HWND (variabilă handle a unei ferestre). Orice fereastră din Windows are o variabilă handle. Programul foloseşte variabila handle pentru indicarea ferestrei. Dacă un program creează mai multe ferestre, fiecare are o variabilă handle diferită.

AFIŞAREA FERESTREIDupă executarea funcţiei CreateWindow, fereastra a fost creată de Windows, dar încă nu este

afişată pe ecran. Pentru aceasta mai sunt necesare încă două apeluri de funcţii. Primul este:ShowWindow (hwnd, iCmdShow) ;Primul parametru este o variabilă handle a ferestrei create de funcţia CreateWindow. Al doilea

parametru este variabila iCmdShow, transmisă funcţiei WinMain. Dacă iCmdShow este SW_SHOWNORMAL (egal cu 1), fereastra este afişată normal. Dacă iCmdShow este SW_SHOWMINNOACTIVE (egal cu 7), atunci fereastra nu este afişată, dar numele şi pictograma acesteia apar pe bara de taskuri.

Apelul:UpdateWindow (hwnd) ;determină redesenarea zonei client. Acest lucru se face prin trimiterea către procedura de

fereastră a unui mesaj WM_PAINT.

81. CONSTRUIREA INTERFEŢEI UTILIZATOR. Ferestre. ControaleFerestreSpaţiul Forms ne oferă clase specializate pentru: creare de ferestre sau formulare (System.Windows.Forms.Form), elemente specifice (controale) cum ar fi butoane (System.Windows.Forms.Button), casete de text (System.Windows.Forms.TextBox) etc.Proiectarea unei ferestre are la bază un cod complex, generat automat pe măsură ce noi desemnăm componentele şi comportamentul acesteia. În fapt, acest cod realizează: derivarea unei clase proprii din System.Windows.Forms.Form, clasă care este înzestrată cu o colecţie de controale (iniţial vidă). Constructorul ferestrei realizează instanţieri ale claselor Button, MenuStrip,Timer etc. (orice plasăm noi în fereastră) şi adaugă referinţele acestor obiecte la colecţia de controale ale ferestrei. Dacă modelul de fereastră reprezintă ferestra principală a aplicaţiei, atunci ea este instanţiată automat în programul principal (metoda Main). Dacă nu, trebuie să scriem noi codul care realizează instanţierea. Clasele derivate din Form moştenesc o serie de proprietăţi care determină atributele vizuale ale ferestrei (stilul marginilor, culoare de fundal, etc.), metode care implementează anumite comportamente (Show, Hide, Focus etc.) şi o serie de metode specifice (handlere) de tratare a evenimentelor (Load, Click etc.). O fereastră poate fi activată cu form.Show() sau cu form.ShowDialog(), metoda a doua permiţând ca revenirea în fereastra din care a fost activat noul formular să se facă numai după ce noul formular a fost închis (spunem că formularul nou este deschis modal). Un propietar este o fereastră care contribuie la comportarea formularului deţinut. Activarea propietarului unui formular deschis modal va determina activarea formularului deschis modal. Când un nou formular este activat folosind form.Show() nu va avea nici un deţinător, acesta stabilinduse direct : Formularul deschis modal va avea un proprietar setat pe null. Deţinătorul se poate stabilisetând proprietarul înainte să apelăm Form.ShowDialog() sau apelând From.ShowDialog() cu proprietarul ca argument.Vizibilitatea unui formular poate fi setată folosind metodele Hide sau Show. Pentru a ascunde un formular putem folosi :this.Hide(); // setarea propietatii Visible indirect sau StartPosition determină poziţia ferestrei atunci când aceasta apare prima dată. Poziţia poate fi setată Manual, sau poate fi centrată pe desktop (CenterScreen), stabilită de Windows, formularul având dimensiunile şi locaţia stabilite de programator (WindowsDefaultLocation) sau Windows-ul va stabili dimensiunea iniţială şi locaţia pentru formular (WindowsDefaultBounds) sau, centrat pe formularul care l-a afişat (CenterParent) atunci când formularul va fi afişat modal. Location (X,Y) reprezintă coordonatele colţului din stânga sus al formularului relativ la colţul stânga sus al containerului. (Această propietate e ignorată dacă StartPosition = Manual). Mişcarea formularului ( şi implicit schimbarea locaţiei) poate fi tratată în evenimentele Move şi LocationChanged . Locaţia formularului poate fi stabilită relativ la desktop astfel: Size (Width şi Height) reprezintă dimensiunea ferestrei. Când se schimbă

Page 16: PW 66-80.docx

propietăţile Width şi Height ale unui formular, acesta se va redimensiona automat, această redimensionare fiind tratată în evenimentele Resize sau in SizeChanged. Chiar dacă propietatea Size a formularului indică dimensiunea ferestrei, formularul nu este în totalitate responsabil pentru desenarea întregului conţinut al său. Partea care este desenată de formular mai este denumită şi Client Area. Marginile, titlul şi scrollbar-ul sunt desenate de Windows. MaxinumSize şi MinimumSize sunt utilizate pentru a restricţiona dimensiunile unui formular. ControlBox precizează dacă fereastra conţine sau nu un icon, butonul de închidere al ferestrei şi meniul System (Restore,Move,Size,Maximize,Minimize,Close). HelpButton-precizează dacă butonul va apărea sau nu lângă butonul de închidere al formularului (doar dacă MaximizeBox=false, MinimizeBox=false). Dacă utilizatorul apasă acest buton şi apoi apasă oriunde pe formular va apărea evenimentul HelpRequested (F1). Icon reprezintă un obiect de tip *.ico folosit ca icon pentru formular. MaximizeBox şi MinimizeBox precizează dacă fereastra are sau nu butonul Maximize şi respectiv Minimize Opacity indică procentul de opacitate ShowInTaskbar precizează dacă fereastra apare in TaskBar atunci când formularul este minimizat. SizeGripStyle specifică tipul pentru ‘Size Grip’ (Auto, Show, Hide). Size grip (în colţul din dreapta jos) indică faptul că această fereastră poate fi redimensionată. TopMost precizează dacă fereastra este afisată în faţa tuturor celorlalte ferestre. TransparencyKey identifică o culoare care va deveni transparentă pe formă. Definirea unei funcţii de tratare a unui eveniment asociat controlului se realizează prin selectarea grupului Events din ferestra Properties a controlului respectiv şi alegerea evenimentului dorit. Dacă nu scriem nici un nume pentru funcţia de tratare, ci efectuăm dublu clic în căsuţa respectivă, se generează automat un nume pentru această funcţie, ţinând cont de numele controlului şi de numele evenimentului (de exemplu button1_Click). Dacă în Designer efectuăm dublu clic pe un control, se va genera automat o funcţie de tratare pentru evenimentul implicit asociat controlului (pentru un buton evenimentul implicit este Clic, pentru TextBox este TextChanged, pentru un formular Load etc.). Printre evenimentele cele mai des utilizate, se numără : Load apare când formularul este pentru prima data încărcat în memorie. FormClosed apare când formularul este închis. FormClosing apare când formularul se va inchide ca rezultat al acţiunii utilizatorului asupra butonului Close (Dacă se setează CancelEventArgs.Cancel =True atunci se va opri închidereaformularului). Activated apare pentru formularul activ. Deactivate apare atunci când utilizatorul va da clic pe alt formular al aplicatiei.

ControaleUnitatea de bază a unei interfeţe Windows o reprezintă un control. Acesta poate fi „găzduit” de un container ce poate fi un formular sau un alt control. Un control este o instanţă a unei clase derivate din System.Windows.Forms şi este reponsabil cu desenarea unei părţi din container. Visual Studio .NET vine cu o serie de controale standard, disponibile în Toolbox. Aceste controale pot fi grupate astfel: Controale form. Controlul form este un container. Scopul său este de a găzdui alte controale. Folosind proprietăţile, metodele şi evenimentele unui formular, putem personaliza programul nostru. În tabelul de mai jos veţi găsi o listă cu controalele cel mai des folosite şi cu descrierea lor. Exemple de folosire a acestor controale vor urma după explicarea proprietăţilor comune al controalelor şi formularelor.

Button Sunt folosite pentru a executa o secvenţă de instrucţiuni în momentul activării lor de către utilizatorcalendar MonthCalendar Afişează implicit un mic calendar al lunii curente. Acesta poate fi derulat şi înainte şi înapoi la celelalte luni calendaristice.casetă de validare CheckBox Oferă utilizatorului opţiunile : da/nu sau include/excludeetichetă Label Sunt folosite pentru afişarea etichetelor de text, şi a pentru a eticheta controalele.casetă cu listă ListBox Afişează o listă de articole din care utilizatorul poate alege.imagine PictureBox Este folosit pentru adăugarea imaginilor sau a altor resurse de tip bitmap.pointer Pointer Este utilizat pentru selectarea, mutarea sau redimensionarea unui control.buton radio RadioButton Este folosit pentru ca utilizatorul să selecteze un singur element dint-un grup de selecţii.casetă de text TextBox Este utilizat pentru afişarea textului generat de o aplicaţie sau pentru a primi datele introduse de la tastatură de către utilizator.

82. Proprietăţi comune ale controalelor şi formularelor. Metode şi evenimente.

Proprietatea Text Această proprietate poate fi setată în timpul proiectării din fereastra Properties, sau programatic, introducând o declaraţie în codul programului.

Page 17: PW 66-80.docx

Proprietăţile ForeColor şi BackColor. Prima proprietate enunţată setează culoare textului din formular, iar cea de a doua setează culoarea formularului. Toate acestea le puteţi modifica după preferinţe din fereastra Properties. Proprietatea AutoSize folosită la controalele Label şi Picture, decide dacă un control este redimensionat automat, pentru a-i cuprinde întreg conţinutul. Proprietatea Enabled determină dacă un control este sau nu activat într-un formular. Proprietatea Visible setează vizibilitatea controlului. Proprietatea Width and Height permite setarea înălţimii şi a lăţimii controlului.

Metode şi evenimenteUn eveniment este un mesaj trimis de un obiect atunci când are loc o anumită acţiune. Această actiune poate fi: interacţiunea cu utilizatorul (mouse click) sau interacţiunea cu alte entităţi de program. Un eveniment (event) poate fi apăsarea unui buton, o selecţie de meniu, trecerea unui anumit interval de timp, pe scurt, orice ce se intamplă în sistem şi trebuie să primească un raspuns din partea programului. Evenimentele sunt proprietăţi ale clasei care le publică. Cuvantul-cheie event contolează cum sunt accesate aceste proprietăţi.

Metodele Show() şi Close(). Evenimentul ClickMetoda Dispose()Metodele Clear() şi Add()Metoda ShowDialog()

83. Obiecte grafice. Validarea informaţiilor de la utilizator. MessageBox. Interfaţă definită de către utilizator.

Spaţiul System.Drawing conţine tipuri care permit realizarea unor desene 2D şi au rol deosebit în proiectarea interfeţelor grafice.Un obiect de tip Point este reprezentat prin coordonatele unui punct într-un spaţiul bidimensionalPutem construi un obiect de tip Point pentru a redimensiona un alt obiect.Structura Color conţine date, tipuri şi metode utile în lucrul cu culori. Fiind un tip valoare (struct) şi nu o clasă, aceasta conţine date şi metode, însă nu permite instanţiere, constructori, destructor, moştenire.

Înainte ca informaţiile de la utilizator să fie preluate şi transmise către alte clase, este necesar să fie validate. Acest aspect este important, pentru a preveni posibilele erori. Astfel, dacă utilizatorul introduce o valoare reală (float) când aplicaţia aşteaptă un întreg (int), este posibil ca aceasta să se comporte neprevăzut abia câteva secunde mai târziu, şi după multe apeluri de metode, fiind foarte greu de identificat cauza primară a problemei.

Datele pot fi validate pe măsură ce sunt introduse, asociind o prelucrare unuia dintre handlerele asociate evenimentelor la nivel de control (Leave, Textchanged, MouseUp etc.)În unele situaţii (de exemplu atunci când valorile introduse trebuie să se afle într-o anumită relaţie între ele), validarea se face la sfârşitul introducerii tuturor datelor la nivelul unui buton final sau la închiderea ferestrei de date.

MessageBox este o clasă din spaţiul de nume System.Windows.Forms, derivată din clasa Object Show este o metodă statică din clasa MessageBox În momentul în care se apasă butonul OK, fereastra cu acest mesaj se închide, metoda Show cedând controlul.Metoda Show are mai multe forme în clasa MessageBox, fiind supradefinită. Apelul acestei funcţii se va face în funcţie de parametri. Să considerăm acum apelul funcţiei Show cu doi parametri: al doilea parametru se va referi la textul care apare pe bara de titlu în fereastră de mesaje:

Sunt multe aplicaţii în care, poate, dorim să ne realizăm o interfaţă proprie, ca formă, în locul celei dreptunghiulare propusă de Visual C#. În primul rând trebuie să ne desenăm propria fereastră de viitoare aplicaţii. Pentru aceasta vom folosi, de exemplu, aplicaţia Paint.Desenăm o figură geometrică care va constitui viitoarea noastră fereastră. Presupunem că dorim ca fereastra să aibă forma de oval. Colorăm ovalul cu o culoare dorită, iar pentru fundal alegem orice culoare, reţinând codul ei RGB Salvăm desenul cu extensia gif: oval.gif Să trecem acum la Visual C#. Alegem: File | New Project | Windows Forms Application, iar ca nume InterfataUtilizator Aduc controlul PictureBox. Din PictureBox Task aleg imaginea care să apară: oval.jpg iar la Size Mode aleg StretchImage astfel încât imaginea să fie toată în PictureBox Deformez PictureBox-ul astfel încât ovalul desenat să ocupe o suprafaţă care să corespundă esteticii programatorului