Examen Pw

  • Uploaded by: DorinRotaru
  • 0
  • 0
  • January 2021
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Examen Pw as PDF for free.

More details

  • Words: 32,926
  • Pages: 71
Loading documents preview...
1. ISTORIA WINDOWS. CE ADUCE NOU WINDOWS. Conceptele şi fundamentele GUI. Consecvenţa privind interfaţă cu utilizatorul. Avantajul oferit de multitasking. Gestionarea memoriei. Interfaţa grafică independentă de dispozitiv Crearea sistemului de operare Windows a fost anunţată de Microsoft Corporation în noiembrie 1983, şi doi ani mai târziu, în noiembrie 1985, a fost lansată versiunea Windows 1.0. Versiunile lansate în următorii doi ani au fost actualizate şi adaptate pentru piaţa internaţională, furnizând noi drivere pentru alte plăci video şi inprimante. Sistemul de operare Windows oferă avantaje semnificative faţă de mediul MS-DOS, atât pentru utilizatori, cât şi pentru programatori. Multe dintre aceste avantaje sunt comune pentru utilizatori şi pentru programatori, deoarece sarcina dezvoltatorilor unui program este să ofere utilizatorilor lucruri de care aceştia au nevoie. Windows 95 face posibil acest lucru. Windows este o interfaţă grafică cu utilizatorul (GUI - graphical user interface), numită uneori şi „interfaţă vizuală" sau „mediu grafic cu ferestre"Toate tipurile de interfeţe grafice cu utilizatorul folosesc elemente grafice afişate într-o imagine de tip bitmap. Elementele grafice asigură o utilizare mai eficientă a spaţiului de afişare, un mediu bogat din punct de vedere vizual pentru transferul de informaţii şi posibilitatea de afişare a rezultatelor aşa cum vor arăta în realitate pe hârtie Windows reprezintă un SO complet , integrat pe 32 biţi şi care se distinge prin: •

facilităţi de conectare în reţea;



facilităţi de protected-mode;



facilităţi de multitasking şi multithreading;

AVANTAJUL OFERIT DE MULTITASKING Prin multitasking noi putem intelege executarea simultana a mai multor taskuri.Traducerea corecta spune doar ca se executa mai multe taskuri fara a se specifica simultaneitatea lor. Avantajul multitaskingului ar fi ca el ne permite sa executam mai multe operatii de care avem nevoie in acelasi timp, de aceea noi putem sa ne permitem comutarea rapida de la un context la altul . Gestionarea memoriei Un sistem de operare nu poate să implementeze multitaskingul fără o gestionare adecvată a memoriei. Pe măsură ce noi programe sunt încărcate în memorie şi altele vechi îşi încheie execuţia, memoria se poate fragmenta. Sistemul de operare trebuie să aibă posibilitatea să consolideze memoria liberă. Pentru aceasta, sistemul trebuie să poată muta blocuri de cod şi de date în memorie. Gestiunea memoriei are rolul de a decide cum trebuie organizată informaţia pe cele două nivele şi cand trebuie transferată informaţia între acestea; tehnicile de gestiune a lucrărilor (multiprogramare, multitasking, time-sharing,etc) implică existenţa unor metode eficiente pentru gestiunea memoriei: tehnici de alocare dinamică şi memoria virtuală.Gestionarea memoriei trebuie sã asigure urmãtoarele funcţii: -organizarea informaţiilor în memoria internã (gestionarea informaţiilor); -evidenţa ocupãrii memoriei interne; -organizarea schimbului de informaţii între memoria internã şi memoria externã (gestionarea schimbului de informaţii);

asigurarea protecţiei informaţiilor memorate în memoria internã (protecţia memoriei). Interfaţa grafică independentă de dispozitiv Interfata utilizator grafica (Graphical User Interface - GUI) permite utilizatorului sa comunice cu aplicatia, folosind în acest scop obiecte grafice de pe ecran: ferestre, butoane, casete de validare, meniuri etc. Actionarea asupra acestora se face folosind tastatura sau dispozitive de intrare speciale, dintre care cel mai raspândit este mouse-ul. 2 Apelurile de funcţii. Arhitectura bazată pe mesaje. Procedura de fereastră. WinMain şi WndProc. Windows 95 asigură suportul pentru mai mult de o mie de apeluri de funcţii pe care le pot folosi aplicaţiile. Toate funcţiile Windows importante sunt declarate în fişiere antet. Principalul fişier antet se numeşte WINDOWS.H şi include multe alte fişiere antet. Aceste fişiere antet sunt furnizate de orice mediu de programare pentru Windows 95, aşa cum este, de pildă, C. Fişierele antet sunt o parte importantă a documentaţiei Windows. În programele pentru Windows folosiţi apelurile de funcţii la fel cum folosiţi funcţiile de bibiotecă C, cum ar fi strlen. Principala diferenţă este faptul că în cazul funcţiilor C codul funcţiilor este legat direct de codul programului, pe când codul funcţiilor Windows este stocat în fişiere din afara programului, numite biblioteci cu legături dinamice Apelurile de funcţii Windows Un program standard apelează nu mai puţin de 17 funcţii Windows. Aceste funcţii, împreună cu o scurtă descriere, sunt prezentate în continuare, în ordinea apariţiei în program:  LoadIcon - încarcă o pictogramă care urmează să fie folosită de un program.  LoadCursor - încarcă un indicator pentru mouse, care urmează să fie folosit de un program.  GetStockObject - obţine un obiect grafic (în acest caz o pensulă folosită pentru desenarea fondului ferestrei).  RegisterClassEx - înregistrează o clasă de fereastră pentru fereastra programului.  CreateWindow - creează o fereastră pe baza unei clase de fereastră.  ShowWindow - afişează o fereastră pe ecran.  UpdateWindow - cere unei ferestre să se redeseneze.  GetMessage - preia un mesaj din coada de mesaje.  TranslateMessage - converteşte unele dintre mesajele de la tastatură.  DispatchMessage - trimite un mesaj către o procedură de fereastră.  PlaySound - redă un fişier de sunet.  BeginPaint - iniţiază o operaţie de desenare a ferestrei.  GetClientRect - obţine dimensiunile zonei client a ferestrei.  DrawText - afişează un text.  EndPaint - încheie o operaţie de desenare.  PostQuitMessage - inserează un mesaj de încheiere în coada de aşteptare.  DefWindowProc - execută operaţiile prestabilite de prelucrare a mesajelor. Arhitectura bazată pe mesaje În Windows, atunci când utilizatorul redimensionează o fereastră, sistemul de operare trimite programului un mesaj prin care îi comunică noile dimensiuni ale ferestrei. Programul poate apoi să modifice conţinutul ferestrei, astfel încât acesta să se adapteze la noile dimensiuni. „sistemul de operare trimite programului un mesaj" - adica Windows apelează o funcţie din program. Parametrii acestei funcţii descriu mesajul respectiv. Această funcţie din programul Windows este cunoscută sub numele de „procedură de fereastră" („window procedure").

Procedura de fereastră Orice fereastră creată de un program are asociată o procedură de fereastră. Procedura de fereastră este e funcţie care se poate afla chiar în program sau într-o bibliotecă cu legături dinamice (DLL). Windows trimite un mesaj către o fereastră prin apelarea procedurii de fereastră. Procedura de fereastră prelucrează anumite informaţii pe baza mesajului primit, apoi returnează controlul sistemului de operare. WinMain şi WndProc Funcţia WndProc returnează o valoare LRESULT, definit ca un număr de tip LONG. Funcţia WinMain este de tipul WINAPI, iar funcţia WndProc este de tipul CALLBACK. Ambii identificatori sunt definiţi ca __stdcall, care defineşte o secvenţă specială de apelare pentru apelurile de funcţii dintre Windows şi aplicaţii. WndProc - trateaza mesajele care vin de la sistemul de operare.Ea mai determina continutul care va fi afisat in zona client al ferestrei si modul cum fereastra va raspunde la ceea ce va face utilizatorul.Deasemenea aceasta functie dupa ce se apeleaza functia BeginPaint , invoca rutina GetClientRect. WndProc- este o procedura de fereastra a ferestrei create de programul Hello.... iar o procedura de fereastra nu reprezinta altceva decit un mod de incapsulare a codului care raspunde intrarilor si afiseaza elementele grafice pe ecran. Funcţia WinMain reprezintă punctul de intrare în program. Aceasta este echivalentul funcţiei main din programele scrise în limbajul C. Orice program pentru Windows trebuie să aibă o funcţie WinMain.

3. Atributele contextului de dispozitiv. Salvarea contextului de dispozitiv. Funcţiile LineTo, Polyline şi PolylineTo, PolyPolyline, Arc, PolyBezier şi PolyBezierTo, Rectangle, Ellipse, RoundRect, Chord şi Pie. a) Contextul de dispozitiv (prescurtat DC - device context) - este o structură de date întreţinută intern de interfaţa GDI. Fiecare context de dispozitiv este asociat unui anumit dispozitiv de afişare, cum ar fi imprimanta, plotterul sau monitorul video.O parte dintre valorile din contextul de dispozitiv sunt atribute grafice. Aceste atribute definesc unele particularităţi privind modul de lucru al unor funcţii de desenare din interfaţa GDI. În cazul funcţiei TextOut, de exemplu, atributele contextului de dispozitiv determină culoarea textului, culoarea fondului, modul de mapare a coordonatelor x şi y în zona client a ferestrei şi fontul folosit de Windows pentru afişarea textului. Atributele contextului de dispozitiv controlează caracteristicile textului afişat. De exemplu, unul dintre atributele contextului de dispozitiv stabileşte culoarea textului. Culoarea prestabilită este negru. De asemenea, contextul prestabilit de dispozitiv stabileşte ca fondul să fie alb. Atunci când un program afişează un text pe ecran, Windows foloseşte această culoare de fond ca să umple spaţiul dreptunghiular care înconjoară fiecare caracter, spaţiu numit „casetă caracter" („character box") b)Salvarea contextului de dispozitiv - Variabila handle a contextului de dispozitiv este eliberata de functia BeginPaint. In general aceasta este salvata intr-o variabila numita hdc. In procedura de fereastra se defineste aceasta variabila astfel : HDC hdc; Tipul de date HDC este definit ca un întreg fără semn, pe 32 de biţi. Apelul funcţiei EndPaint eliberează variabila handle a contextului de dispozitiv. c)Functiile : Windows poate să deseneze linii drepte, linii eliptice (linii curbe, pe circumferinţa unei elipse) şi curbe Bezier. Cele şapte funcţii acceptate de Windows 95 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

Functia Polyline – foloseste ca punct de plecare pozitia curenta, si stabileste ca pozitie curenta sfirsitul ultimei linii desenate. Funcţia LineTo este una dintre puţinele funcţii GDI care nu are nevoie de dimensiunile complete ale obiectului ce urmează să fie desenat. Funcţia LineTo desenează o linie de la „poziţia curentă" definită în contextul de dispozitiv pană la punctul specificat la apelarea funcţiei (exclusiv acest punct). Poziţia curentă este folosită ca punct de plecare şi de alte funcţii GDI. Dacă apelaţi funcţia LineTo fără să stabiliţi mai întâi poziţia curentă, funcţia desenează o linie pornind din colţul din stânga-sus al zonei client. Dacă doriţi să desenaţi o linie din punctul (xStart, yStart) pană în punctul (xEnd, yEnd) trebuie să apelaţi mai întâi funcţia MoveToEx ca să stabiliţi ca poziţie curentă punctul (xStart, ySfart): (MoveToEx (hdc, xStart, yStart, &pt) ;) LineTo (hdc, cxClient, cyClient) ; Rectangle(hdc,xLeft,yTop,xRight,yBottom)(desenarea unui dreptunghi) Ellipse (hdc, xLeft, yTop, xRight, yBottom) ;( ne permite desenarea elipsei) RoundRect (hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse) ; (Funcţia pentru desenarea unui dreptunghi cu colţurile rotunjite ) Functiile PolyBezier si PoluBezierTo se folosesc pentru trasarea uneia sau a mai multor curbe Bezier conexe: PolyBezier (hdc, pt, iCount) ; sau instrucţiunea: PolyBezierTo (hide, pt, iCount) ; În ambele cazuri, pt este o matrice de structuri POINT. Pentru funcţia PolyBezier primele patru puncte specifică (în această ordine) punctul de început, primul punct de control, al doilea punct de control şi punctul final al curbei Bezier. Următoarele curbe Bezier au nevoie doar de trei puncte, deoarece punctul de început al următoarei curbe Bezier este punctul de sfârşit al primei curbe, şi aşa mai departe. Parametrul iCount reprezintă numărul de puncte din matrice, adică unu plus de trei ori numărul curbelor pe care vreţi să le desenaţi. Funcţia PolyBezierTo foloseşte poziţia curentă ca punct de început pentru prima curbă Bezier. Fiecare curbă desenată are nevoie doar de trei puncte. La returnarea funcţiei, poziţia curentă este punctul final al ultimei curbe desenate. funcţiile Rectangle, Ellipse, RoundRect, Chord şi Pie nu sunt tocmai nişte funcţii de desenare a liniilor. Desigur, ele desenează şi linii, dar şi colorează zona închisă, cu pensula curentă de colorare a suprafeţelor. În mod prestabilit, această pensulă are culoarea albă, aşa că s-ar putea ca operaţia să nu fie atât de evidentă atunci când încercaţi pentru prima dată să utilizaţi aceste funcţii. Deşi, în sens strict, funcţiile aparţin unei alte secţiuni din capitolul de faţă, „Desenarea suprafeţelor pline", Funcţiile Arc, Chord şi Pie primesc aceiaşi parametri: 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) ;

În cazul funcţiei Chord, Windows uneşte capetele arcului, iar în cazul funcţiei Pie, uneşte capetele arcului cu centrul elipsei PolyPolyline (mai multe linii poligonale),

4 BAZELE UTILIZARII CRONOMETRULUI Cronometrul Windows este un dispozitiv de intrare, ce comunică periodic unei aplicaţii trecerea unui anumit interval de timp. Cronomestrul este mult mai util decât credeţi, şi nu numai pentru programele care afişează ora, aşa cum este ceasul afişat de Windows pe bara de taskuri. Iată câteva alte utilizări sub Windows ale cronometrului, deşi s-ar putea ca unele să nu fie atât de evidente: ■

Multitaskingul - Deşi Windows 95 este un mediu cu multitasking controlat, uneori este mult mai eficient ca un program să returneze controlul sistemului de operare, imediat ce este posibil. Dacă programul trebuie să execute o operaţie de durată, o poate împărţi în operaţii mai mici, pe care să le prelucreze la primirea unui mesaj WMJTIMER. (Vom discuta mai multe despre acest subiect în Capitolul 14.)



Actualizarea unui raport de stare - Un program poate să utilizeze cronometrul pentru afişarea „în timp real" a unor informaţii care se schimbă continuu, în funcţie de resursele sistemului sau de evoluţia unei anumite operaţii.



Implementarea unei caracteristici de „autosalvare" - Cronometrul poate să „amintească" unui program Windows să salveze pe hard-disc documentul la care lucrează utilizatorul, după trecerea unui anumit interval de timp.



Închiderea versiunilor demonstrative ale unui program - Unele versiuni demonstrative ale programelor sunt proiectate astfel încât să-şi încheie execuţia, de exemplu, după trecerea a 30 de minute de la lansare. Cronometrul poate să semnaleze unei astfel de aplicaţii terminarea timpului permis de rulare.



Deplasări succesive - Obiectele grafice dintr-un joc sau imaginile afişate succesiv de un program de instruire asistată de calculator trebuie să fie prelucrate la anumite intervale de timp. Folosirea cronometrului elimină inconsecvenţele care pot apărea datorită diferenţelor dintre viteza de lucru a microprocesoarelor.

Multimedia - Programele pentru redarea CD-urilor audio, a sunetelor sau a secvenţelor muzicale sunt rulate de multe ori în fundal. Un program poate să utilizeze cronometrul pentru a determina cât a fost redat din secvenţa audio şi a actualiza corespunzător informaţiile vizuale afişate

5 Care este punctul de intrare într-un program Windows Funcţia WinMain reprezintă punctul de intrare în program. Aceasta este echivalentul funcţiei main din programele scrise în limbajul C. Orice program pentru Windows trebuie să aibă o funcţie WinMain 6 CE ADUCE NOU SISTEMUL DE OPERARE WINDOWS Sistemul de operare Windows oferă avantaje semnificative faţă de mediul MS-DOS, atât pentru utilizatori, cât şi pentru programatori. Multe dintre aceste avantaje sunt comune pentru utilizatori şi pentru programatori, deoarece sarcina dezvoltatorilor unui program este să ofere utilizatorilor lucruri de care aceştia au nevoie. Windows 95 face posibil acest lucru.

7.Ce este notatia ungara ? notaţia ungară", o convenţie de denumire a variabilelor intitulată astfel în onoarea legendarului programator de la Microsoft, Charles Simonyi. 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". Şi ultimii doi parametri ai funcţiei WndProc respectă notaţia ungară, deşi, aşa cum am arătat mai devreme, wParam ar fi trebuit să se numească uiParam (de la „unsigned integer"). Totuşi, deoarece aceşti doi parametri se definesc folosind tipurile de date WPARAM şi LPARAM, am păstrat denumirile originale.

8 Ce este o variabilă handle şi care este destinaţia ei? Variabila handle – este de obicei un nr pe 32 biti, care face trimitere la un obiect. 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.

9 Ce este programare controlată de evenimente? Programarea orientată eveniment este o paradigmă a programării calculatoarelor. Spre deosebire de programele tradiționale, care-și urmează propria execuție, schimbându-și câteodata doar cursul în puncte de ramificație (instrucțiuni test, etc), cursul execuției unui program orientat eveniment este condus în mare parte de evenimente externe. Programele orientate eveniment sunt formate de obicei dintr-un număr de programe mici numite handlere de eveniment, care sunt apelate ca răspuns la evenimente externe și dintr-un coordonator (dispatcher), care apelează handlerele de evenimente, folosind de obicei o coadă a evenimentelor, care să rețină evenimentele care nu au fost procesate. În multe cazuri, handlerele de evenimente pot declanșa ele însele evenimente, ducând la o cascadă de evenimente. Programarea orientată eveniment accentuează ca virtuți flexibilitatea și asincronicitatea. Programele cu interfețe grafice sunt de obicei programate într-o modalitate gestionată de evenimente. Sistemele de operare sunt un alt exemplu clasic de programe dirijate de evenimente pe cel puțin două nivele. La cel mai de jos nivel, handlerele de întreruperi se comportă ca handlere de evenimente hardware, cu procesorul în rol de coordonator (dispatcher). Sistemele de operare, de asemenea se comportă ca și coordonatori pentru procese, transmițând datele și întreruperile soft către procese user, care de multe ori sunt programate ca și handlere de eveniment.

10. Ce este un device context Device Context – structura de date intretinuta intern de interfata GDI.O parte din valorile din DC sunt atributele grafice , ce definesc careva particularitati referitor la modul de lucru a unor functii de desenare din interfata GDI.

11 Ce este multitaskingul controlat? Prin multitasking noi putem intelege executarea simultana a mai multor taskuri.In versiunile anterioare ale Windowsului era folosit multitaskingul necontrolat, ceea ce insemna ca nu se folosea ceasul sistemului ca sa se aloce timpi de procesare a diferitor programe ce rulau in sistem. Multitaskingul controlat insa permite aceasta alocare a timpilor de procesare , ceea ce inseamna ca programele cedeaza voluntar controlul , astfel incit alte programe sa isi poate si ele continua executia.In Windows 95 multitaskingul este controlat si programele se pot imparti in mai multe fire de executie, care par sa ruleze in acelasi timp.

12 Ce facem dacă cronometrul nu este accesibil? Cronometrul Windows este un dispozitiv de intrare, ce comunică periodic unei aplicaţii trecerea unui anumit interval de timp. Programul specifică sistemului de operare acest interval de timp, spunându-i ceva de genul: „Fă-mi un semn la fiecare 10 secunde". Windows trimite periodic programului, mesaje WM_TIMER prin care îi semnalează trecerea intervalului de timp respectiv. Dacă nu este disponibil nici un cronometru, funcţia SetTimer returnează valoarea NULL. S-ar putea ca programul să funcţioneze la fel de bine şi fără un cronometru, dar dacă într-adevăr aveţi nevoie de un cronometru ,aplicaţia nu are altă soluţie decât să-şi încheie execuţia. Dacă apelaţi funcţia SetTimer din WinMain, puteţi să închideţi programul ieşind din funcţia WinMain cu valoarea de returnare FALSE. Să presupunem că aveţi nevoie de un cronometru cu durata de 1000 ms. După apelarea funcţiei CreateWindow, dar înainte de intrarea în ciclul de tratare a mesajelor, puteţi să includeţi următoarea instrucţiune:

if (!SetTimer (hwnd, 1, 1000, NULL)) return FALSE ; Acesta este un mod neprietenos de închidere a unui program. Secvenţa de cod din exemplul următor afişează o casetă de mesaje atunci când funcţia SetTimer nu poate aloca programului un cronometru: if (!SetTimer (hwnd, 1, 1000, NULL)) { MessageBox (hwnd, "Too many clocks or timers!", "Program Name", MB_ICONEXCLAMATION ] MB_OK); return FALSE ; }

13 Ce prezintă procedura unei ferestre? Orice fereastră creată de un program are asociată o procedură de fereastră. Procedura de fereastră este e funcţie care se poate afla chiar în program sau într-o bibliotecă cu legături dinamice (DLL). Windows trimite un mesaj către o fereastră prin apelarea procedurii de fereastră. Procedura de fereastră prelucrează anumite informaţii pe baza mesajului primit, apoi returnează controlul sistemului de operare. Procedura de fereastra- mai este si un mod de incapsulare a codului care raspunde intrarilor(de la tastatura/mouse) si afiseaza elementele grafice pe ecran,facind acest lucru prin prelucrarea mesajelor trimise catre fereastra.

14.

Clasa butoanelor

Clasa butoanelor este o clasă predefinită ce permite crearea controalelor de tip ferestre descendent sub formă de butoane. Existenţa clasei într-unul dintre fişierele Windows permite crearea butoanelor direct prin apelarea funcţiei CreateWindow, nefiind necesară inregistrarea clasei de fereastră. Clasa butoanelor are o procedură de fereastră (aflată într-una dintre bibliotecile cu legături dinamice ale sistemului de operare) care prelucrează mesajele trimise către ferestrele butoanelor, ceea ce determină ca toate butoanele să reacţioneze într-un mod similar la anumite acţiuni ale utilizatorului(de ex: schimbarea culorii în cazul apasării). Procedura ferestrei buton din Windows execută întreţinerea acestor butoane şi toate operaţiile de redesenare. Sistemul de operare este responsabil de interpretarea click-urilor de mouse, redesenarea butonului sau de modul în care butonul se mişcă atunci când este apăsat. Sarcina programatorului este să intercepteze mesajul WM_COMMAND acesta este modul în care butonul informează procedura ferestrei despre declanşarea unui eveniment.

15.Coduri virtuale de taste. Starea tastelor de modificare. Utilizarea mesajelor de acţionare a tastelor. Fiecare tastă este identificată de un număr numit cod virtual. Acest cod virtual este conţinut în parametrul wParam al mesajelor WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, WM_SYSKEYDOWN. Cel mai des utiizate coduri virtuale sunt definite în fişierele antet din windows, având un nume sepcific precedat de prefixul VK- virtual key. De exemplu: VK_SHIFT, VK_CONTROL şi VK_RETURN sunt codurile virtuale corespunzătoare tastelor Shift, Ctrl şi Enter ale tastaturii. Starea tastelor de modificare (Shift, Alt, Ctrl) poate fi obţinută cu ajutorul funcţiei GetKeyState. De exemplu: GetKeyState (VK_SHIFT) returnează o valoare negativă (adică un număr în care primul bit are valoarea 1) dacă tasta Shift este apăsată. Valoarea returnată de apelul: GetKeyState (VK_CAPITAL) are un 1 în bitul cel mai puţin semnificativ dacă tasta Caps Lock este activă. Funcţia GetKeyState nu verifică starea tastaturii în timp real, ci starea tastaturii până în momentul mesajului curent. Pentru a obţine starea curentă a unei taste, se foloseşte funcţia GetAsyncKeyState.

Utilizarea mesajelor de acţionare a tastelor: În principiu, este necesar ca în scrierea unui program windows să se ţină cont numai de mesajele WM_KEYDOWN şi WM_KEYUP, întrucât mesajele WM_SYSKEYUP, WM_SYSKEYDOWN sunt folosite pentru funcţii de sistem (deci nu este necesară interceptarea lor). Mai mult, dacă sunt prelucrate mesajele WM_KEYDOWN, pot fi ignorate mesajele WM_KEYUP. Programele pentru Windows folosesc mesajele WM_KEYDOWN pentru tastele care nu generează caractere. Folosirea mesajelor pentru acţionări de taste în combinaţie cu informaţiile despre tastele de modificare (furnizate de funcţia GetKeyState) cu scopul de a le transforma în mesaje pentru caractere, poate genera probleme din cauza diferenţelor între tastaturile internaţionale. Mesajele WM_KEYDOWN sunt utile pentru tastele de deplasare, tastele funcţionale şi tastele speciale, precum Insert, Delete. Uneori tastele Insert, Delete si tastele funcţionale sunt folosite ca acceleratori pentru comenzi de meniu. Deoarece Windows transformă acceleratorii în comenzi de meniu, nu este nevoie să prelucraţi în program mesajele pentru acţionarea tastelor de accelerare. De cele mai multe, mesajele WM_KEYDOWN sunt prelucrate numai pentru tastele de deplasare a cursorului. Unele funcţii Windows folosesc de multe ori tastele de deplasare în combinaţie cu tasta Shift pentru extinderea unei selecţii - de exemplu într-un procesor de texte. Tasta Ctrl este folosită deseori pentru a schimba semnificaţia unei taste de deplasare. De exemplu, tasta Ctrl în combinaţie cu săgeata spre dreapta mută cursorul cu un cuvânt la dreapta.

16.Crearea ferestrelor child. Fereastra descendent prelucrează mesajele primite de la mouse şi de la tastatură şi înştiinţează fereastra părinte atunci când starea proprie se modifică. În acest fel, fereastra descendent devine un dispozitiv de introducere a datelor pentru fereastra părinte. Fereastra descendent încapsulează funcţionalităţi specifice legate de modul de afişare pe ecran, răspunde de datele introduse de utilizator şi metodele de înştiinţare a unei alte ferestre în momentul producerii unui eveniment important. Deşi pot fi create propriile controale de tip fereastră descendent, este mai uşor de a beneficia de avantajele oferite de un set de clase de fereastră (şi proceduri specifice) predefinite, clase pe care programele pot să le folosească pentru crearea unor controale de tip fereastră descendent standard: butoane, casete de validare, casetede editare, casete listă, casete combinate, bare de derulare. Fiecare fereastră descendent este creată printr-un apel al funcţiei CreateWindow. Poziţia şi dimensiunea pot fi modificate apelând funcţia MoveWindow . Când este folosit unul dintre controalele predefinite, nu este necesară înregistrarea unei clase pentru fereastra descendent. Clasa există deja în Windows şi are unul dintre aceste nume: „button", „static", „scrollbar", „edit", „listbox" sau „combobox". Unul din aceste nume este utilizat ca parametru al funcţiei CreateWindow. Parametrul de stil (style) al funcţiei CreateWindow defineşte mai precis aspectul şi funcţionalitatea controlului de tip fereastră descendent. Sistemul de operare Windows conţine deja procedurile de fereastră pentru prelucrarea mesajelor către fereastra descendent pe baza acestor clase. Procedura ferestrei părinte trimite mesaje către controlul de tip fereastră descendent, iar acesta trimite mesaje către procedura ferestrei părinte. După apelarea funcţiei CreateWindow nu mai trebuie să facem nimic în legătură cu aceste ferestre descendent. Procedura ferestrei buton din Windows execută întreţinerea acestor butoane şi toate operaţiile de redesenareLa terminarea programului, Windows distruge toate ferestrele descendent odată cu distrugerea ferestrei părinte.

17. Cum poate fi obţinută variabila handle a unui device context? Există mai multe metode de obţinere a variabilei handle de dispozitiv. Prima metodă este legată de tratarea mesajelor WM_PAINT, şi anume, prin apelul funcţiilor BeginPaint şi EndPaint: case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; [apelarea unor funcţii GDI] EndPaint (hwnd, &ps) ; return 0 ; Aceste funcţii au nevoie de variabila handle a ferestrei (transmisă procedurii de fereastră ca parametru) şi de adresa unei variabile de tipul PAINTSTRUCT. În timpul prelucrării mesajului WM_PAINT, procedura de fereastră apelează mai întâi funcţia BeginPaint ca să completeze câmpurile structurii ps. Valoarea returnată de funcţia BeginPaint este variabila handle a contextului de dispozitiv. În general, aceasta este salvată într-o variabilă numită hdc de tipul HDC. Tipul de date HDC este definit ca un întreg fără semn, pe 32 de biţi. Apelul funcţiei EndPaint eliberează variabila handle a contextului de dispozitiv. O altă metodă de obţinere a variabilei handle a contextului de dispozitiv, utlizată in afara prelucrarii mesajelor WM_PAINT este apelul la funcţia GetDC. Funcţia ReleaseDC eliberează variabila atunci când nu mai este necesară:

hdc = GetDC(hwnd) ; [apelarea unor funcţii GDI] ReleaseDC(hwnd, hdc) ; La fel ca funcţiile BeginPaint şi EndPaint, şi funcţiile GetDC şi ReleaseDC ar trebui apelate în pereche, în timpul prelucrării aceluiaşi mesaj. Diferenţa dintre cele două metode de obţinere a variabilei hdc este că variabila handle returnată de funcţia GetDC se referă la un dreptunghi cu întreaga zonă client a ferestrei, şi nu doar la un dreptunghi invalid. Spre deosebire de funcţia BeginPaint, GetDC nu validează nici o regiune invalidă. Un program Windows poate să obţină şi o variabilă handle a unui context de dispozitiv care se aplică întregii ferestre, nu numai zonei client a ferestrei: hdc = GetWindowDC (hwnd); [alte linii de program] ReleaseDC (hwnd, hdc); Contextul de dispozitiv include, în afară de zona client, bara de titlu a ferestrei, barele de derulare şi chenarul Funcţiile BeginPaint, GetDC şi GetWindowDC obţin variabila handle a contextului de dispozitiv asociat unei anumite ferestre de pe ecran. O funcţie mai generală pentru obţinerea variabilei handle a unui context de dispozitiv este CreateDC:

hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData); [alte linii de program] DeleteDC (hdc); Pentru a obţine o variabila handle a contextului de dispozitiv pentru tot spaţiul de afişare, se utilizează următorul apel: hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);

18.

Curbe Bezier. Funcţia PolyBezierTo.

Curbele Bezier îşi datorează numele inginerului Pierre Bezier, angajat al companiei de automobile Renault, care a elaborat un set de formule necesare proiectării la calculator a caroseriilor. De atunci, datorită formei bidimensionale, curba Bezier s-a dovedit a fi cea mai utilă curbă pentru grafica pe calculator. 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 acţionează ca nişte „magneţi" care deformează linia dreaptă dintre cele două puncte finale. Funcţiile Bezier sunt considerate utile pentru proiectarea asistată de calculator, datorită câtorva caracteristici: În primul rând, cu puţină practică, de obicei puteţi să manipulaţi curba până ajunge la o formă apropiată de cea dorită. În al doilea rând, curbele Bezier sunt foarte uşor de controlat. În unele variante ale funcţiilor spline, curba nu trece prin nici unul din punctele care o definesc. Curbele Bezier, însă, sunt întotdeauna ancorate în cele două puncte finale. (Aceasta este una dintre ipotezele de la care porneşte calculul formulei Bezier.) De asemenea, unele forme ale funcţiilor spline au puncte de singularitate, din care curba se întinde la infinit. În proiectarea asistată de calculator acest lucru este de cele mai multe ori evitat. Ca urmare, curbele Bezier sunt întotdeauna limitate de un patrulater (numit „carcasă convexă" - „convex hull") format prin unirea punctelor finale şi a punctelor de control. În al treilea rând, o altă caracteristică a curbelor Bezier implică relaţiile dintre punctele finale şi punctele de control. Curba este întotdeauna tangentă la linia trasată de la primul punct final la primul punct de control şi are întotdeauna aceeaşi direcţie cu această linie. (Această caracteristică este ilustrată vizual de programul BEZIER.) De asemenea, curba este întotdeauna tangentă la linia trasată de la al doilea punct final la al doilea punct de control şi are întotdeauna aceeaşi direcţie cu această linie. (Acestea sunt alte două ipoteze de la care este derivată formula Bezier.) În al patrulea rând, curbele Bezier sunt satisfăcătoare şi din punct de vedere estetic. Pentru trasarea mai multor curbe Bezier conexe, se ulizează instrucţiunea: PolyBezierTo (hdc,pt, iCount) , unde pt este o matrice de structuri POINT. Parametrul iCount reprezintă numărul de puncte din matrice, adică unu plus de trei ori numărul curbelor pe care vreţi să le desenaţi. Funcţia PolyBezierTo foloseşte poziţia curentă ca punct de început pentru prima curbă Bezier. Fiecare curbă desenată are nevoie doar de trei puncte. La returnarea funcţiei, poziţia curentă este punctul final al ultimei curbe desenate.

19.

Cursorul de editare (CARET). Funcţii pentru cursorul de editare. Soluţia Unicode pentru Windows.

Atunci când se introduce text într-un program, poziţia în care va apărea următorul caracter este indicată de o liniuţă de subliniere sau de un mic dreptunghi, în Windows pentru acest semn se foloseşte termenul „cursor de editare".

Funcţii pentru cursorul de editare Există cinci funcţii principale pentru cursorul de editare:  CreateCaret - creează un cursor de editare asociat unei ferestre.  SetCaretPos - stabileşte poziţia cursorului de editare în fereastră.  ShowCaret - afişează cursorul de editare.  HideCaret - maschează cursorul de editare.  DestroyCaret - distruge cursorul de editare creat. Mai există şi alte funcţii pentru obţinerea poziţiei cursorului de editare (GetCaretPos) şi pentru stabilirea şi obţinerea intervalelor de licărire a acestuia (SetCaretBlinkTime şi GetCaretBlinkTime). Cursorul de editare este, de obicei, o linie ori un bloc orizontal de dimensiunea unui caracter, sau o linie verticală. Linia verticală este recomandată în cazul folosirii unui font proportional, cum ar fi fontul sistem prestabilit din Windows. Deoarece caracterele din fonturile proporţionale nu au aceeaşi lăţime, linia sau blocul orizontal nu poate avea lăţimea exactă a unui caracter. Cursorul de editare nu poate fi creat pur şi simplu în timpul prelucrării mesajului WM_CREATE şi nici distrus în timpul prelucrării mesajului WM_DESTROY. El este ceea ce se numeşte o „resursă de sistem". Aceasta înseamnă că în sistem există un singur cursor de editare. De fapt, atunci când un program trebuie să afişeze un cursor de editare în fereastra proprie, el „împrumută" acest semn de la sistem. Cursorul de editare este afişat în fereastra care deţine cursorul de intrare (input focus). La un moment dat, o singură fereastră poate deţine cursorul de intrare, aşa că existenţa unui singur cursor de editare este logică. Un program poate determina dacă deţine cursorul de intrare prin prelucrarea mesajelor WM_SETFOCUS şi WM_KILLFOCUS. O procedură de fereastră recepţionează un mesaj WM_SETFOCUS atunci când primeşte cursorul de intrare şi un mesaj WM_KILLFOCUS atunci când pierde cursorul de intrare. Aceste mesaje sunt transmise în pereche. O procedură de fereastră primeşte întotdeauna un mesaj WM_SETFOCUS înainte de a primi un mesaj WM_KILLFOCUS şi întotdeauna va primi un număr egal de mesaje WM_SETFOCUS şi WM_KILLFOCUS pană la distrugerea ferestrei. Principala regulă de folosire a cursorului de editare este simplă. O procedură de fereastră apelează funcţia CreateCaret în timpul prelucrării mesajului WM_SETFOCUS şi funcţia DestroyCaret în timpul prelucrării mesajului WM_KILLFOCUS. Există şi alte câteva reguli: la creare, cursorul de editare nu este afişat. După apelarea funcţiei CreateCaret, programul trebuie să apeleze funcţia ShowCaret pentru a face vizibil cursorul de editare. În plus, procedura de fereastră trebuie să-l mascheze, apelând funcţia HideCaret, ori de câte ori desenează ceva pe ecran în timpul prelucrării unui alt mesaj decât WM_PAINT. După terminarea operaţiei de desenare, programul apelează funcţia ShowCaret ca să afişeze din nou cursorul de editare. Efectul funcţiei HideCaret este aditiv: dacă s+a apelat funcţia HideCaret de mai multe ori fără a fi apelată funcţia ShowCaret, atunci când se doreşte ca acest cursor de editare să devină din nou vizibil,este necesar apelul funcţiei ShowCaret de tot atâtea ori de cate ori s-a apelat şi funcţia HideCaret.

20.

Desenarea suprafeţelor pline. Funcţia Polygon şi modul de umplere a poligoanelor. Funcţia SetPolyFillMode. Umplerea suprafeţelor interioare. Pentru desenarea suprafeţe pline sunt utilizate 7 funcţii windows: Funcţie

Figura

Rectangle

Dreptunghi cu colţuri drepte

Ellipse

Elipsă

RoundRect

Dreptunghi cu colţuri rotunjite

Chord

Arc pe circumferinţa unei elipse, având capetele unite printr-o coardă

Pie Polygon PolyPolygon

Suprafaţă de forma unei felii de plăcintă, reprezentând un segment de elipsă. Figură geometrică având mai multe laturi Mai multe figuri geometrice cu mai multe laturi

Windows desenează conturul figurilor folosind peniţa curentă selectată în contextul de dispozitiv şi umple interiorul lor cu pensula curentă. În mod prestabilit, aceasta este pensula de stoc WHITE_BRUSH, ceea ce înseamnă că interiorul figurilor va fi umplut cu alb. Windows defineşte şase pensule de stoc: WHITE_BRUSH, LTGRAY_BRUSH, GRAY_BRUSH, DKGRAY_BRUSH, BLACK_BRUSH şi NULL_BRUSH (sau HOLLOW_BRUSH). Windows defineşte tipul HBRUSH ca variabilă handle a unei pensule. Pentru a obţine variabila handle a unei pensulei de stoc se apelează funcţia GetStockObject:. hBrush = GetStoCkObject (GRAY_BRUSH) ; Odată selectată in contextual de dispozitiv cu ajutorul funcţiei SelectObject (hdc, hBrush) pensula respectivă va colora interiorul figurilor în gri. Pentru a desena o figură fără contur se utilizează peniţa NULL_PEN, şi , în mod similar, pentru a desena o figură fără contur se utlizează pensula NULL_BRUSH. Funcţia Polygon este utlizată pentru a desena diverse poligoane pe baza unui sistem de puncte. Ea are drept parametric variabila handle a contextului de dispozitiv, un pointer la o matrice de structure POINT, şi numărul de puncte din matrice: Polygon (hdc, pt, iCount) . Suprafaţa închisă de poligon este colorată folosind pensula curentă în două moduri: ALTERNATE sau WINDING . Modul prestabilit de umplere a poligoanelor este ALTERNATE, ceea ce înseamnă că Windows colorează numai suprafeţele închise la care se poate ajunge din exteriorul poligonului prin traversarea unui număr impar de laturi (1, 3, 5 şi aşa mai departe). Celelalte suprafeţe interioare nu sunt umplute. Modul WINDING de umplere, presupune colorarea tuturor suprafeţelor închise de polygon. Modul de umplere poate fi setat cu ajutorul funcţiei SetPolyFillMode: SetPolyFillMode (hdc, iMode) .

Umplerea suprafeţelor interioare Interiorul figurilor Rectangle, RoundRect, Ellipse, Chord, Pie, Polygon şi PollyPolygon este umplut cu pensula - numită uneori şi „model" („pattern") - selectată în contextul de dispozitiv. O pensulă este de fapt o imagine bitmap 8x8 repetată pe verticală şi pe orizontală, pentru umplerea unei suprafeţe. Windows conţine patru funcţii pentru crearea pensulelor logice:

66. hBrush = CreateSolidBrush (rgbColor) ; 67. hBrush = CreateHatchBrush (iHatchStyle, rgbColor) – crearea unei pensule “haşurată" cu linii orizontale, verticale sau oblice. 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. 68. hBrush = CreatePatternBrush (hBitmap) – crearea unei pensule proprii, bazată pe o imagine bitmap. 69. hBrush = CreateBrushIndirect (&logbrush) - funcţie care poate înlocui toate celelalte trei funcţii de creare a pensulelor. Variabila logbrush este o structură de tip LOGBRUSH („logical brush") cu 3 câmpuri: lbStyle (UINT),lbColor (COLORREF),lbHatch (LONG). Pentru a selecta pensula în contextul de dispozitiv se foloseşte funcţia SelectObject: SelectObject (hdc, hBrush) ;

O pensulă creată poate fi ştearsă cu ajutorul funcţiei DeleteObject: DeleteObject (hBrush) ;

Pentru a obţine informaţii despre o pensulă, se apelează funcţia GetObject: GetObject (hBrush, sizeof (LOGBRUSH), (LPVOID) &logbrush) ;

unde variabila logbrush este o structură de tip LOGBRUSH („logical brush").

21.

Dimensiunea unui caracter. Funcţia GetTextMetrics. Tipul TEXTMETRIC. Dimensiunile textului.

Dimensiunea unui caracter este necesară în cazul utilizării funcţiei TextOut pentru afişarea mai multor linii. Spaţiul dintre liniile succesive de text poate fi stabilit pe baza înălţimii unui caracter iar spaţiul dintre coloane pe baza lăţimii medii a caracterelor din font. Dimensiunile caracterelor sunt obţinute prin apelarea funcţiei GetTextMetrics. Funcţia GetTextMetrics are ca parametru o variabilă handle a contextului de dispozitiv, deoarece returnează informaţii despre fontul selectat în contextul de dispozitiv. Windows copiază valorile referitoare la dimensiunile caracterelor într-o structură de tip TEXTMETRIC. Valorile sunt exprimate în unităţi de măsură care depind de modul de mapare selectat în contextul de dispozitiv. În contextul prestabilit de dispozitiv, modul de mapare este MM_TEXT, aşa că dimensiunile sunt date în pixeli. Pentru folosirea funcţiei GetTextMetrics se defineşte mai întâi o variabilă de tipul TEXTMETRIC (numită, de obicei, tm): TEXTMETRIC

tm;

În continuare se obţine o variabilă handle a contextului de dispozitiv şi se apelează funcţia GetTextMetrics: hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm) ; ReleaseDC(hwnd, hdc); Astfel se obţine o structura cu infomţii despre dimensiunile textului, care pot fi salvate pentru utilizarea în viitor. Dimensiunile textului:

tmInternalLeading - spaţiul păstrat deasupra unui caracter pentru semnele de accentuare. tmExternalLeading - spaţiul recomandat pentru a fi lăsat între rândurile de text. tmAveCharWidth -lăţimea medie a literelor mici. tmMaxCharWidth -lăţimea celui mai mare caracter al fontului. Lăţimea medie a majusculelor poate fi obţinută calculând 150% din valoarea tmAveCharWidth.

22.

DIMENSIUNEA ZONEI CLIENT. Macroinstrucţiunile LOWORD şi HIWORD (LOWORD (lParam), HIWORD (lParam)). Barele de derulare. Domeniul şi poziţia unei bare de derulare.

Dimensiunea ferestrelor poate să varieze foarte mult: de la o valoare maximă în care zona client ocupă întregul ecran, cu excepţia barei de titlu a programului până la o valoare minimă în care zona client este de fapt eliminată. Dimensiunile totale ale ferestrei mărite pot fi obţinute prin apelarea funcţiei GetSystemMetrics cu parametrii SM_CXFULLSCREEN şi SM_CYFULLSCREEN. Pentru un monitor VGA valorile returnate sunt 640 şi 461 de pixeli. O metodă obişnuită de determinare a dimensiunilor zonei client a unei ferestre este prelucrarea mesajului WM_SIZE în procedura de fereastră. Windows trimite un mesaj WM_SIZE către procedura de fereastră, de fiecare dată când se modifică dimensiunile ferestrei. Parametrul lParam transmis procedurii de fereastră conţine lăţimea zonei client în cuvântul mai puţin semnificativ (LOWORD) şi înălţimea zonei client în cuvântul mai semnificativ (HIWORD). Codul pentru prelucrarea acestui mesaj arată astfel: static int cxClient, cyClient ; [alte linii de program] case WM_SIZE : cxClient = LOWORD (lParam) ;

cyClient = HIWORD (lParam) ; return 0 ;

Despachetarea parametrului lParam pentru obţinerea dimensiunilor zonei client se face cu ajutorul macroinstrucţiunilor LOWORD şi HIWORD, care sunt definite în fişierele antet din Windows. Barele de derulare se numără printre cele mai reuşite componente ale unei interfeţe grafice pentru mouse având funcţia de a permite vizualizarea informaţiei pentru care este nevoie de mai mult spaţiu decât este disponibil în zona client a ferestrei. Ele sunt poziţionate vertical (pentru deplasări în sus şi în jos) sau orizontal (pentru deplasări la stânga şi la dreapta). Bara de derulare este parcursă longitudinal de o „casetă de derulare" care indică poziţia aproximativă a părţii afişate pe ecran faţă de întregul document. Pentru a include în fereastra aplicaţiei o bară de derulare orizontală sau vertical este necesar de a include identificatorul WS_VSCROLL (derulare verticală) şi/sau WS_HSCROLL (derulare orizontală) în stilul de fereastră din apelul funcţiei CreateWindow. Barele de derulare sunt plasate întotdeauna la marginea de jos sau la cea din dreapta a ferestrei şi se întind pe toată lăţimea, respectiv înălţimea zonei client. Zona client nu include spaţiul ocupat de barele de derulare. Lăţimea unei bare de derulare verticale şi înălţimea uneia orizontale sunt constante pentru un driver de afişare dat..

Windows se ocupă de modul de utilizare a mouse-ului pentru barele de derulare, dar barele de derulare ale ferestrelor nu au o interfaţă automatizată cu tastatura. Domeniul şi poziţia unei bare de derulare

Fiecare bară de derulare are asociate un „domeniu" (definit printr-o pereche de numere întregi care reprezintă valorile maximă şi minimă) şi o „poziţie" (punctul în care se află caseta de derulare în domeniul asociat barei de derulare). Atunci când caseta de derulare se află la capătul de sus (sau la capătul din partea stângă) al barei de derulare, poziţia corespunde valorii minime. Capătul de jos (sau capătul din partea dreaptă) al barei de derulare reprezintă valoarea maximă. În mod prestabilit, domeniul unei bare de derulare este de la 0 (sus sau în stânga) la 100 (jos sau în dreapta) dar poate fi uşor modificat astfel încât să aibă o formă mai convenabilă pentru program: SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ; Parametrul iBar poate avea una dintre valorile SB_VERT şi SB_HORZ, iar iMin şi iMax sunt poziţiile minimă şi maximă din domeniu, în timp ce bRedraw trebuie să aibă valoarea TRUE pentru ca Windows să redeseneze bara de derulare pe baza noului domeniu stabilit. Poziţia casetei de derulare este reprezentată întotdeauna printr-o valoare întreagă. De exemplu, o bară de derulare cu domeniul cuprins între 0 şi 4 are cinci poziţii ale casetei de derulare. Pentru a stabili o nouă poziţie a casetei de derulare pe bara de derulare se utilizează funcţia SetScrollPos : SetScrollPos (hwnd, iBar, iPos, bRedraw) ; Parametrul iPos reprezintă noua poziţie, care trebuie să fie cuprinsă în domeniul delimitat de iMin şi iMax. Windows conţine funcţii asemănătoare (GetScrollRange şi GefScrollPos) pentru obţinerea domeniului şi a poziţiei unei bare de derulare.

23.

Elemente de bază despre mouse. Funcţia GetSystemMetrics (SM_MOUSEPRESENT); cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS). Parametrul SM_SWAPBUTTON. Zona senzitivă a indicatorului.

Windows 95 permite folosirea mouse-ului cu un buton, cu două butoane sau cu trei butoane, precum şi folosirea unui joystick sau a unui creion optic, pentru simularea unui mouse cu un buton. Totuşi, cel mai utlizat este mouse-ul cu trei butoane, devenit un standard de facto. Al doilea buton al mouse-ului este recomandat pentru apelarea „meniurilor de context" - meniuri care apar în fereastră în afara barei de meniu - sau pentru operaţii speciale de tragere. Pentru a determina dacă mouse-ul este prezent se foloseşte funcţia GetSystemMetrics având drept parametru identificatorul SM_MOUSEPRESENT: fMouse = GetSystemMetrics (SM_MOUSEPRESENT) ; Variabila fMouse va avea valoarea TRUE (diferită de zero) dacă mouse-ul este instalat. Pentru determinarea numărului de butoane ale mouse-ului instalat, folosiţi tot funcţia GetSystemMetrics: cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS) ; Această funcţie returnează valoarea 0 dacă mouse-ul nu este instalat. Utilizatorii care folosesc mâna stângă pot să inverseze butoanele mouse-ului folosind Panoul de control din Windows. O aplicaţie poate să determine dacă butoanele mouse-ului au fost inversate apelând funcţia GetSystemMetrics cu parametrul SM_SWAPBUTTON. Zona senzitivă a indicatorului. Atunci când utilizatorul deplasează mouse-ul, Windows deplasează pe ecran o mică imagine bitmap numită „indicator". Indicatorul are o „zonă senzitivă" cu dimensiunea de un pixel, care indică o poziţie precisă pe ecran. Driverul de afişare conţine câteva indicatoare de mouse predefinite, care pot fi folosite de programe. Indicatorul cel mai obişnuit este săgeata oblică definită în fişierele antet din Windows cu numele IDC_ARROW. Zona senzitivă a acestui indicator este vârful săgeţii. Indicatorul IDC_CROSS are zona senzitivă situată la celor două linii.

24.

Ferestre child de control şi culoare.

Ades, utilizarea unor aspecte implicite pentru crearea butoanelor duce la un design neclar sau mai putin atragător Pentru a îmbunătăţi aspectul acestor butoane trebuie ori să schimbăm culoarea zonei client, aşa încât aceasta să se asorteze cu fondul butoanelor, ori să schimbăm culoarea folosită pentru fondul butoanelor. Culorile de sistem pentru butoane: COLOR_BTNFACE este folosită pentru culoarea suprafeţei principale a butoanelor de apăsare şi pentru fondul celorlalte butoane. (De asemenea, aceasta este culoarea de sistem folosită pentru casete de dialog şi casete de mesaje.) COLOR_BTNSHADOW este folosită pentru sugerarea unei umbre la marginile din dreapta şi de jos ale butoanelor de apăsare, precum şi în interiorul pătratelor din casetele de validare şi a cercurilor din butoanele radio. COLOR_BTNTEXT- culoarea textului în cazul butoanelor de apăsare COLOR_WINDOWTEXT - culoarea textului pentru pentru celelalte butoane. În cazul afişării butoanelor pe suprafaţa zonei client, una dintre metodele de evitare a conflictelor între culori este folosirea culorilor de sistem. Pentru început, se foloseşte COLOR_BTNFACE la definirea clasei de fereastră pentru fondul zonei client:

wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1) ;

Atunci când variabila hbrBackground din structura WNDCLASSEX are o valoare, Windows înţelege că aceasta se referă la culoarea de sistem, nu la o variabilă handle. Atunci când sunt specificate în câmpul hbrBackground al structurii WNDCLASSEX, la aceste valori trebuie adăugat 1, pentru a se evita folosirea valorii NULL. Dacă în timpul rulării programului culoarea de sistem se schimbă, suprafaţa zonei client va fi invalidată şi Windows va folosi noua valoare pentru COLOR_BTNFACE. Pentru a rezolva problema cauzată de necorespondenţa dintre culoarea de sistem şi fondul din spatele textului în cazul funcţiei TextOut se vor utiliza funcţiile SetTextColor şi SetBkColor. Astfel, culorile pentru fond şi pentru text vor fi identice culorile de sistem. SetBkColor (hdc, GetSysColor (COLORBTNFACE)) ; SetTextColor (hdc, GetSysColor (COLOR_WINDOWTEXT)) ;

Acum, fondul zonei client, al textului şi culoarea textului se potrivesc cu culorile butoanelor. Mesajul WM_CTLCOLORBTN Modificarea culorilor butoanelor nu este o idee plauzibilă din punct de vedere practic. Apelul funcţiei SetSysColors cu scopul modificării aspectului butoanelor, va afecta toate programele care rulează în momentul respectiv sub Windows - o mişcare pe care utilizatorii nu o vor aprecia prea mult. O abordare mai potrivită (teoretic) este prelucrarea mesajului WM_CTLCOLORBTN. Acesta este un mesaj pe care controalele de tip buton îl trimit către procedura ferestrei părinte atunci când fereastra descendent este pe cale de a executa o redesenare. Fereastra părinte poate să folosească această ocazie ca să modifice culorile pe care procedura ferestrei descendent urmează să le folosească pentru desenare. Atunci când procedura părinte recepţionează mesajul WM_CTLCOLORBTN, parametrul wParam conţine variabila handle a contextului de dispozitiv al butonului, iar IParam este variabila handle a ferestrei butonului. Atunci când fereastra părinte primeşte acest mesaj, controlul de tip buton a obţinut deja contextul de dispozitiv. În timpul prelucrării mesajului WM_CTLCOLORBTN: ■

Se stabileşte (opţional) o culoare de text cu ajutorul funcţiei SetTextColor.



Se stabileşte (opţional) o culoare de fond cu ajutorul funcţiei SetBkColor.

■ Se returnează către fereastra descendent o variabilă de manipulare a pensulei cu care se va desena. Teoretic, fereastra descendent foloseşte pensula respectivă pentru colorarea fondului Totuşi, în legătură cu mesajul WM_CTLCOLORBTN este o problemă: acesta nu este trimis decât de butoanele de apăsare şi de butoanele desenate de proprietar; de asemenea, numai butoanele desenate de proprietar răspund la prelucrarea făcută mesajului de către fereastra părinte, folosind pensula trimisă pentru colorarea fondului. Oricum, acest lucru este inutil, deoarece fereastra părinte este răspunzătoare de desenarea acestor butoane.

25.

Ferestre child. Butoane definite de programator.

BS_OWNERDRAW Crearea unui buton cu stilul BS_OWNERDRAW oferă controlul complet asupra aspectului vizual al butonului. Majoritatea programelor care folosesc stilul BS_OWNERDRAW pentru desenarea butoanelor de proprietar folosesc mici imagini (bitmap) pentru identificarea acestor butoane. Un buton creat cu stilul BS_OWNERDRAW trimite ferestrei părinte un mesaj WM_DRAWITEM de fiecare dată când butonul trebuie să fie redesenat. Aceasta se întâmplă la crearea butonului, de fiecare dată când este apăsat sau eliberat, când obţine sau pierde cursorul de intrare şi în orice altă situaţie când trebuie să fie redesenat. în mesajul WM_DRAWITEM, parametrul IParam este un pointer către o structură de tip DRAWITEMSTRUCT. Această structură conţine informaţiile necesare programului pentru redesenarea butonului. Câmpurile din structură importante pentru lucrul cu butoane sunt hDC (contextul de dispozitiv al butonului), rcltem (o structură RECT în care este stocată dimensiunea butonului), CtllD (identificatorul ferestrei controlului) şi UemState (care indică dacă butonul este apăsat sau dacă deţine cursorul de intrare). Dacă butonul este apăsat, unul dintre biţii câmpului UemState din structura DRAWITEMSTRUCT are valoarea 1. Acest bit poate fi testat folosind constanta ODS_SELECTED. Dacă butonul deţine cursorul de intrare, atunci bitul ODS_FOCUS din câmpul UemState are valoarea 1. În cazul folosirii buroanelor desneate de proprietar, Windows obţine contextul de dispozitiv şi îl include în structura DRAWITEMSTRUCT. Este necesar ca la sfârşit contextul de dispozitiv să fie în aceeaşi stare ca la început, deci orice obiect GDI selectat în contextul de dispozitiv trebuie să fie deselectat.

26.

Ferestre child. Butoane şi input focus.

Butoanele de apăsare, butoanele radio şi butoanele desenate de proprietar primesc cursorul de intrare atunci când se execută clic pe acestea. Controlul indică faptul că deţine cursorul de intrare printr-o linie punctată care înconjoară textul. Atunci când o fereastră descendent primeşte cursorul de intrare, fereastra părinte îl pierde; toate intrările de la tastatură sunt direcţionate către control, nu către fereastra părinte. Totuşi, controalele de tip fereastră descendent răspund numai la apăsarea barei de spaţiu, care funcţionează în acest caz ca şi butonul mouse-ului. Cu alte cuvinte, programul a pierdut controlul asupra tastaturii. Atunci când sistemul de operare Windows mută cursorul de intrare de la o fereastră (cum ar fi fereastra părinte) la o altă fereastră (cum ar fi controlul de tip fereastră descendent), trimite mai întâi un mesaj WM_KILLFOCUS către fereastra care pierde cursorul de intrare. Parametrul wParam al mesajului este variabila handle a ferestrei care primeşte cursorul de intrare. Windows trimite apoi un mesaj WM_SETFOCUS către fereastra care primeşte cursorul de intrare. Parametrul wParam al mesajului este variabila de manipulare a ferestrei care pierde cursorul de intrare. (În ambele cazuri, wParam poate avea valoarea NULL, ceea ce arată că nici o fereastră nu primeşte sau nu pierde cursorul de intrare.) O fereastră părinte poate împiedica un control de tip fereastră descendent să primească cursorul de intrare prelucrând mesajul WM_KILLFOCUS. Să presupunem că matricea hwndCmd conţine variabilele handle ale tuturor ferestrelor descendent. (Aceste variabile au fost salvate în matrice în timpul apelării funcţiei CreateWindow pentru crearea ferestrelor descendent.) NUM este numărul ferestrelor descendent.

case WM_KILLFOCUS : for (i = 0 ; i < NUM ; 1++) if (hwndChild[i] == (HWND) wParam SetFocus (hwnd) ; break ; return 0 ; În această secvenţă de cod, atunci când fereastra părinte este avertizată că urmează să piardă cursorul de intrare în favoarea uneia dintre ferestrele descendent, apelează funcţia SetFocus ca să recâştige cursorul de intrare. Însă această prelucrare împiedică butoanele să răspundă la apăsarea barei de spaţiu, deoarece butoanele nu obţin niciodată cursorul de intrare. O soluţie mai bună ar fi permiterea butoanelor să obţină cursorul de intrare, şi, în acelaşi timp, permiterea utilizatorului să treacă de la un buton la altul cu ajutorul tastei Tab.

27.

Ferestre child. Butoane visibile şi accesibile.

Pentru recepţionarea intrărilor de la mouse şi de la tastatură, o fereastră descendent trebuie să fie vizibilă (afişată), dar şi activată. Atunci când o fereastră este vizibilă, dar nu este activată, textul acesteia este afişat cu gri, în loc de negru. Dacă parametrul WS_VISIBLE nu este inclus în clasa ferestrei la crearea ferestrei descendent, aceasta nu va fi afişată până când nu este apelată funcţia ShowWindow: ShowWindow (hwndChild, SW_SHOWNORMAL) ; Dacă parametrul WS_VISIBLE este inclus în clasa ferestrei, nu este necesar apelul funcţia ShowWindow. Totuşi, prin apelarea funcţiei ShowWindow poate fi mascată o fereastră descendent afişată: ShowWindow (hwndChild, SW_HIDE) ; Pentru a determina dacă o fereastră descendent este afişată se utilizază apelul: IsWindowVisible (hwndChild) ; În mod prestabilit, ferestrele descendent sunt activate. Pentru a le dezactiva se utilizează funcţia: EnableWindow (hwndChild, FALSE) ; Pentru controalele de tip buton, această acţiune are ca efect afişarea cu gri a textului din buton. Butonul nu mai răspunde la intrările de la mouse sau de la tastatură. Aceasta este cea mai bună metodă de a indica faptul că opţiunea reprezentată de un anumit buton nu este disponibilă. Pentru a reactiva o fereastră descendent se utilizează aceeaşi funcţie, dar având drept al doliea parametru valoarea TRUE: EnableWindow (hwndChild, TRUE) ; Pentru a determina dacă o fereastră descendent este activă sau nu se utilizează funcţia: IsWindowEnabled (hwndChild) ;

28.

Ferestre child. Check box.

Casetele de validare sunt dreptunghiuri etichetate cu un text; de obicei, textul apare în partea dreaptă a casetei de validare. (Dacă la crearea butonului este folosit stilul BS_LEFTTEXT, textul apare în stânga casetei de validare.) De obicei, casetele de validare sunt incluse în aplicaţii pentru a permite utilizatorilor să selecteze diferite opţiuni. Casetele de validare funcţionează ca un comutator: executarea unui clic într-o casetă de validare determină apariţia unui marcaj de validare; un al doilea clic face ca marcajul de validare să dispară. Cele mai cunoscute stiluri de casete de validare sunt BS_CHECKBOX şi BS_AUTOCHECKBOX. În cazul stilului BS_CHECKBOX, sarcina de aplicare a marcajului de validare revine programatorului, prin trimiterea unui mesaj BS_SETCHECK. Parametrul wParam trebuie să aibă valoarea 1 pentru afişarea marcajului de validare şi valoarea 0 pentru ştergerea acestuia. Pentru inversarea marcajului de validare la prelucrarea mesajului WM_COMMAND primit de la control poate fi utilizată instrucţiunea: SendMessage ((HWND) lParam, BM_SETCHECK, (WPARAM) SendMessage ((HWND) lParam, BM_GETCHECK, 0, 0), 0) ; Valoarea lParam este variabila handle a ferestrei descendent, transmisă către procedura ferestrei prin mesajul WM_COMMAND. Pentru a iniţializa o casetă de validare de tip BS_CHECKBOX cu un X, se utilizează aceeaşi funcţie cu parametrul BM_SETCHECK: SendMessage (hwndButton, BM_SETCHECK, 1, 0) ; În cazul folosirii stilului BS_AUTOCHECKBOX, controlul este cel care actualizează afişarea marcajului de validare. Procedura ferestrei părinte poate să ignore mesajele WM_COMMAND. Pentru a dtermina starea butonului, se transmite către acesta mesajul BM_GETCHECK: iCheck = (int) SendMessage (hwndButton, BM_GETCHECK, 0, 0) ; iCheck are valoarea TRUE (sau o valoare diferită de 0) dacă butonul este validat şi valoarea FALSE (sau 0) în caz contrar. Celelalte două stiluri de casete de validare sunt BS_3STATE şi BS_AUTO3STATE. Aşa cum indică şi numele lor, aceste stiluri permit afişarea unei stări terţe - culoarea gri din caseta de validare - în cazul în care se trimite către control un mesaj WM_SETCHECK cu parametrul wParam egal cu 2. Culoarea gri indică utilizatorului că opţiunea respectivă este nedeterminată sau irelevantă. În acest caz, caseta nu poate fi validată - cu alte cuvinte, este dezactivată. Totuşi, caseta de validare continuă să trimită mesaje către fereastra părinte atunci când se execută clic. Caseta de validare este aliniată la partea stângă a dreptunghiului şi este centrată între marginile de sus şi de jos ale acestuia, conform dimensiunilor specificate la apelarea funcţiei CreateWindow. Executarea unui clic oriunde în cadrul dreptunghiului determină trimiterea unui mesaj WM_COMMAND către fereastra părinte, înălţimea minimă a casetei de validare este egală cu înălţimea unui caracter. Lăţimea minimă este egală cu numărul de caractere din text, plus două.

29. Ferestre child. Clasa barelor de derulare 30. Ferestre child. Clasa de redactare. 31. Ferestre child. Clasa static 32. Ferestre child. Coduri de înștiințare Ferestrele descendent pot comunica cu ferestrele părinte în ambele sensuri. Ferestrele descendent generează mesaje WM_COMMAND, care le transmite ferestrei părinte. lParam conține variabila handle a ferestrei descendent, LOWORD (wParam) – conține identificatorul ferestrei descendent, HIWORD (wParam) – conține codul de înștiințare transmis ferestrei părinte. Exemplu de cod de înștiințare: BN_CLICKED (valoarea 0), BN_PUSHED (valoarea 2), etc.

33. Ferestre child. Colorarea barelor de derulare și a textului static. Colorarea barelor de derulare se face prin tratarea mesajelor WM_CTLCOLORSCROLLBAR. Ca răspuns la acest mesaj, fereastra părinte poate utiliza contextul de dispoztitv pentru a seta culoarea barei. De fapt tratarea acestui mesaj returnează variabila handle a pensulei utilizate pentru desenarea barei de derulare. În cazul textului static este tratat mesajul WM_CTLCOLORSTATIC, ulterior apelîndu-se funcțiile SetBkColor() - pentru fundal sau SetTextColor() – pentru text.

34. Ferestre child. Colorarea fondului. (*traducere din engleză – Petzold – BackGround Color)

În mod implicit, ferestrele descendent sunt desenate utilizînd pensula de culoare gri, pentru că butoanele au fost create pentru a fi utilizate în casetele de dialog, a căror fundal este de această culoare. Setarea culorii de fundal a ferestrei părinte se face în timpul setării parametrilor clasei ferestrei: wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH).

Pentru a adapta culoarea ferestrei descendent la culoarea fundalului ferestrei părinte vom fi nevoiți ori să schimbăm modalitatea de desenare a fundalului ferestrei părinte, ori să schimbăm culoarea ferestrei descendent. O modalitate de a înțelege cum aceasta se face este înțelegerea culorilor de sistem (întrebarea 35) (Petzold – Coloring the Background - ** cred că proful asta a avut în vedere)

În programul cu bare de derulare, care schimbă culoarea fundalului ferestrei părinte, culoarea de fundal este setată în felul următor: wndclass.hbrBackground = CreateSolidBrush (0) Atunci cînd este mutată bara de derulare, programul trebuie să creeze o nouă pensulă și să transmită variabila handle a pensulei structurii clasei de fereastră. Accesarea acestei variabile handle se face prin apel la funcția GetClassWord., iar setarea – prin SetClassWord. Atunci cînd oricare dintre bare își schimbă poziția, se șterge pensula folosită și se creează una nouă prin apel la funcția: SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush (RGB (color[0],color[1], color[2]))))

Cînd este necesară recolorarea fundalului se apelează InvalidateRect(), ceea ce determină plasarea în coadă a unui mesaj WM_PAINT. Astfel încît acesta este un mesaj de prioritate joasă, el nu va fi procesat atît timp cît se porcesează mesajele provenite de la barele de derulare. Putem corecta acest lucru prin apel implicit al funcției UpdateWindow(hWnd). Totuși UpdateWindow() poate frîna interpretarea tastelor mouse-ului și a tastaturii. Putem deci transmite tratarea mesajelor WM_PAINT funcției DefWindowProc(), ceea ce înseamnă ca programul nostru va trata doar un BeginPaint() și EndPaint() atunci cînd îi va fi trimis un mesaj WM_PAINT.

35. Ferestre child. Culori de sistem. SO Windows utilizează 29 de culori pentru a desena diferite componente arătate la ecran. Aceste 29 de culori pot fi accesate prin GetSysColor() și modificate prin SetSysColor(). Identificatorii definiți în fișierele header specifică culorile de sistem. **Setarea culorii de sistem prin SetSysColor() se face doar pentru sesiunea de Windows curentă.

Culorile de sistem (unele) pot fi modificate și din Control Panel. Culorile selectate sunt stocate în registru pentru WinNT și în fișierul WIN.INI pentru Win98. Atît în registru, cît și în fișierul WIN.INI, cuvintele cheie pentru culorile de sistem sunt diferite de identificatorii utilizați la apelurile funcțiilor GetSysColor() sau SetSysColor(). Exemplu: Identificatorul GetSysColor() sau SetSysColor() COLOR_SCROLLBAR Identificatorul din registru sau WIN.INI Scrollbar Culoarea standard RGB C0−C0−C0 Este utilizat pentru setarea culorii barelor de derulare. ** Progresul SO Windows a determinat utilizarea elementelor grafice mai sofisticate, incluzînd diferite elemente 3D, ceea ce a determinat mărirea numărului culorilor de sistem. Astfel, pentru versiunile mai recente de Windows, identificatorii culorilor pot să nu mai fie atît de expliciți: COLOR_SCROLLBAR  setează culoarea barelor de derulare.

36. Ferestre child. Interfața tastaturii Barele de derulare pot procesa acționările butoanelor de la tastatură. Astfel acționarea butoanelor Home, End, Page Up, Page Down generează diferite valori pentru parametrul wParam, în cazul mesajelor legate de barele de derulare: SB_TOP, SB_BOTTOM, SB_PAGEUP, SB_PAGEDOWN respectiv. Pentru a transmite input focus-ul barei de derulare atunci cînd este acționată cu mouse-ul, trebuie inclus identificatorul WS_TABSTOP atunci cînd se crează fereastra descendent prin CreateWindow(). Ulterior trebuie tratat mesajul WM_SETFOCUS, apelîndu-se funcția SetFocus (hwndScroll[idFocus]), unde hWndScroll este variabila handle a ferestrei descendent, iar idFocus o variabilă globală. Atribuirea input focus-ului barei de derulare determină utilizarea interfeței complete a tastaturii de către bara de derulare. Oricum, aceasta va ignora o bună parte din butoane, axîndu-se doar pe cele, care determină poziția cursorului.

37. Ferestre child. Introducerea unei proceduri de fereastră noi. Presupunem că avem situația: avem mai multe bare de derulare în zona client și este necesitatea de a transmite input focus-ul de la una la alta prin intermediul tastei Tab. Dificultatea o reprezintă faptul că o bară de derulare deja deține input focus-ul și ignoră apăsarea Tab-ului. Pentru a rezolva această problemă trebuie introdusă o nouă procedură de fereastră pentru fereastra descendent, care va trata anumite mesaje, de care avem nevoie și va transmite controlul procedurii de fereastră implicite. Setarea unei noi proceduri de fereastră se face prin apel la funcția SetWindowLong(). Astfel, pentru fiecare dintre barele de derulare prezente se apelează această funcție: OldScroll[i] = (WNDPROC) SetWindowLong (hwndScroll[i], GWL_WNDPROC,(LONG) ScrollProc))

În rezultat, ScrollProc va recepționa toate mesajele, pe care SO le trimite barelor de derulare în cadrul programului.

38. Ferestre child. Mesajul WM_CTLCOLORBTN. Astfel încît este posibil de a seta culoarea zonei client și a textului afișat, astfel încît culoarea acestora să coincidă cu culoarea butoanelor și a ferestrelor descendent. Apare întrebarea: este posibil de a adapta culoarea butoanelor la culorile pe care le preferăm? Teoretic – da, practic – nu, pentru că unica posibilitate de a o face este funcția SetSysColor(). Însă această funcție determină schimbarea tuturor culorilor în sistem ceea ce le-ar schimba în toate aplicațiile, care rulează curent în Windows. O altă modalitate (teoretic) mai bună este tratarea mesajelor WM_CTLCOLORBTN. Acest mesaj este trimis de către fereastra descendent atunci cînd aceasta își desenează zona client. Aici este cazul de a schimba culorile, pe care fereastra descendent le folosește pentru a colora fundalul: SetBkColor() sau pentru a scrie un text: SetTextColor(). Problema care apare este faptul că doar butoanele de tip Push sau cele desenate de utilizator trimit astfel de mesaj ferestrei părinte și doar butoanele owner-draw (desenate de utilizator) răspund la procesarea acestui mesaj de către fereastra părinte, ceea ce, de fapt, este inutil pentru că în final anume fereastra părinte este responsabilă de desenarea butoanelor.

39. Ferestre child. Radio buttons. Radio buton este o fereastră descendent, care, în grup, permit alegerea unor opțiuni, care se exclud reciproc. Arată ca o casetă de validare, numai că în loc de casetă este un cerculeț alb, care, în caz că este validat, este marcat de un cerculeț negru mai mic. Indicatorii utilizați pentru crearea unui buton radio: BS_RADIOBUTTON, BS_AUTORADIOBUTTON. Diferența între aceștia este faptul că pentru primul trebuie controlată manual marcarea lui, adică pentru a permite validarea acestuia trebuie apelată funcția SendMessage() cu parametrul BM_SETCHECK și wParam egal cu 1: SendMessage (hwndButton, BM_SETCHECK, 1, 0)

Auto-radio-butonul se validează automat la acționarea lui prin intermediul unui dispozitiv de intrare (mouse, tastatură). Stingerea butoanelor radio, adică interzicerea validării lor se face prin apel la funcția SendMessage (hwndButton, BM_SETCHECK, 0, 0), unde wParam este egal cu 0. **Diferența substanțială între o casetă de validare și buton radio este faptul că un buton radio nu poate fi invalidat prin apăsare repetată. El este asemănător cu butoanele cu ajutorul cărora se alege frecvența radio prestabilită din automobile: doar un buton poate fi acționat într-un moment de timp.

40. Ferestre child. Stilurile clasa de redactare Implicit o fereastră descendent de editare are doar o singură linie. ES_MULTILINE transformă fereastra de editare întruna cu mai multe linii. ES_AUTOVSCROLL automat derulează pe verticală textul scris, iar ES_AUTOHSCROLL – pe orizontală. Pentru adăugarea barelor de derulare în fereastra de editare, trebuie folosiți indicatorii barelor de derulare standard WS_HSCROLL, WS_VSCROLL. Atunci cînd este ales un text, el încetează să fie evidențiat cînd fereastra de editare pierde input-focus-ul. Pentru a preveni acest fapt trebuie folosit indicatorul ES_NOHIDESEL. Toți acești indicatori determină stilul ferestrei de editare.

41. Ferestre child. Utilizarea ferestrelor de redactare de control Atunci cînd se utilizează mai multe ferestre de editare, este necesar de a utiliza principiul windows subclassing pentru a semnala trecerea de la o fereastră de editare la alta, adică de a crea o procedură de fereastră specifică pentru fiecare fereastră de editare. O altă modalitate este interceptarea butoanelor Tab sau Shift-Tab. Există diverse mesaje pentru interacționarea cu textul introdus în caseta de editare. Toate aceste mesaje sunt trimise prin intermediul funcției SendMessage(), utilizînd indicatorul necesar WM_COPY, WM_CUT, etc. Se poate obține începutul șirului și sfîrșitul acestuia (SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iStart,(LPARAM) &iEnd)), poate fi înlocuit textul cu un alt șir (SendMessage (hwndEdit, EM_REPLACESEL, 0, (LPARAM) szString)) sau obținut numărul de linii (iCount = SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0) ;).

42.Ferestre. Culoarea butoanelor. O fereastra child (copil) este o fereastra care are setat stilul WS_CHILD si are urmatoarele proprietati:     

are o fereastra parent (parinte); sta intotdeauna in zona client a ferestrei parinte (nu poate fi afistata in afara); daca fereastra parinte este mutata, fereastra copil este mutata in acelas fel (pozitia ei relativa la zona client a parintelui nu se schimba); este distrusa atunci cand se distruge fereastra parinte. o fereastra child nu poate avea menu;

Pentru a crea o fereasta child, trebuie setat stilul WS_CHILD si pasat un handle la parinte in apelul functiei CreateWindow sau CreateWindowEx;

Colorarea butoanelor poate fi modificata doar teoretic, nu si in practica. Putem utiliza funcţia SetSysColors ca să modificam aspectul butoanelor. Aceasta va afecta toate programele care rulează în momentul respectiv sub Windows o mişcare pe care utilizatorii nu o vor aprecia prea mult. O abordare mai potrivită (din nou, teoretic) este prelucrarea mesajului WM_CTLCOLORBTN. Acesta este un mesaj pe care controalele de tip buton îl trimit către procedura ferestrei părinte atunci când fereastra descendent este pe cale de a executa o redesenare. Fereastra părinte poate să folosească această ocazie ca să modifice culorile pe care procedura ferestrei descendent urmează să le folosească pentru desenare. (In versiunile pe 16 biţi ale sistemului de operare Windows, un mesaj numit WM_CTLCOLOR era folosit pentru toate controalele. Acesta a fost înlocuit cu mesaje separate pentru fiecare tip standard de control.) Atunci când procedura părinte recepţionează mesajul WM_CTLCOLORBTN, parametrul wParam conţine variabila handle a contextului de dispozitiv al butonului, iar Iparam este variabila handle a ferestrei butonului. Atunci când fereastra părinte primeşte acest mesaj, controlul de tip buton a obţinut deja contextul de dispozitiv. În timpul prelucrării mesajului WM_CTLCOLORBTN: ■

Stabiliţi (opţional) o culoare de text cu ajutorul funcţiei SetTextColor.



Stabiliţi (opţional) o culoare de fond cu ajutorul funcţiei SetBkColor.



Returnaţi către fereastra descendent o variabilă de manipulare a pensulei cu care se va desena.

Teoretic, fereastra descendent foloseşte pensula respectivă pentru colorarea fondului. Este sarcina dumneavoastră să distrugeţi pensula atunci când aceasta nu mai este necesară. Totuşi, în legătură cu mesajul WM_CTLCOLORBTN este o problemă: acesta nu este trimis decât de butoanele de apăsare şi de butoanele desenate de proprietar; de asemenea, numai butoanele desenate de proprietar răspund la prelucrarea făcută mesajului de către fereastra părinte, folosind pensula trimisă pentru colorarea fondului. Oricum, acest lucru este inutil, deoarece fereastra părinte este răspunzătoare de desenarea acestor butoane. Dacă doriţi să aveţi controlul complet asupra aspectului vizual al butoanelor, dar nu vreţi să vă pierdeţi timpul cu logica de tratare a intrărilor de la mouse şi de la tastatură, creaţi un buton cu stilul BS_OWNERDRAW.

43.

Ferestrele child de control

Controalele de tip fereastră descendent sunt folosite de cele mai multe ori în casetele de dialog. Aşa cum veţi vedea în Capitolul 11, poziţia şi dimensiunea controalelor de tip fereastră descendent sunt definite într-un şablon al casetei de dialog, conţinut în fişierul de resurse al programului. Pentru crearea unei ferestre normale a aplicaţiei, definiţi mai întâi clasa ferestrei şi o înregistraţi în Windows cu ajutorul funcţiei RegisterClassEx. Pe baza acestei clase creaţi apoi fereastra cu ajutorul funcţiei CreateWindow. Totuşi, atunci când folosiţi unul dintre controalele predefinite, nu trebuie să înregistraţi o clasă pentru fereastra descendent. Clasa există deja în Windows şi are unul dintre aceste nume: „button", „static", „scrollbar", „edit", „listbox" sau „combobox". Nu trebuie decât să folosiţi unul dintre aceste nume ca parametru al funcţiei CreateWindow. Parametrul de stil (style) al funcţiei CreateWindow defineşte mai precis aspectul şi funcţionalitatea controlului de tip fereastră descendent. Sistemul de operare Windows conţine deja procedurile de fereastră pentru prelucrarea mesajelor către fereastra descendent pe baza acestor clase. Folosirea controalelor de tip fereastră descendent direct pe suprafaţa ferestrei implică executarea unor operaţii de nivel mai scăzut decât în cazul folosirii controalelor de tip fereastră descendent în casetele de dialog, deoarece gestionarul casetei de dialog inserează un nivel de izolare între program şi controale. Controalele de tip fereastră descendent pe care le creaţi pe suprafaţa ferestrei nu vă oferă însă posibilitatea de deplasare a cursorului de intrare de la un control la altul

cu ajutorul tastei Tab sau al tastelor de deplasare. Un control de tip fereastră descendent poate obţine cursorul de intrare, dar, după ce obţine acest cursor, nu îl va mai ceda ferestrei părinte.

44. Folosirea peniţelor de stoc. Crearea, selectarea şi ştergerea peniţelor. Funcţiile CreatePen, CreatePenIndirect, ExtCreatePen. Parametrii iPenStyle, iWidth, rgbColor. Iată o metodă pentru crearea, selectarea şi ştergerea peniţelor.Mai întâi definim variabilele pentru stocarea variabilelor handle ale stilurilor: static HPEN hPen;

În timpul prelucrării mesajului WM_CREATE, cream penita. hPen = CreatePen (PS_SOLID, 1, 0);

În timpul prelucrării mesajului WM_PAINT (sau în orice alt moment în care avem o variabilă handle validă a contextului de dispozitiv) putem să selectam oricare dintre peniţe în contextul de dispozitiv şi să desenam: SelectObject (hdc, hPen) ; [funcţii de desenare a liniilor]

În timpul prelucrării mesajului WM_DESTROY putem să ştergem peniţele create: DeleteObject (hPen) ;

Folosind funcţiile CreatePen sau CreatePenIndirect putem crea o „peniţă logică" (logical pen) care este doar o descriere a unei peniţe. Funcţiile CreatePen, CreatePenIndirect şi ExtCreatePen returnează o variabilă handle a peniţei logice create. Parametrul iPenStyle precizează dacă se desenează o linie continuă, o linie punctată sau una întreruptă. Pentru stilurile PS_SOLID, PS_NULL şi PS_INSIDEFRAME, parametrul iWidth reprezintă grosimea liniei. Dacă iWidth are valoarea 0, liniile desenate de Windows vor avea grosimea de un pixel. Dacă parametrul iWidth are o valoare mai mare de 1, Windows va desena o linie continuă. Parametrul rgbColor din funcţia CreatePen este un număr întreg fără semn reprezentând culoarea peniţei.

45.

Formatarea textului. Funcţia wsprintf. Funcţia GetSystemMetrics.

Deoarece dimensiunile fontului sistem nu se modifică în timpul unei sesiuni Windows, trebuie să apelam funcţia GetTextMetrics o singură dată după lansarea în execuţie a programului. Un loc potrivit pentru acest apel este codul de prelucrare a mesajului WM_CREATE din procedura de fereastră. Pentru a afisa mai multe linii de text avem nevoie să obţinem valorile pentru înălţimea şi lăţimea caracterelor. Acest lucru se poate realiza prin definirea a două variabile în care să salvam lăţimea medie (cxChar) şi înălţimea totală a caracterelor (cyChar): static int cxChar, cyChar ; Aceste variabile sunt declarate ca statice deoarece trebuie să fie valide atunci când procedura de fereastră prelucrează alte mesaje (cum ar fi WM_PAINT). Dacă variabilele sunt declarate ca globale în alte funcţii nu mai este necesar să fie declarate statice. Codul de prelucrare a mesajului WM_CREATE:

case WH_CREATE: hdc = GetDC (hwnd); GetTextMetrics (hdc, &tm); cxChar = tm.tmAveCharWidth; cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC (hwnd, hdc); return 0; Funcţia GetSystemMetrics returnează informaţii despre dimensiunea unor elemente grafice din Windows, cum ar fi pictograme, cursoare, bare de titlu şi bare de derulare. Aceste dimensiuni depind de placa video şi de driverul de afişare. Funcţia GetSystemMetrics acceptă un singur parametru, numit „index". Indexul este unul dintre cei 73 de identificatori de tip întreg definiţi în fişierele antet din Windows. GetSystemMetrics returnează o valoare întreagă care reprezintă, de obicei, dimensiunea elementului transmis ca parametru. Functiile wsprintf si sprintf permit afisarea numerelor formatate, cat si siruri simple de caractere. Dacă nu trebuie să afişam numere în virgulă mobilă, putem folosi funcţia wsprintf în locul funcţiei sprintf. Funcţia wsprintf are aceeaşi sintaxă ca şi funcţia sprintf, dar este inclusă în Windows, aşa că nu va mări dimensiunea fişierului executabil. Diferenta dintre printf si wsprintf este ca şirul de caractere formatat este stocat într-o matrice de caractere, si returnează lungimea şirului de caractere.

46. Funcţia GetDeviceCaps. Dimensiunea dispozitivului. Valorile HORZSIZE şi VERTSIZE, HORZRES şi VERTRES, ASPECTX, ASPECTY şi ASPECTXY, LOGPIXELSX şi LOGPIXELSY. Functia GetDviceCaps() furnizează informaţii despre posibilităţile contextului de dispozitiv. Avem nevoie de rezoluţia verticală (numărul de dots tipăribili de la începutul paginii până la sfârşitul ei), deci vom furniza ca parametru constanta VERTRES, în funcţia GetDeviceCaps(). Constanta HORZRES în aceeaşi funcţie ne furnizează rezoluţia orizontală. HORZSIZE - Lățimea, în milimetri, a ecranului fizic. VERTSIZE - Înălțimea, în milimetri, a ecranului fizic. ASPECTX - Lățimea relativă a unui pixel folosit pentru desenarea unei linii. ASPECTY - Înălțimea relativă a unui pixel folosit pentru desenarea unei linii. ASPECTXY- Lățime pe diagonală a pixelului folosit pentru desenarea unei linii. LOGPIXELSX - Numărul de pixeli pe inch logic de-a lungul lățimii ecranului. Într-un sistem cu mai multe monitoare de afișare, această valoare este aceeași pentru toate monitoarele. LOGPIXELSY - Numărul de pixeli pe inch logic de-a lungul înălțimii ecranului. Într-un sistem cu mai multe monitoare de afișare, această valoare este aceeași pentru toate monitoarele. GetDeviceCaps() acceptă un număr de 29 de constante diferite .

47.

Funcţia TextOut. Contextul de dispozitiv. Obţinerea unei variabile handle a contextului de dispozitiv:

Contextul de dispozitiv (prescurtat DC - device context) este o structură de date întreţinută intern de interfaţa GDI. Fiecare context de dispozitiv este asociat unui anumit dispozitiv de afişare, cum ar fi imprimanta, plotterul sau monitorul video. În cazul monitoarelor video, un context de dispozitiv este de obicei asociat unei anumite ferestre de pe ecran. Prima metoda de a obtine variabila handle este in timpul prelucrarii mesajelor WM_PAINT. Sunt implicate două funcţii: BeginPaint şi EndPaint. Aceste funcţii au nevoie de variabila handle a ferestrei (transmisă procedurii de fereastră ca parametru) şi de adresa unei variabile de tipul PAINTSTRUCT. De obicei, programatorii Windows numesc această variabilă ps şi o definesc în procedura de fereastră astfel: PAINTSTRUCT

ps;

În timpul prelucrării mesajului WM_PAINT, procedura de fereastră apelează mai întâi funcţia BeginPaint ca să completeze câmpurile structurii ps. Valoarea returnată de funcţia BeginPaint este variabila handle a contextului de dispozitiv. În general, aceasta este salvată într-o variabilă numită hdc. În prcedura de fereastră definiţi această variabilă astfel: HDC

hdc;

Tipul de date HDC este definit ca un întreg fără semn, pe 32 de biţi. Programul poate apoi să folosească funcţii GDI, cum ar fi TextOut. Apelul funcţiei EndPaint eliberează variabila handle a contextului de dispozitiv. În general, prelucrarea mesajului WM_PAINT se face astfel: case WM_PAINT : hdc = BeginPaint (hwnd, &ps) ; [apelarea unor funcţii GDI] EndPaint (hwnd, &ps) ; return 0 ;

Obţinerea unei variabile handle a contextului de dispozitiv: a doua metodă Puteţi să obţineţi o variabilă handle a unui context de dispozitiv şi în timpul prelucrării altor mesaje decât WM_PAINT, sau atunci când aveţi nevoie de variabila handle a contextului în alte scopuri, cum ar fi obţinerea unor informaţii despre contextul de dispozitiv. Apelaţi funcţia GetDC pentru a obţine variabila handle şi apoi apelaţi funcţia ReleaseDC atunci când nu mai aveţi nevoie de aceasta: hdc = GetDC(hwnd) ; [apelarea unor funcţii GDI] ReleaseDC(hwnd, hdc) ; La fel ca funcţiile BeginPaint şi EndPaint, şi funcţiile GetDC şi ReleaseDC ar trebui apelate în pereche. Atunci când apelaţi funcţia GetDC în timpul prelucrării unui mesaj, este recomandat să apelaţi funcţia ReleaseDC înainte de a ieşi din procedura de fereastră. Nu apelaţi funcţia GetDC ca răspuns la un mesaj şi funcţia ReleaseDC ca răspuns la un alt mesaj.

Spre deosebire de variabila handle a contextului de dispozitiv obţinută din structura PAINTSTRUCT, variabila handle returnată de funcţia GetDC se referă la un dreptunghi cu întreaga zonă client a ferestrei. Puteţi să desenaţi în orice parte a zonei client, nu doar în dreptunghiul invalid (dacă există un dreptunghi invalid). Spre deosebire de funcţia BeginPaint, GetDC nu validează nici o regiune invalidă. Funcţia TextOut afişează pe ecran un şir de caractere. Are forma : TextOut (hdc, x, y, psString, iLength) ; Primul parametru este o variabilă handle a contextului de dispozitiv - valoarea hdc returnată de funcţia GetDC sau valoarea hdc returnată de funcţia BeginPaint în timpul prelucrării mesajului WM_PAINT. Parametrul psString este un pointer la un şir de caractere, iar iLength este lungimea acestui şir de caractere, adică numărul de caractere conţinut de şir. Valorile x şi y din apelul funcţiei TextOut definesc începutul şirului de caractere în zona client a ferestrei. Valoarea x indică poziţia pe orizontală, iar valoarea y indică poziţia pe verticală.

48. Funcţiile SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw), SetScrollPos (hwnd, iBar, iPos, bRedraw). Funcţia de SetScrollRange stabileşte valorile minime si maxime pentru bara de defilare specificata. Are forma : SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ; Parametrul iBar poate avea una dintre valorile SB_VERT şi SB_HORZ, iar iMin şi iMax sunt poziţiile minimă şi maximă din domeniu, în timp ce bRedraw trebuie să aibă valoarea TRUE dacă vreţi ca Windows să redeseneze bara de derulare pe baza noului domeniu stabilit. Poziţia casetei de derulare este reprezentată întotdeauna printr-o valoare întreagă. De exemplu, o bară de derulare cu domeniul cuprins între 0 şi 4 are cinci poziţii ale casetei de derulare. 8. Puteţi să folosiţi funcţia SetScrollPos ca să stabiliţi o nouă poziţie a casetei de derulare pe bara de derulare: SetScrollPos (hwnd, iBar, iPos, bRedraw) ; Parametrul iPos reprezintă noua poziţie, care trebuie să fie cuprinsă în domeniul delimitat de iMin şi iMax. Windows conţine funcţii asemănătoare (GetScrollRange şi GefScrollPos) pentru obţinerea domeniului şi a poziţiei unei bare de derulare.

49.

Ignorarea tastaturii. Cursorul de intrare. Acţionări de taste şi caractere

Ignorarea tastaturii Deşi tastatura este principala sursă de intrări de la utilizatori a unui program pentru Windows, programele nu trebuie să reacţioneze la toate mesajele pe care le primeşte de la tastatură. Multe funcţii ale tastaturii sunt tratate chiar de Windows. De exemplu, puteţi să ignoraţi apăsările de taste legate de funcţii sistem. Acestea sunt, în general, combinaţii cu tasta Alt. Programul nu este obligat să monitorizeze aceste taste, deoarece Windows îi comunică efectul acestora. (Totuşi, dacă este nevoie, programul poate face şi acest lucru.) De exemplu, dacă utilizatorul selectează un articol dintr-un meniu cu ajutorul tastaturii, Windows trimite programului un mesaj prin care îi comunică articolul de meniu selectat, indiferent dacă utilizatorul a folosit mouse-ul sau tastatura.

Unele programe pentru Windows folosesc „acceleratori" (sau „taste de accelerare") pentru opţiunile de meniu folosite mai frecvent. Acceleratorii sunt, de obicei, combinaţii de taste funcţionale - sau alte taste corespunzătoare unor caractere - cu tasta Ctrl. Tastele de accelerare sunt definite în fişierul de resurse al programului. Tastatura trebuie să fie partajată de toate aplicaţiile rulate simultan sub Windows. Unele aplicaţii pot avea mai multe ferestre, iar tastatura trebuie să fie partajată de toate ferestrele din cadrul aceleiaşi aplicaţii. Atunci când este apăsată o tastă, o singură fereastră trebuie să primească mesajul privind apăsarea tastei respective. Fereastra care primeşte acest mesaj este fereastra care deţine „cursorul de intrare" („input focus"). Conceptul cursorului de intrare este strâns legat de conceptul de „fereastră activă". Fereastra care deţine cursorul de intrare este fie fereastra activă, fie o fereastră descendent a ferestrei active. De obicei, fereastra activă este uşor de identificat. Dacă fereastra activă are o bară de titlu, Windows evidenţiază bara de titlu a acesteia. Dacă fereastra activă are un cadru de dialog (o formă des întâlnită în casetele de dialog) în locul unei bare de titlu, Windows evidenţiază acest cadru. Dacă fereastra activă a fost redusă la o pictogramă (minimizată), Windows evidenţiază textul afişat sub pictogramă. O procedură de fereastră poate să afle când are cursorul de intrare prin interceptarea mesajelor WM_SETFOCUS şi WM_KILLFOCUS. Mesajul WM_SETFOCUS indică faptul că fereastra primeşte cursorul de intrare (input focus), iar mesajul WM_KILLFOCUS indică faptul că fereastra pierde cursorul de intrare.

Acţionări de taste şi caractere Mesajele privind tastatura pe care un program le recepţionează de la sistemul de operare fac diferenţa între „acţionările de taste" („keystrokes") şi „caractere". Aceste noţiuni sunt legate de cele două moduri în care puteţi să priviţi tastatura. În primul rând, tastatura este o colecţie de taste. Tastatura are o singură tastă A; apăsarea tastei A este o acţionare de tastă, iar eliberarea tastei A este tot o acţionare de tastă. Tastatura este, însă, în acelaşi timp, şi un dispozitiv de intrare care generează caractere afişabile. Tasta A poate să genereze mai multe caractere, în funcţie de starea tastelor Ctrl, Shift şi Caps Lock. În mod normal, caracterul generat este a. Dacă tasta Shift este apăsată, sau tasta Caps Lock este activă, caracterul generat este A. Dacă tasta Ctrl este apăsată, caracterul generat este Ctrl+A. Dacă se foloseşte un driver de tastatură pentru o limbă străină, apăsarea tastei A poate să fie precedată de un „caracter mort" („dead-character key") sau de tastele Shift, Ctrl sau Alt în diferite combinaţii. Combinaţiile pot să genereze un caracter a sau A cu un accent. Pentru acţionările de taste care generează caractere afişabile, Windows trimite programului atât mesaje pentru acţionarea de taste, cât şi mesaje pentru caractere. Unele taste nu generează caractere. Astfel de taste sunt Shift, tastele funcţionale, tastele de deplasare şi tastele speciale, precum Insert şi Delete. În cazul acestor taste, Windows generează numai mesaje pentru acţionari de taste.

50.

În ce constă arhitectura orientată pe mesaje?

Orice fereastră creată de un program are asociată o procedură de fereastră. Procedura de fereastră este e funcţie care se poate afla chiar în program sau într-o bibliotecă cu legături dinamice (DLL). Windows trimite un mesaj către o fereastră prin apelarea procedurii de fereastră. Procedura de fereastră prelucrează anumite informaţii pe baza mesajului primit, apoi returnează controlul sistemului de operare. O procedură de fereastră prelucrează mesajele trimise ferestrei respective. Deseori, aceste mesaje informează fereastra cu privire la acţiunile executate de utilizator cu ajutorul mouse-ului sau al tastaturii. Aceasta este calea prin care o fereastră „află", de exemplu, că un buton a fost apăsat. Alte mesaje comunică ferestrei că a fost redimensionată sau că trebuie să fie refăcută.

Atunci când un program este lansat în execuţie, Windows creează o „coadă de mesaje" („message queue") pentru programul respectiv, în această coadă de mesaje sunt păstrate mesajele trimise către toate ferestrele pe care le creează programul. Programul conţine o mică secvenţă de cod numită „ciclu de mesaje" („message loop") care preia mesajele din coada de aşteptare şi le distribuie procedurilor de fereastră corespunzătoare. Alte mesaje sunt trimise direct procedurii de fereastră, fără să mai fie plasate în coada de mesaje.

51. În ce constă consecvenţa privind interfaţa cu utilizatorul? Windows este o interfaţă grafică cu utilizatorul (GUI - graphical user interface), numită uneori şi „interfaţă vizuală" sau „mediu grafic cu ferestre" („graphical windowing environment"). La început, ecranul era folosit numai pentru afişarea informaţiilor pe care utilizatorul le introducea de la tastatură. Într-o interfaţă grafică, ecranul devine chiar o sursă pentru celelalte intrări ale utilizatorului. Pe ecran sunt afişate diferite obiecte grafice sub forma pictogramelor şi a unor dispozitive de intrare, precum butoanele şi barele de derulare. Folosind tastatura (sau, mai direct, un dispozitiv de indicare precum mouse-ul) utilizatorul poate să manipuleze direct aceste obiecte de pe ecran. Obiectele grafice pot fi deplasate, butoanele pot fi apăsate şi barele de derulare pot fi derulate. Interacţiunea dintre program şi utilizator devine mult mai directă. În locul unui ciclu unidirectional al informaţiilor de la tastatură la program şi de la program la ecran, utilizatorul interacţionează direct cu obiectele de pe ecran. Utilizatorii nu mai sunt dispuşi să piardă prea mult timp pentru a învăţa cum se foloseşte calculatorul sau cum să stăpânească un anumit program. Windows îi ajută în acest sens, deoarece toate programele pentru Windows au un aspect asemănător şi se comportă fundamental la fel. Programele ocupă o fereastră - o suprafaţă dreptunghiulară de pe ecran. Fereastra poate fi identificată datorită unei bare de titlu. Majoritatea funcţiilor oferite de program sunt apelate cu ajutorul unui meniu. Informaţiile afişate care nu încap pe un singur ecran pot fi vizualizate cu ajutorul barelor de derulare. Unele articole de meniu apelează casete de dialog în care utilizatorul introduce informaţii suplimentare. În majoritatea programelor mai mari pentru Windows există o casetă de dialog care deschide un fişier. Această casetă de dialog arată la fel (sau foarte asemănător) în mai multe programe Windows şi este apelată aproape întotdeauna cu aceeaşi opţiune de meniu. Din punctul de vedere al programatorului, consecvenţa în realizarea interfeţei cu utilizatorul este rezultatul folosirii procedurilor integrate în Windows pentru construirea meniurilor şi a casetelor de dialog. Toate meniurile au aceeaşi interfaţă cu tastatura şi cu mouse-ul deoarece aceste operaţii sunt manipulate mai degrabă de Windows, decât de programul respectiv.

52.

În ce constă interfaţa grafică independentă de dispozitiv?

Windows este o interfaţă grafică şi programele pentru Windows pot folosi toate avantajele oferite de elementele grafice şi de textul formatat atât pentru ecran, cât şi pentru imprimantă. O interfaţă grafică nu are numai avantajul de a fi mai atractivă, ci şi pe acela de a furniza utilizatorului o cantitate mai mare de informaţii. Programele scrise pentru Windows nu au acces direct la componentele hardware ale dispozitivelor de afişare, cum ar fi ecranul sau imprimanta. În schimb, Windows foloseşte un limbaj de programare pentru grafică (numit GDI - Graphics Device Interface) care simplifică afişarea textului formatat şi a elementelor grafice. Windows transformă componentele hardware de afişare în dispozitive virtuale. Un program scris pentru Windows va rula cu orice placă video şi cu orice imprimanta pentru care Windows are un driver de dispozitiv. Programul nu trebuie să determine ce tip de dispozitiv fizic este ataşat la calculator. Crearea unei interfeţe grafice independente de dispozitiv pentru calculatoarele IBM PC nu a fost o sarcină uşoară pentru dezvoltatorii sistemului de operare Windows. Proiectarea calculatoarelor personale s-a făcut pe baza principiului

arhitecturilor deschise. Producătorii terţi de componente hardware au fost încurajaţi să dezvolte dispozitive periferice, şi datorită acestui fapt au apărut o mulţime de astfel de dispozitive. Deşi au fost create anumite standarde, programele convenţionale pentru MS-DOS trebuie să asigure suportul individual pentru diferite configuraţii standard. De exemplu, este un lucru destul de obişnuit ca un program de procesare de texte pentru MS-DOS să fie livrat împreună cu câteva dischete care conţin mai multe fişiere mici, pentru adaptarea la diferite tipuri de imprimante. Programele Windows 95 nu au nevoie de drivere proprii, deoarece acestea sunt asigurate chiar de sistemul de operare.

53. Interfaţa pentru dispozitive grafice. Filozofia GDI. Structura interfeţei GDI. Tipuri de apeluri de funcţii. Primitive GDI. Interfaţa pentru dispozitive grafice (GDI - Graphics Device Interface) este o componentă a sistemului de operare Windows 95 şi are ca sarcină afişarea elementelor grafice (inclusiv a textului) pe ecran şi la imprimantă. GDI este, în general, un sistem de afişare static, ce permite numai animaţii limitate. Aşa cum este implementată în Windows 95, interfaţă GDI nu asigură un suport direct pentru afişarea tridimensională sau pentru rotirea obiectelor. Din punctul de vedere al programatorului, interfaţa GDI este formată din câteva sute de apeluri de funcţii şi unele tipuri de date, macroinstrucţiuni şi structuri asociate acestor funcţii Filozofia GDI

În versiunile pe 32 de biţi ale sistemului de operare Windows elementele grafice sunt manipulate, în principal, prin funcţii exportate din biblioteca cu legături dinamice GDI32.DLL, care, la rândul ei, foloseşte biblioteca cu legături dinamice pe 16 biţi GDI.EXE. Aceste module apelează proceduri din diferite fişiere driver pentru afişare - un fişier .DRV pentru afişarea pe ecran şi, probabil, unul sau mai multe fişiere .DRV care controlează imprimantele şi plotterele. Driverele execută operaţiile de acces la componentele hardware ale monitorului video sau convertesc comenzile GDI în coduri sau comenzi pe care le pot interpreta diferite tipuri de imprimante. Pentru diferite tipuri de plăci video sau de imprimante este nevoie, desigur, de diferite fişiere driver. Deoarece la calculatoarele compatibile PC pot fi ataşate diferite dispozitive de afişare, unul dintre scopurile principale ale interfeţei GDI este să permită manipularea elementelor grafice independent de dispozitiv. Programele scrise pentru Windows ar trebui să ruleze fără probleme, indiferent de dispozitivul grafic de afişare folosit, dacă acesta este acceptat de sistemul de operare. Interfaţa GDI realizează acest lucru prin furnizarea unor componente care izolează programele de caracteristicile particulare ale diferitelor dispozitive de ieşire. Tipuri de apeluri de funcţii În general, apelurile de funcţii GDI pot fi clasificate în mai multe categorii. Chiar dacă nu sunt foarte stricte şi există unele suprapuneri, aceste categorii pot fi enunţate astfel:

-

-

-

Funcţii care obţin (sau creează) şi eliberează (sau distrug) un context de dispozitiv. . Funcţiile GetDC şi ReleaseDC vă permit să faceţi aceste lucruri în timpul prelucrării altor mesaje decât WM_PAINT, pe când funcţiile BeginPaint şi EndPaint (deşi din punct de vedere tehnic fac parte din subsistemul USER din Windows) sunt folosite în timpul prelucrării mesajului WM_PAINT. Funcţii care obţin informaţii despre contextul de dispozitiv. Funcţii care desenează ceva. Funcţii care stabilesc sau obţin atribute ale contextului de dispozitiv. Un „atribut" al contextului de dispozitiv specifică modul de lucru al funcţiilor de desenare. De exemplu, folosiţi funcţia SetTextColor ca să precizaţi culoarea textului afişat cu funcţia TextOut (sau cu o altă funcţie de afişare a textului). Funcţii care lucrează cu obiecte GDI.

Primitive GDI Elementele grafice pe care le afişaţi pe ecran sau le tipăriţi la imprimantă pot fi împărţite în mai multe categorii, numite „primitive". Iată care sunt aceste categorii:

-

-

-

54.

Linii şi curbe. Liniile reprezintă baza oricărui sistem de desenare vectorial. GDI permite folosirea liniilor drepte, a dreptunghiurilor, a elipselor (inclusiv subsetul de elipse cunoscute sub numele de cercuri), a arcelor - care sunt curbe reprezentând porţiuni din circumferinţa unei elipse sau a curbelor Bezier Suprafeţe pline. Dacă o serie de linii sau de curbe închid o suprafaţă, aceasta poate fi „umplută" folosind pensula GDI curentă. Această pensulă poate fi o culoare compactă, un model (haşuri orizontale, verticale sau pe diagonală) sau o imagine bitmap repetată pe verticală sau pe orizontală. Imagini bitmap. Imaginile bitmap sunt matrice dreptunghiulare de biţi, care corespund pixelilor unui dispozitiv de afişare. Imaginile bitmap sunt instrumente de bază pentru sistemele grafice de tip rastru. În general, acestea sunt folosite pentru afişarea imaginilor complexe (deseori preluate din lumea reală) pe ecran sau pentru tipărirea acestora la imprimantă. De asemenea, imaginile bitmap sunt folosite pentru afişarea unor mici imagini (cum ar fi pictograme, indicatoare de mouse şi butoane de pe barele cu instrumente de lucru ale aplicaţiilor) care trebuie afişate foarte rapid. Text. Textul este mai puţin „matematic" decât alte aspecte ale graficii pe calculator. Textul, aşa cum îl ştim, este legat de sute de ani de tipografia tradiţională, apreciată adesea ca adevărată artă. Din acest motiv, textul este de multe ori nu doar cea mai complexă parte a sistemului grafic, ci şi cea mai importantă. Structurile create pentru definirea fonturilor şi pentru obţinerea informaţiilor despre fonturi sunt printre cele mai mari din Windows. Începând cu versiunea Windows 3.1, interfaţa GDI acceptă fonturile TrueType, bazate pe contururi umplute, care pot fi manipulate de alte funcţii GDI. Mesaje CARACTER. Mesajul WM_CHAR. Mesaje pentru „caractere moarte".

. Există patru mesaje caracter: Caractere Caractere non-sistem Caractere sistem

WM_CHAR WM_SYSCHAR

Caractere „moarte" WM_DEADCHAR WM_SYSDEADCHAR

Mesajul WM_CHAR Atunci când trebuie să prelucreze caracterele introduse de la tastatură (de exemplu, într-un procesor de texte sau întrun program de comunicaţii) programul prelucrează mesajele WM_CHAR. .Dacă utilizatorul apasă o literă (de exemplu, tasta A), procedura de fereastră primeşte un mesaj WM_CHAR pentru care parametrul wParam conţine codul ASCII al literei „a" cu semnul diacritic respectiv.

Mesaje pentru „caractere moarte" De obicei, programele pot să ignore mesajele WM_DEADCHAR si WM_SYSDEADCHAR. Pe unele tastaturi, în afară de tastatura de tip american, o serie de taste sunt folosite pentru adăugarea semnelor diacritice la o literă. Acestea se numesc „taste moarte" („dead keys") deoarece nu pot crea singure caractere. De exemplu, pe o tastatura germană, în locul tastei +/= de pe tastatura americană se află o tastă moartă pentru accentul ascuţit ('') dacă nu este apăsată tasta Shift, si pentru accentul grav (`) dacă este apăsată tasta Shift.

Atunci când utilizatorul apasă această tastă moartă, procedura de fereastră primeşte un mesaj WM_DEADCHAR pentru care parametrul wParam conţine codul ASCII al semnului diacritic. Dacă utilizatorul apasă apoi o literă (de exemplu, tasta A), procedura de fereastră primeşte un mesaj WM_CHAR pentru care parametrul wParam conţine codul ASCII al literei „a" cu semnul diacritic respectiv. Ca urmare, programul nu trebuie să prelucreze mesajul WM_DEADCHAR, deoarece mesajul WM_CHAR următor îi furnizează toate informaţiile necesare. Codul Windows se ocupă chiar şi de tratarea erorilor: dacă tasta moartă este urmată de o literă care nu poate avea semnul diacritic respectiv (cum ar fi litera „s"), procedura de fereastră primeşte două mesaje WM_CHAR - pentru primul parametrul wParam conţine codul ASCII al semnului diacritic, iar pentru al doilea parametrul wParam conţine codul ASCII al literei „s".

55.

Mesaje de la barele de derulare. Structurarea programului pentru desenare. ScrollWindow

Barele de derulare se numără printre cele mai reuşite componente ale unei interfeţe grafice pentru mouse; sunt uşor de folosit şi determină o reacţie vizuală foarte rapidă. Barele de derulare sunt poziţionate vertical (pentru deplasări în sus şi în jos) sau orizontal (pentru deplasări la stânga şi la dreapta). Windows trimite procedurii de fereastră mesajul WM_VSCROLL sau mesajul WM_HSCROLL atunci când utilizatorul execută clic pe bara de derulare sau trage caseta de derulare cu ajutorul mouse-ului. Fiecare acţiune cu mouse-ul asupra barei de derulare generează cel puţin două mesaje - unul la apăsarea butonului şi al doilea la eliberarea acestuia. Procedura de fereastră poate să primească mai multe mesaje SB_LINEUP, SB_PAGEUP, SB_PAGEDOWN, SB_LINEDOWN dacă butonul mouse-ului este ţinut apăsat în timp ce indicatorul lui este poziţionat pe bara de derulare. Mesajul SB_ENDSCROLL semnalează eliberarea butonului mouse-ului. În general puteţi ignora mesajele SB_ENDSCROLL. Atunci când cuvântul mai puţin semnificativ al parametrului wParam are una dintre valorile SB_THUMBTRACK sau SB_THUMBPOSITION, cuvântul mai semnificativ al parametrului wParam conţine poziţia curentă pe bara de derulare. Această poziţie se încadrează în domeniul barei de derulare. Structurarea programului pentru desenare Cel mai bine este să structuraţi programul astfel încât toate operaţiile de desenare în zona client să se facă în timpul prelucrării mesajelor WM_PAINT. Deoarece programul trebuie să aibă posibilitatea de redesenare a întregii zone client în momentul primirii unui mesaj WM_PAINT, probabil veţi duplica unele secvenţe de cod dacă veţi face tipărirea şi în alte puncte din program. În unele aplicaţii s-ar putea să nu fie suficientă simpla transmitere a unor mesaje WM_PAINT prin marcarea unor porţiuni din fereastră ca invalide. După ce apelaţi funcţia InvalidateRect, Windows plasează în coada de aşteptare un mesaj WM_PAINT, iar procedura de fereastră va prelucra la un moment dat acest mesaj. Totuşi, Windows tratează mesajele WM_PAINT ca mesaje de prioritate scăzută şi, dacă în sistem activitatea este intensă, poate să treacă un timp destul de lung pană la prelucrarea acestora. Toată lumea a văzut „găuri" albe în ferestre după închiderea unor casete de dialog. Dacă doriţi ca actualizarea porţiunii invalide să se facă imediat, după funcţia InvalidateRect apelaţi imediat funcţia UpdateWindow: UpdateWindow (hwnd) ; Funcţia UpdateWindow determină sistemul de operare să apeleze procedura de fereastră cu un mesaj WM_PAINT dacă vreo porţiune a zonei client este invalidă. (Dacă întreaga zonă client este validă, procedura de fereastră nu mai este apelată.) Acest mesaj WM_PAINT sare peste coada de aşteptare, procedura de fereastră fiind apelată direct de Windows. După ce procedura de fereastră

încheie operaţia de redesenare, sistemul de operare cedează din nou controlul programului şi execuţia continuă de la instrucţiunea de după apelul funcţiei UpdateWindow. ScrollWindow

Funcţia Windows ScrollWindow este folosită pentru derularea conţinutului ferestrei. Această funcţie are următorul format: ScrollWindow (hwnd, xInc, yInc, pRect, pClipRect) ; Valorile xlnc şi ylnc specifică numărul de pixeli cu care se face derularea. Daca parametrii pRect şi pClipRect au valoarea NULL, atunci se specifica faptul că trebuie derulată întreaga zonă client. Windows invalidează dreptunghiul din zona client „descoperit" de operaţia de derulare. Aceasta generează un mesaj WM_PAINT. Nu este necesară apelarea funcţiei InvalidateRect. (Reţineţi că funcţia ScrollWindow nu este o procedură GDI, deoarece nu are nevoie de o variabilă handle. ScrollWindow este una dintre puţinele funcţii non-GDI din Windows care modifică aspectul zonei client a ferestrei.)

56. Mesaje generate de mouse în afara zonei client. Mesajul de testare a poziţiei. Mesajele generează mesaje. Mesajele generate de mouse în afara zonei client corespund mesajelor din zona client, dar includ caracterele „NC" (de la „non-client"). Dacă mouse-ul este deplasat în afara zonei client a unei ferestre, procedura de fereastră primeşte următoarele mesaje: Buton

Apăsat

Eliberat

Apăsat (al doilea clic)

Stânga

WM_NCLBUTTON DOWN

WM_NCLBUTTONUP

WM_NCLBUTTONDBLCLK

Mijloc

WM_NCMBUTTONDOWN

WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK

Dreapta WM_NCRBUTTONDOWN

WM_NCRBUTTONUP

WM_NCRBUTTONDBLCLK

Totuşi, parametrii wParam şi lParam pentru mesajele generate de mouse din afara zonei client sunt diferite de cele generate din zona client. Parametrul wParam indică zona non-client din care a fost generat mesajul. Parametrul wParam poate conţine unul dintre identificatorii cu prefixul HT („hit test") definiţi în fişierele antet din Windows. Variabila lParam conţine coordonata pe axa x în cuvântul mai puţin semnificativ şi coordonata pe axa y în cuvântul mai semnificativ. Totuşi, aceste coordonate sunt relative la ecran, nu la zona client. Pentru coordonatele de ecran, punctul de origine (0,0) este colţul din stânga-sus al zonei de afişare a ecranului. Valorile coordonatei x cresc către dreapta, iar valorile coordonatei y cresc în jos Mesajul de testare a poziţiei Mesajul WM_NCHITTEST („non client hit test") este folosit pentru verificarea poziţiei din care a fost generat mesajul. Acest mesaj precede toate celelalte mesaje generate de mouse, din zona client sau din afara acesteia. Parametrul IParam al mesajului conţine coordonatele x şi y ale indicatorului de mouse. Parametrul wParam nu este folosit. De obicei, aplicaţiile Windows transmit acest mesaj funcţiei DefWindowProc. Windows foloseşte mesajul WM_NCHITTEST ca să genereze celelalte mesaje, în funcţie de poziţia mouse-ului. Pentru mesajele din afara zonei client, valoarea returnată de funcţia DefWindowProc în urma prelucrării mesajului WM_NCHITTEST devine parametrul wParam al mesajului generat. Această valoare poate fi oricare dintre valorile wParam care însoţesc mesajele generate de mouse din afara zonei client, plus următoarele:

HTCLIENT

Zona client

HTNOWHERE

Nici o fereastră

HTTRANSPARENT

O fereastră acoperită de o altă fereastră

HTERROR

Determină funcţia DefWindowProc să emită un semnal sonor

Dacă funcţia DefWindowProc generează un mesaj HTCLIENT în urma prelucrării mesajului WM_NCHITTEST, Windows transformă coordonatele ecran în coordonate ale zonei client şi generează un mesaj pentru zona client. Mesajele generează mesaje Windows foloseşte mesajul WM_NCHITTEST ca să genereze alte mesaje de mouse. Ideea mesajelor care generează alte mesaje este des întâlnită în Windows. După cum ştiţi, dacă executaţi dublu clic pe pictograma meniului sistem a unui program Windows, execuţia acestuia se încheie. Executarea unui dublu clic generează o serie de mesaje WM_NCHITTEST. Deoarece indicatorul mouse-ului se află deasupra pictogramei meniului sistem, funcţia DefWindowProc returnează valoarea HTSYSMENU şi Windows inserează în coada de aşteptare a programului un mesaj WM_NCLBUTTONDBLCLK care conţine în parametrul wParam valoarea HTSYSMENU. De obicei, procedura de fereastră retransmite acest mesaj funcţiei DefWindowProc. Atunci când recepţionează mesajul cu parametrul wParam egal cu HTSYSMENU, funcţia DefWindowProc inserează în coada de aşteptare un mesaj WM_SYSCOMMAND cu parametrul wParam egal cu SC_CLOSE. (Acest mesaj WM_SYSCOMMAND este generat şi atunci când utilizatorul selectează opţiunea Close din meniul sistem.) Din nou, procedura de fereastră transmite acest mesaj funcţiei DefWmdowProc. Funcţia DefWindowProc îl prelucrează trimiţând procedurii de fereastră mesajul WM_CLOSE. Dacă doriţi ca programul să ceară confirmarea utilizatorului înainte de terminare, procedura de fereastră trebuie sunt intercepteze mesajul WM_CLOSE. În caz contrar, funcţia DefWmdowProc prelucrează mesajul WM_CLOSE apelând funcţia DestroyWindow. Printre alte acţiuni, funcţia DestroyWindow trimite procedurii de fereastră un mesaj WM_DESTROY. În mod normal, procedura de fereastră prelucrează mesajul WM.DESTROY astfel: case WM_DESTROY : PostQuitMessage (0) ; return 0 ;

Funcţia PostQuitMessage determină sistemul de operare să insereze în coada de mesaje un mesaj WM_QUIT. Acest mesaj nu ajunge niciodată la procedura de fereastră, deoarece determină funcţia GetMessage să returneze valoarea 0, care încheie ciclul de tratare a mesajelor.

57. MESAJE GENERATE DE MOUSE ÎN ZONA CLIENT Mesaje non-client. Măştile MK_LBUTTON, MK_MBUTTON, MK_RBUTTON, MK_SHIFT, MK_CONTROL. Mesaje zona-client> Atunci când mouse-ul este deplasat peste zona client a unei ferestre, procedura de fereastră primeşte mesajul WM_MOUSEMOVE. Dacă un buton al mouse-ului este apăsat sau eliberat în zona client a unei ferestre, procedura de fereastră primeşte un sir de mesaje ca: WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK de si de asemenea un sir de mesaje pentru celelate butoane ale soricelului(pentru butonul din mijloc si cel din dreapta-depinde de tipul mouse’ului(cu unul doua sau trei butoane, cit si de specificatiile ferestre ce poate sau nu sa primeasca dublu clik)). , parametrul lParam conţine poziţia mouse-ului. Mesaje NC> Dacă mouse-ul se află în afara zonei client, dar se află încă în fereastră, Windows trimite procedurii de fereastră un mesaj „non-client". Zona „non-client" include bara de titlu, meniul şi barele de derulare ale ferestrei. În general nu este nevoie să prelucraţi mesajele generate în afara zonei client(DefWindowProc()).Mesajele generate de

mouse în afara zonei client corespund mesajelor din zona client, dar includ caracterele „NC"(WM_NCLBUTTONDOWN,WM_NCLBUTTONUP,WM_NCLBUTTONDBLCLK). Parametrul wParam indică zona nonclient din care a fost generat mesajul. Parametrul wParam poate conţine unul dintre identificatorii cu prefixul HT. Variabila lParam conţine coordonata pe axa x în cuvântul mai puţin semnificativ şi coordonata pe axa y în cuvântul mai semnificativ(raportate la zona ecran). Mastiel> Valoarea parametrului wParam indică starea buloanelor mouse-ului şi starea tastelor Shift şi Ctrl. Puteţi să testaţi parametrul wParam folosind o serie de măşti definite în fişierele antet din Windows. MK_LBUTTON Butonul din stânga al mouse-ului este apăsat MK_MBUTTON Butonul din mijloc al mouse-ului este apăsat MK_RBUTTON Butonul din dreapta al mouse-ului este apăsat MK_SHIFT

Tasta Shift este apăsată

MK_CONTROL Tasta Ctrl este apăsată

58. Mesajele de la o fereastră child la una părinte. Mesajele de la o fereastra copil la una parinte pot fi observate foarte bine pe baza unei ferestre de tip „button” ce este copilul unei ferestre parinte.Atunci când executaţi clic pe un buton, controlul de tip fereastră descendent trimite mesajul WM_COMMAND către fereastra părinte. Programul interceptează mesajul WM_COMMAND cu valorile lParam şi wParam. Iată ce semnificaţie au acestea: LOWORD (wParam)

Identificatorul ferestrei descendent

HIWORD (wParam)

Codul de înştiinţare

lParam

Variabila handle a ferestrei descendent

Dacă faceţi conversia unor programe scrise pentru versiunile pe 16 biţi ale sistemului de operare Windows, reţineţi că aceşti parametri au fost modificaţi în vederea adaptării la dimensiunea pointerilor pe 32 de biţi. Codul de înştiinţare este un cod de submesaj pe care fereastra descendent îl foloseşte pentru a transmite ferestrei părinte mai multe informaţii despre semnificaţia mesajului. Valorile pe care le pot avea aceste coduri sunt definite în fişierele antet definite în Windows:BN_CLICKED;BN_PAINT;BN_HILITE;BN_UNHILITE;BN_DISABLE;BN_DOUBLECLICKED;

59. Mesajele de la timer. Programul nostru avind un timer setat v-a primi la fiecare interval de timp specificat un singur mesaj , si anume WM_TIMER, insa este important de tinut cont ca ceasul foloseste tactul de sitem sau mai bine spus intreruperile de sistem ce au unele restrictii, întreruperi sunt generate la fiecare 54,925 milisecunde, adică de 18,2 ori pe secundă. Intervalul de timp pe care îl specificaţi la apelarea funcţiei SetTimer este rotunjit la un multiplu întreg de tacturi de ceas. De exemplu, prin împărţirea intervalului de 1000 de milisecunde la 54,925 rezultă 18,207, valoare care este rotunjită la 18 tacturi de ceas, ceea ce înseamnă, de fapt, un interval de 989 milisecunde.Insa intreruperile de ceas caatare nu pot fi condsiderate ca fiind asincrone, insa mesajele WM_TIMER au o prioritate joasa, fiind in principiu foarte asemanatoare cu mesajele WM_PAINT.

60. Mesajele privind tastatura: acţionări de taste şi „caractere". Taste obişnuite şi taste de sistem. WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP. Variabila lParam. Actionari de taste si caractere> Mesajele privind tastatura pe care un program le recepţionează de la sistemul de operare fac diferenţa între „acţionările de taste" („keystrokes") şi „caractere". Aceste noţiuni sunt legate de cele două moduri în care puteţi să priviţi tastatura. În primul rând, tastatura este o colecţie de taste. Tastatura are o singură tastă A; apăsarea tastei A este o acţionare de tastă, iar eliberarea tastei A este tot o acţionare de tastă. Tastatura este, însă, în acelaşi timp, şi un dispozitiv de intrare care generează caractere afişabile. Tasta A poate să genereze mai multe caractere, în funcţie de starea tastelor Ctrl, Shift şi Caps Lock. În mod normal, caracterul generat este a. Dacă tasta Shift este apăsată, sau tasta Caps Lock este activă, caracterul generat este A. Dacă tasta Ctrl este apăsată, caracterul generat este Ctrl+A. Dacă se foloseşte un driver de tastatură pentru o limbă străină, apăsarea tastei A poate să fie precedată de un „caracter mort" („dead-character key") sau de tastele Shift, Ctrl sau Alt în diferite combinaţii. Combinaţiile pot să genereze un caracter a sau A cu un accent. Pentru acţionările de taste care generează caractere afişabile, Windows trimite programului atât mesaje pentru acţionarea de taste, cât şi mesaje pentru caractere. Unele taste nu generează caractere. Astfel de taste sunt Shift, tastele funcţionale, tastele de deplasare şi tastele speciale, precum Insert şi Delete. În cazul acestor taste, Windows generează numai mesaje pentru acţionari de taste. Taste obisnuite si taste de sistem> Mesajele WM_SYSKEYDOWN şi WM_SYSKEYUP sunt generate, de obicei, pentru taste apăsate în combinaţie cu tasta Alt. Aceste acţionari de taste apelează opţiuni din meniul programului ori din meniul sistem, sunt folosite pentru funcţii ale sistemului, cum ar fi comutarea ferestrei active (Alt+Tab sau Alt+Esc) sau sunt folosite pentru acceleratori de meniu (Alt în combinaţie cu o tastă funcţională). De obicei, programul ignoră mesajele WM_SYSKEYDOWN şi WM_SYSKEYUP şi le retransmite funcţiei DefWindowProc. Deoarece Windows manipulează combinaţiile Alt+tastă, nu este nevoie să interceptaţi aceste mesaje. WM_KEYDOWN şi WM_KEYUP sunt caracteristice deja pentru tastele obisnuite. Variabila lParam> Pentru toate mesajele legate de acţionările de taste variabila lParam (pe 32 de biţi) transmisă procedurii de fereastră este împărţită în şase câmpuri: contorul de repetare(specifică numărul de acţionari de taste reprezentat de un mesaj. În majoritatea cazurilor, contorul de repetare are valoarea 1), codul de scanare OEM(codul de scanare al tastaturii, generat de componentele hardware deobicei ignorat, indicatorul flag pentru taste extinse are valoarea 1 dacă mesajul este generat de una dintre tastele suplimentare de pe tastatura IBM extinsă.), codul de context(are valoarea 1 dacă este apăsată tasta Alt), starea anterioară a tastei(are valoarea 0 dacă tasta nu a fost anterior apăsată, şi valoarea 1 dacă tasta a fost apăsată) şi starea de tranziţie(are valoarea 0 dacă tasta este apăsată şi valoarea 1 dacă tasta este eliberată).

61. Mesajele WM_CREATE, WM_PAINT şi WM_DESTROY. WM_CREATE> Atunci când din main se apelează funcţia CreateWindow, Windows face ce are de făcut şi apelează funcţia WndProc, transmiţându-i variabila handle a ferestrei şi mesajul WM_CREATE. WndProc prelucrează mesajul WM_CREATE şi returnează controlul sistemului de operare.De cele mai dese ori WM_CREATE ce este practic primul mesaj primit de procedura de fereastra este folosit pentru a initializa unele valori sau variabile necesare in viitorul imediat al timpului de executie. WM_PAINT> Acest mesaj este foarte important în programarea sub Windows, deoarece informează fereastra privind faptul că o parte sau întreaga zonă client a acesteia este „invalidă" şi trebuie să fie redesenată. Aproape întotdeauna, prelucrarea mesajului WM_PAINT începe prin apelarea funcţiei BeginPaint şi se termină cu apelarea funcţiei EndPaint cu parametrii (hwnd, &ps),ps- PAINTSTRUCT conţine unele informaţii pe care programul le poate folosi pentru redesenarea zonei client.

WM_DESTROY> Un alt mesaj important este WM_DESTROY. Acest mesaj indică faptul că sistemul de operare desfăşoară un proces de distrugere a ferestrei pe baza unei comenzi de la utilizator. Mesajul este trimis atunci când utilizatorul execută clic pe butonul Close, selectează opţiunea Close din meniul sistem sau apasă fastele Alt+F4. Programul HELLOWIN răspunde la acest mesaj printr-o metodă standard, apelând funcţia PostQuitMessage (0) ; Această funcţie inserează în coada de aşteptare a programului un mesaj WM_QUIT. Am spus anterior că funcţia GetMessage returnează o valoare diferită de zero în cazul preluării oricărui mesaj în afară de WM_QUIT. Atunci când preia din coada de aşteptare un mesaj WM_QUIT, funcţia GetMessage returnează valoarea 0, ceea ce determină ieşirea din ciclul de tratare a mesajelor din funcţia WinMain şi închiderea programului.

62. Mesajul WM_PAINT. Dreptunghiuri valide şi invalide. WM_PAINT> Acest mesaj este foarte important în programarea sub Windows, deoarece informează fereastra privind faptul că o parte sau întreaga zonă client a acesteia este „invalidă" şi trebuie să fie redesenată. Aproape întotdeauna, prelucrarea mesajului WM_PAINT începe prin apelarea funcţiei BeginPaint şi se termină cu apelarea funcţiei EndPaint cu parametrii (hwnd, &ps),ps- PAINTSTRUCT conţine unele informaţii pe care programul le poate folosi pentru redesenarea zonei client(inclusiv o structura de tip RECT ce inlcude dreptunghoil invalid).Cel mai important la mesajul WM_PAINT este faptul ca el permite desenarea doar in zona invalida ce nu este altceva decit o regiune a zonei client ce a fost acoperita de un meniu popup sau a fost suprapusa de o alta fereastra .. mutata in afara zonei ecran etc si spre final valideaza zona in cauza.Desenarea fortata se poate efectua apelind funtia InvalidateRect(hwnd,lpRect,bErase); ce invalideaza o zona si respectiv asugura desenarea in cadrul zonei date(daca pentru lpRect includem valoarea NULL intreaga zona client va fi redesenata). 63. Modificarea textului unui buton. Puteţi să modificaţi textul unui buton (sau al unei alte ferestre) prin apelarea funcţiei SetWindowText: SetWindowText (hwnd, pszString) ; unde hwnd este variabila handle a ferestrei al cărei text urmează să fie înlocuit, iar pszString este un pointer la un şir de caractere terminat cu caracterul nul. Pentru o fereastră normală, acesta este textul care va fi afişat în bara de titlu. Pentru un buton, acesta este textul afişat pe buton. De asemenea, puteţi să obţineţi textul ferestrei curente: iLength = GetWindowText (hwnd, pszBuffer, iMaxLength) ; Parametrul iMaxLength specifică numărul maxim de caractere care va fi copiat în bufferul adresat de pointerul pszBuffer. Funcţia returnează lungimea şirului de caractere copiat. Puteţi să pregătiţi programul pentru un text de o anumită lungime apelând mai întâi funcţia GetWindowTextLength: iLength = GetWindowTextLength (hwnd) ;

64. Moduri de desenare. Operaţii rastru (ROP - raster operation). Funcţiile SetROP2, iDrawMode, GetROP2. Imaginaţi-vă o cale prin care să puteţi folosi aceeaşi peniţă ca să desenaţi o linie albă pe fond negru, dar şi o linie neagră pe fond alb, ştiind ce culoare are fondul. Dacă vă este utilă această facilitate, puteţi să o obţineţi prin schimbarea modului de desenare. Atunci când foloseşte o peniţă pentru desenarea unei linii, Windows face de fapt o operaţie booleană între pixelii peniţei şi pixelii de pe suprafaţa destinaţie. Efectuarea operaţiei booleene între pixeli se numeşte „operaţie rastru"(ROP). Deoarece desenarea unei linii implică numai două modele de pixeli (peniţa şi destinaţia),

operaţia booleană se numeşte „operaţie rastru binară" sau ROP2. Windows defineşte 16 coduri ROP2 care specifică modul de combinare între pixelii peniţei şi pixelii suprafeţei, în contextul de dispozitiv prestabilit, modul de desenare definit este R2_COPYPEN, ceea ce înseamnă că Windows copiază pixelii peniţei pe suprafaţa destinaţie - adică modul normal în care suntem obişnuiţi să funcţioneze o peniţă. Există alte 15 coduri ROP2. Puteţi să selectaţi un nou mod de desenare în contextul de dispozitiv astfel: SetROP2 (hdc, iDrawMode) ; unde parametrul iDrawMode este una dintre valorile din coloana „Mod de desenare" a tabelului ce contine toate modurile de desenare.Puteţi să obţineţi modul curent de desenare astfel: iDrawMode = GetROP2 (hdc) ; Exemple de moduri de desenare : Modul R2_NOTCOPYPEN desenează cu alb dacă peniţa este neagră şi cu negru dacă peniţa este albă. Modul R2_BLACK desenează întotdeauna cu negru, indiferent de culoarea peniţei şi a destinaţiei. În mod similar, modul R2_WHITE desenează întotdeauna cu alb. Modul R2_NOP este o „operaţie nulă" - destinaţia rămâne nemodificată.

65. Modurile de mapare „metrice". Moduri de mapare proprii. Modul de mapare MM_ISOTROPIC.

Modul de mapare MM_ANISOTROPIC sau ajustarea imaginii. Moduri de mapare metrice> Windows include două moduri de mapare în care coordonatele logice sunt exprimate în unităţi fizice. Deoarece coordonatele logice pe axele x şi y sunt mapate la unităţi fizice identice, aceste moduri de mapare vă ajută să desenaţi cercuri „mai rotunde" şi pătrate „mai pătrate".

Extensiile ferestrei şi ale vizorului depind de modul de mapare şi de raportul de afişare a dispozitivului. Aşa cum am menţionat anterior, extensiile nu sunt impor tante ca atare, având o semnificaţie numai exprimate ca rapoarte.Importanta este trecerea la noile senduri de crestere a axelor de coordonate , la axa y ea fiind inversa celei obisnuite la MM_TEXT, pentru facilitate putem muta originea sistemului in centrul ferestrei : SetViewportOrgEx (hdc, cxClient/2, cyClient/2, NULL) ; daca ar fi sa mutam originea ferestrei am fi nevoiti sa transformam puctele fizice in cele logice pentru a fi transmise functiei SetWindowOrgEx (hdc, -pt.x/2, -pt.y/2, NULL) ; Moduri de mapare proprii> Acestea sunt singurele moduri de mapare care vă permit să modificaţi extensiile ferestrei şi ale vizorului, ceea ce înseamnă că vă permit să modificaţi factorul de scalare pe care Windows îl foloseşte pentru convertirea coordonatelor logice şi a coordonatelor de dispozitiv. MM_ISOTROPIC> Modul de mapare MM_ISOTROPIC este ideal pentru folosirea unor axe arbitrare, cu unităţi logice egale pe cele două axe. Dreptunghiurile cu lăţimi şi înălţimi logice egale sunt afişate ca pătrate. Elipsele cu lăţimi şi înălţimi logice egale sunt afişate ca cercuri.Puteţi să folosiţi un sistem de coordonate cartezian cu patru cadrane având axe arbitrar scalate în cele patru direcţii şi cu punctul de coordonate (0, 0) în centrul zonei client. Dacă, de exemplu, vreţi ca fiecare axă să ia valori de la 0 la 1000, folosiţi codul următor: SetMapMode (hdc, MM_ISOTROPIC) ; SetWindowExtEx (hdc, 1000, 1000, NULL); SetViewportExtEx (hdc, cxClient/2, -cyClient/2, NULL) ;

SetViewportOrgEx (hdc, cxClient/2, cyCllent/2, NULL) ; Important este faptul ca imaginea va ramine neschimbata chiar daca fereastra e mai mult lata decit inaltasi invers. MM_ANISOTROPIC> Atunci când stabiliţi extensiile ferestrei şi pe ale vizorului în modul de mapare MM_ISOTROPIC, Windows ajustează valorile astfel încât unităţile logice de pe cele două axe să aibă aceleaşi dimensiuni. În modul de mapare MM_ANISOTROPIC, Windows nu face nici o ajustare a valorilor pe care le stabiliţi. Aceasta înseamnă că în modul de mapare MM_ANISOTROPIC nu este obligatorie păstrarea raportului corect de afişare. Pentru a folosi modul de mapare MM_ANISOTROPIC, stabiliţi un sistem arbitrar de coordonate pentru zona client, ca şi pentru modul de mapare MM_ISOTROPIC. Codul de mai jos stabileşte punctul de coordonate (0, 0) în colţul din stângajos 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 (hdc, 0, cyClient, NULL) ;

66. Modurile de mapare. Coordonate de dispozitiv şi coordonate logice. Sistemele de coordonate ale dispozitivului. Vizorul şi fereastra. Folosirea modului de mapare MM_TEXT. Modul de mapare> este un atribut al contextului de dispozitiv ce afecteaza aproape orice operatie de desnenare.De exemplu in 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. 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) ; Coordonatele de dispozitiv si cele logice> sunt un element important ce trebuie inteles.Cele fizice sunt coordonatele dipozitivului fizic(adica pixelii) pe cind cele logice sunt dependete de modul de mapare.Insa cind se folosesc fiecare tip de coordonate. Windows va folosi în continuare coordonatele de dispozitiv pentru toate mesajele (cum ar fi WM_SIZE, WM_MOVE şi WM_MOUSEMOVE), pentru toate funcţiile care nu fac parte din interfaţa GDI şi chiar pentru unele funcţii GDI. GetSystemMetrics nu este o funcţie GDI, aşa că va returna în continuare dimensiunile în unităţi de dispozitiv, adică în pixeli. . Dacă modul de mapare este MM_LOENGLISH în momentul apelării funcţiei, GetTextMetrics returnează lăţimea şi înălţimea caracterelor, în sutimi de inci. Sistemele de coordonate ale dispozitivului> Deşi în general am lucrat doar în zona client a ferestrei, în anumite situaţii Windows foloseşte alte două sisteme de coordonate de dispozitiv. În toate sistemele de coordonate de dispozitiv sunt folosiţi pixelii ca unitate de măsură. Valorile de pe axa orizontală (x) cresc de la stânga la dreapta iar valorile de pe axa verticală (y) cresc de sus în jos. Atunci când folosim întregul ecran, spunem că lucrăm în „coordonate ecran". Colţul din stânga-sus este punctul de coordonate (0, 0). Dacă folosiţi funcţia CreateDC cu parametrul DISPLAY ca să obţineţi un context de dispozitiv pentru întregul ecran, atunci coordonatele logice specificate la apelarea funcţiilor GDI vor fi mapate la coordonatele ecranului. „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. Al treilea sistem de coordonate de dispozitiv - cu care vom lucra cel mai des -foloseşte

„coordonatele zonei client". Punctul (0,0) este colţul din stânga-sus al zonei client. Puteţi să transformaţi coordonatele zonei client în coordonatele ecranului şi invers folosind funcţiile ClientToScreen şi ScreenToClient. Vizorul şi fereastra> 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 (coordonate de dispozitiv) folosind două formule:

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

DPtoLP (hdc, pPoints, iNumber) ;//Converteste punctele de dispozitiv in logice LPtoDP (hdc, pPoints, iNumber) ;//Converteste punctele logice in cele de dipozitiv Folosirea modului de mapare MM_TEXT> 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. Î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. 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) ; Totuşi, modul de mapare MM_TEXT prezintă o mică problemă: de obicei, într-un sistem de coordonate cartezian, valorile de pe axa y cresc în sus, pe când în modul de mapare MM_TEXT acestea cresc în jos. In acest sens, modul de mapare MM_TEXT este un caz izolat, această problemă fiind corectată de celelalte cinci moduri de mapare.

67. Obţinerea informaţiilor despre culori. PLANES, BITSPIXEL, NUMCOLORS: Tipul COLORREF. 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); 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 O la 255. Rezultă o paletă potenţială de 224 culori (aproximativ 16 milioane de culori).

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

dispozitiv. Obtinerea variablilei Handle a CD> hdc - BeginPaint (hwnd, &ps); [alte Unii de program] EndPaint (hwnd, &ps);//Permite desenarea doar in zona invalida si validarea acesteia hdc = GetDC (hwnd); (alte linii de program] ReleaseDC (hwnd, hdc);//Permite desenarea in intreaga zona client hdc = GetWindowDC (hwnd); [alte linii de program] ReleaseDC (hwnd, hdc);//Permite desenarea in intreaga fereastra … ce poate creaa efecte nedorite Funcţiile BeginPaint, GetDC şi GetWindowDC obţin variabila handle a contextului de dispozitiv asociat unei anumite ferestre de pe ecran. O funcţie mai generală pentru obţinerea variabilei handle a unui context de dispozitiv este CreateDC: hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData); [alte linii de program] DeleteDC (hdc); De exemplu, puteţi să obţineţi variabila handle a contextului de dispozitiv pentru tot spaţiul de afişare, cu următorul apel:

hdc = CreateDC ("DISPLAY", NULL, NULL, NULL); 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) 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); Dacă aveţi nevoie de anumite informaţii despre acest dispozitiv>, cum ar fi dimensiunile ecranului (dimensiunile în pixeli şi cele fizice) sau posibilităţile de folosire a culorilor, puteţi să le obţineţi prin apelarea funcţiei GetDeviceCaps („get device capabilities"): iValue = GetDeviceCaps (hdc, iIndex) ; Parametrul iIndex este unul dintre cei 28 de identificatori definiţi în fişierele antet din Windows. De exemplu, dacă iIndex are valoarea HORZRES funcţia GetDeviceCaps returnează lăţimea dispozitivului în pixeli; VERTRES returnează înălţimea dispozitivului în pixeli. 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 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 ferestrei După 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 { 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 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 desenare Am 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 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 sistem Tot î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 golurilor Folosirea 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 Î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 programului Windows 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 zilună-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) ; 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: 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 c

Tip de date char

by

BYTE (unsigned char)

i

int

x, 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ţie

s

şir de caractere

sz

sir de caractere terminat cu zero

h

variabilă handle

p

pointer

În sfârşit, în program sunt folosiţi trei identificatori cu majuscule pentru diferite tipuri de variabile handle: Identificator Semnificaţie HINSTANCE Variabilă handle a unei „instanţe" - programul însuşi HWND

Variabilă handle a unei ferestre

HDC

Variabilă handle a unui context de dispozitiv

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: 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ţei wndclass.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 ferestrei wndclass.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 ferestrei Clasa 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 ferestrei

WS_OVERLAPPEDWINDOW,

// stilul ferestrei

CW_USEDEFAULT,

// poziţia iniţiala pe axa x

CW_USEDEFAULT,

// poziţia iniţiala pe axa y

CW_USE DEFAULT,

// dimensiunea iniţiala pe axa x

CW_USEDEFAULT,

// dimensiunea iniţiala pe axa y

NULL,

// variabila handle a ferestrei părinte

NULL,

// variabila handle a meniului

hlnstance,

// variabila handle a instanţei programului

NULL) ;

// 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ă 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 FERESTREI După 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.

DOT NET 81.

Arhitectura .NET Framework. Compilarea programelor. De ce am alege .NET?

.NET este un cadru (Framework) de dezvoltare software unitară care permite realizarea, distribuirea şi rularea aplicaţiilor desktop Windows şi aplicaţiilor WEB. Tehnologia .NET pune laolaltă mai multe tehnologii (ASP, XML, OOP, SOAP, WDSL, UDDI) şi limbaje de programare (VB, C++, C#, J#) asigurând, totodată, atât portabilitatea codului compilat între diferite calculatoare cu sistem Windows, cât şi reutilizarea codului în programe, indiferent de limbajul de programare utilizat. Componenta .NET Framework este formată din compilatoare, biblioteci şi alte executabile utile în rularea aplicaţiilor .NET. Fişierele corespunzătoare se află, în general, în directorul C:\WINDOWS\Microsoft. NET\Framework\V2.0…. (corespunzător versiunii instalate) Un program scris într-unul dintre limbajele .NET conform Common Language Specification (CLS) este compilat în Microsoft Intermediate Language (MSIL sau IL). Codul astfel obţinut are extensia "exe", dar nu este direct executabil, ci respectă formatul unic MSIL. CLR include o maşină virtuală asemănătoare cu o maşină Java, ce execută instrucţiunile IL rezultate în urma compilării. Maşina foloseşte un compilator special JIT (Just In Time). Compilatorul JIT analizează codul IL corespunzător apelului unei metode şi produce codul maşină adecvat şi eficient. El recunoaşte secvenţele de cod pentru care s-a obţinut deja codul maşină adecvat, permiţând reutilizarea acestuia fără recompilare, ceea ce face ca, pe parcursul rulării, aplicaţiile .NET să fie din ce în ce mai rapide. Faptul că programul IL produs de diferitele limbaje este foarte asemănător are ca rezultat interoperabilitatea între aceste limbaje. Astfel, clasele şi obiectele create într-un limbaj specific .NET pot fi utilizate cu succes în altul. În plus, CLR se ocupă de gestionarea automată a memoriei (un mecanism implementat în platforma .NET fiind acela de eliberare automată a zonelor de memorie asociate unor date devenite inutile – Garbage Collection). Ca un element de portabilitate, trebuie spus că .NET Framework este implementarea unui standard numit Common Language Infrastructure (http://www.ecma-international.org/publications/standards/Ecma-335.htm ), ceea ce permite rularea aplicaţiilor .NET, în afară de Windows, şi pe unele tipuri de Unix, Linux, Solaris, Mac OS X şi alte sisteme de operare (http://www.mono-project.com/Main_Page ). De ce am alege .NET? În primul rând pentru că ne oferă instrumente pe care le putem folosi şi în alte programe, oferă acces uşor la baze de date, permite realizarea desenelor sau a altor elemente grafice. Spaţiul de nume System.Windows.Forms conţine instrumente (controale) ce permit implementarea elementelor interfeţei grafice cu utilizatorul. Folosind aceste controale, puteţi proiecta şi dezvolta rapid şi interactiv, elementele interfeţei grafice. Tot .NET vă oferă clase care efectuează majoritatea sarcinilor uzuale cu care se confruntă programele şi care plictisesc şi fură timpul programatorilor, reducând astfel timpul necesar dezvoltării aplicaţiilor

82.

Introducere în C#. Caracterizare. Crearea aplicaţiilor consolă

Limbajul C# a fost dezvoltat de o echipă restrânsă de ingineri de la Microsoft, echipă din care s-a evidenţiat Anders Hejlsberg (autorul limbajului Turbo Pascal şi membru al echipei care a proiectat Borland Delphi). C# este un limbaj simplu, cu circa 80 de cuvinte cheie şi 12 tipuri de date predefinite. El permite programarea structurată, modulară şi orientată obiectual, conform perceptelor moderne ale programării profesioniste. Principiile de bază ale programării orientate pe obiecte (ÎNCAPSULARE, MOŞTENIRE, POLIMORFISM) sunt elemente fundamentale ale programării C#. În mare, limbajul moşteneşte sintaxa şi principiile de programare din C++. Sunt o serie de tipuri noi de date sau funcţiuni diferite ale datelor din C++, iar în spiritul realizării unor secvenţe de cod sigure (safe), unele funcţiuni au fost adăugate

(de exemplu, interfeţe şi delegări), diversificate (tipul struct), modificate (tipul string) sau chiar eliminate (moştenirea multiplă şi pointerii către funcţii). Unele funcţiuni (cum ar fi accesul direct la memorie folosind pointeri) au fost păstrate, dar secvenţele de cod corespunzătoare se consideră „nesigure”. Crearea aplicaţiilor consolă Pentru a realiza aplicaţii consolă în mediul de dezvoltare Visual Studio, trebuie să instalăm o versiune a acestuia. După lansarea aplicaţiei, din meniul File se alege opţiunea NewProject apoi alegem ConsoleApplication, modificând numele aplicaţiei în caseta Name. Când creaţi o aplicaţie consolă, se generează un fişier cu extensia .cs. Extensia cs provine de la C Sharp. Redenumirea lui se poate realiza din fereastra Solution Explorer, pe care o puteţi afişa cu ajutorul combinaţiei de taste Ctrl+W,S sau din meniul View.

83.

Structura unui program C#. Sintaxa limbajului.

O aplicaţie C# este formată din una sau mai multe clase, grupate în spaţii de nume (namespaces). Este obligatoriu ca doar una din aceste clase să conţină un „punct de intrare” (entry point), şi anume metoda (funcţia) Main. Clasa (class), în termeni simplificaţi, reprezintă principalul element structural şi de organizare în limbajele orientate spre obiecte, grupând date cât şi funcţii care prelucrează respectivele date. în module, dezvoltate separat, de mai multe persoane. Din acest motiv, există posibilitatea de a apărea identificatori cu acelaşi nume. Pentru a evita erori furnizate din acest motiv, în 1955 limbajul C++ introduce noţiunea şi cuvântul cheie namespace. Fiecare mulţime de definiţii dintr-o librărie sau program este grupată într-un spaţiu de nume, existând astfel posibilitatea de a avea într-un program definiţii cu nume identic, dar situate în alte spaţii de nume. În cazul în care, într-o aplicaţie, unele clase sunt deja definite, ele se pot folosi importând spaţiile de nume care conţin definiţiile acestora. Mai menţionăm faptul că un spaţiu de nume poate conţine mai multe spaţii de nume. Sintaxa limbajului Ca şi limbajul C++ cu care se înrudeşte, limbajul C# are un alfabet format din litere mari şi mici ale alfabetului englez, cifre şi alte semne. Vocabularul limbajului este format din acele „simboluri” cu semnificaţii lexicale în scrierea programelor: cuvinte (nume), expresii, separatori, delimitatori şi comentarii.

84. C#: Expresii şi operatori. Instrucţiunile try-catch-finally şi throw. Un operator este un simbol care indica o actiune. Operandul este valoarea asupra careia se executa operatia. Operatorii alaturi de operanzi formeaza o expresie. Clasificarea operatorilor Operatorii sunt impartiti 3 categorii. Operatori unari – actioneaza asupra unui singur operand. Operatori binari – actioneaza intre doi operanzi. Operatori ternari – actioneaza asupra a trei operanzi. Exista doar unul de acest tip, operatorul conditional.

Operatorii aritmetici In C#, exista urmatorii operatori aritmetici : + , - ,* , / , % , ++ , -- .

Operatorii relationali Operatorii relationali se refera la relatiile de ordine care pot exista intre doua valori: =, !=, < , > , <= , >= . Deoarece acesti operatori produc rezultate de tip adevarat sau fals, sunt folositi des cu operatorii logici. Operatorii logici Pentru operatorii logici, operanzii trebuie sa fie de tipul bool, rezultatul fiind tot de acest tip. Operator

Semnificatie

!

negatie logica

&&

SI logic

||

SAU logic

Operatorul de atribuire Operatorul de atribuire “=” se foloseste intr-o constructie de forma variabila = expresie. Dupa evaluarea expresiei, rezultatul va fi atribuit variabilei. Pentru atribuire se mai folosesc si operatorii +=, –=, *=, /=, %=. Operatorul conditional Este de forma : expresie1? expresie2: expresie3 . Daca expresie1 este adevarata, atunci va fi returnata valoarea lui expresie2. Dacaexpresie1 este falsa, atunci va fi returnata valoarea lui expresie3. Cuvintele cheie in C# rezervate pentru tratarea exceptiilor sunt try, catch, finally, throw. Acestea reprezinta un sistem unitar, utilizarea unuia dintre ele implicand si utilizarea altuia. Intr-un bloc try vom scrie instructiunile care trebuie verificate pentru aparitia erorilor. Daca pe parcursul executiei acestor intructiuni apare o exceptie, aceasta este “aruncata”, lansata (thrown). Cu ajutorul lui catch programul poate intercepta exceptia si o poate trata in functie de logica programului. Instructiunile din catch se executa doar daca se lanseaza o exceptie. Instructiunile din finally se vor executa intotdeauna. O imagine de ansamblu a codului folosit pentru tratarea exceptiilor: try { //in this block exception may get thrown

} catch { //handle exception } finally { //cleanup code, optionally } Cuvantul cheie try nu poate aparea fara a fi completat de cuvantul cheie catch sau de finally si nici invers. Finally este optional. Pot exista mai multe instructiuni catch asociate unui try. Instructiunea care se va executa se va stabili in functie de tipul exceptiei, celelalte sunt ignorate. Throw Pentru a lansa manual o exceptie se foloseste throw. if (numbers == null) throw new ArgumentNullException("Array is null"); Tipul obiectului trebuie sa fie o clasa derivata din Exception.

85.Evoluţia tehnicilor de programare. Tipuri de date obiectuale. Încapsulare.Supraîncărcare. 1.1. Evoluţia tehnicilor de programare Programarea nestructurată(un program simplu, ce utilizează numai variabile globale);complicaţiile apar când prelucrarea devine mai amplă, iar datele se multiplică şi se diversifică. Programarea procedurală(program principal deservit de subprograme cu parametric formali, variabile locale şi apeluri cu parametri efectivi); se obţin avantaje privind depanarea şi reutilizarea codului şi se aplică noi tehnici privind transferul parametrilor şi vizibilitateavariabilelor; complicaţiile apar atunci când la program sunt asignaţi doi sau mai mulţiprogramatori care nu pot lucra simultan pe un acelaşi fişier ce conţine codul sursă. Programarea modulară(gruparea subprogramelor cu funcţionalităţi similare în module, implementate şi depanateseparat); se obţin avantaje privind independenţa şi încapsularea (prin separarea zonei de implementare, păstrând vizibilitatea numai asupra zonei de interfaţă amodulului) şi se aplică tehnici de asociere a procedurilor cu datele pe care le manevrează, stabilind şi diferite reguli de acces la date şi la subprograme.Se observă că modulele sunt ”centrate” pe proceduri,acestea gestionând şi setul de date pe care le prelucrează.

Programarea orientată obiect(programe cu noi tipuri ce integrează atât datele, cât şi metodele asociate creării,prelucrării şi distrugerii acestor date); se obţin avantaje prin abstractizarea programării (programul nu mai este o succesiune de prelucrări, ci un ansamblu de obiecte care prind viaţă, au diverse proprietăţi, sunt capabile de acţiuni specifice şi care interacţionează în cadrul programului); intervin tehnici noi privind instanţierea, derivarea şi polimorfismul tipurilor obiectuale. Tipuri de date obiectuale. Încapsulare Un tip de date abstract (ADT) este o entitate caracterizată printr-o structură de date şi un ansamblu de operaţii aplicabile acestor date. Considerând, în rezolvarea unei problemede gestiune a accesului utilizatorilor la un anumit site, tipul abstract USER , vom obseva că sunt multe date ce caracterizează un utilizator Internet. Totuşi se va ţine cont doar de datele semnificative pentru problema dată. Astfel, ”culoarea ochilor” este irelevantă în acest caz, întimp ce ”data naşterii” poate fi importantă. În aceeaşi idee, operaţii specifice ca ”se înregistrează”, ’comandă on-line” pot fi relevante, în timp ce operaţia ”manâncă” nu este, în cazul nostru. Evident, nici nu se pun în discuţie date sau operaţii nespecifice (”numărul delaturi” sau acţiunea ”zboară”).Operaţiile care sunt accesibile din afara entităţii formează interfaţa acesteia. Astfel,operaţii interne cum ar fi conversia datei de naştere la un număr standard calculat de la01.01.1900 nu fac parte din interfaţa tipului de date abstract, în timp ce operaţia ”plasează ocomandă on-line” face parte, deoarece permite interacţiunea cu alte obiecte (SITE, STOC etc.) O instanţă a unui tip de date abstract este o ”concretizare” a tipului respectiv, formatădin valori efective ale datelor.Un tip de date obiectual este un tip de date care implementează un tip de date abstract.Vom numi operaţiile implementate în cadrul tipului de date abstract metode . Spunem că datele şi metodele sunt membrii unui tip de date obiectual. Folosirea unui astfel de tip presupune: existenţa definiţiei acestuia, apelul metodelor şi accesul la date. Un exemplu de-acum clasic de tip de date abstract este STIVA. Ea poate avea ca date: numerele naturale din stivă, capacitatea stivei, vârful etc. Iar operaţiile specifice pot fi:I ntroducerea în stivă ( push) şi extragerea din stivă ( pop). La implementarea tipului STIVA, vom defini o structura de date care să reţină valorile memorate în stivă şi câmpuri de datesimple pentru: capacitate, număr de elemente etc. Vom mai defini metode (subprograme)capabile să creeze o stivă vidă, care să introducă o valoare în stivă, să extragă valoarea dinvârful stivei, să testeze dacă stiva este vidă sau dacă stiva este plină etc. Crearea unei instanţe noi a unui tip obiectual, presupune operaţii specifice de”construire” a noului obiect, metoda corespunzătoare purtând numele de constructor. Analog, la desfiinţarea unei instanţe şi eliberarea spaţiului de memorie aferent datelor sale, se aplică o metodă specifică numită destructor.O aplicaţie ce utilizează tipul obiectual STIVA, va putea construi două sau mai multe stive (de cărţi de joc, de exemplu), le va umple cu valori distincte, va muta valori dintr-o stivă în alta după o anumită regulă desfiinţând orice stivă golită, până ce rămâne o singură stivă.De observat că toate aceste prelucrări recurg la datele, constructorul, destructorul şi la metodele din interfaţa tipului STIVA descris mai sus. Principalul tip obiectual întâlnit în majoritatea mediilor de dezvoltare (Viisual Basic,Delphi, C++, Java, C#) poartă numele de clasă (class). Există şi alte tipuri obiectuale (struct,object). O instanţă a unui tip obiectual poartă numele de obiect. .La implementare, datele şi metodele asociate trebuie să fie complet şi corect definite,astfel încât utilizatorul să nu fie nevoit să ţină cont de detalii ale acestei implementări. El vaaccesa datele, prin intermediul proprietăţilor şi va efectua operaţiile, prin intermediulmetodelor puse la dispoziţie de tipul obiectual definit. Spunem că tipurile de date obiectuale respectă principiulÎncapsulării.

Permiţând extensia tipurilor de date abstracte, clasele pot avea la implementare: •date şi metode caracterisitice fiecărui obiect din clasă (membri de tip instanţă), •date şi metode specifice clasei (membri de tip clasă). Astfel, clasa STIVA poate beneficia, în plus, şi de date ale clasei cum ar fi: numărul de stive generate, numărul maxim sau numărul minim de componente ale stivelor existente etc. Modificatorul static plasat la definirea unui membru al clasei face ca acela să fie un membru de clasă, nu unul de tip instanţă. Dacă în cazul membrilor nestatici, există câte unexemplar al membrului respectiv pentru fiecare instanţă a clasei, membrii statici sunt unici,fiind accesaţi în comun de toate instanţele clasei. Mai mult, membrii statici pot fi referiţi fără acrea vreo instanţă a clasei respective. 1.3. Supraîncărcare Deşi nu este o tehnică specifică programării orientată obiect, ea creează un anumit context pentru metodele ce formează o clasă şi modul în care acestea pot fi (ca orice subprogram) apelate.Prin supraîncarcare se înţelege posibilitatea de a defini în acelaşi domeniu devizibilitate mai multe funcţii cu acelaşi nume, dar cu parametri diferiti ca tip şi/sau ca număr.Astfel ansamblul format din numele funcţiei şi lista sa de parametri reprezintă o modalitateunică de identificare numită semnătură sau amprentă. Supraîncărcarea permite obţinereaunor efecte diferite ale apelului în contexte diferite.Apelul unei funcţii care beneficiază, prin supraîncărcare, de două sau mai multesemnături se realizează prin selecţia funcţiei a cărei semnătură se potriveşte cel mai bine culista de parametri efectivi (de la apel).Astfel, poate fi definită metoda ”comandă on-line” cu trei semnături diferite: 1)comanda_online(cod_prod)cu un parametru întreg (desemnând comanda unui singur produs identificat prin cod_prod. 2)comanda_online(cod_prod,cantitate)cu primul parametru întreg şi celalalt real 3)comanda_online(cod_prod,calitate)cu primul parametru întreg şi al-II-ilea caracter.

86.Moştenire. Polimorfism. Metode virtuale. Principiile programării orientate pe obiecte. Pentru tipurile de date obiectuale class este posibilă o operaţie de extindere sau specializare a comportamentului unei clase existente prin definirea unei clase noi cemoşteneşte datele şi metodele clasei de bază, cu această ocazie putând fi redefiniţi unii membri existenţi sau dăugaţi unii membri noi. Operaţia mai poartă numele de derivare.Clasa din care se moşteneştea se mai numeşte clasă de bază sau superclasă. Clasacare moşteneşte se numeşte subclasă , clasă derivată sau clasă descendentă. O subclasă poate moşteni de la o singură superclasă, adică avem de-a face cu moştenire simplă; aceeaşi superclasă însă poate fi derivată în mai multe subclase distincte. O subclasă, la randul ei, poate fi superclasă pentru o altă clasă derivată.O clasă de bază impreună cu toate clasele descendente (direct sau indirect) formeaza oierarhie de clase. În C#, toate clasele moştenesc de la clasa de bază Object. În contextul mecanismelor de moştenire trebuie amintiţi modificatorii Abstract şi sealed aplicaţi unei clase, modificatori ce obligă la şi respectiv se opun procesului de derivare. Astfel, oclasă abstractă trebuie obligatoriu derivată, deoarece direct din ea nu se pot obţine obiecteprin operaţia de instanţiere, în timp ce o clasă sigilată (sealed) nu mai poate fi derivată (e unfel de terminal în ierarhia claselor). O metodă abstractă

este o metodă pentru care nu este definită o implementare, aceasta urmând a fi realizată în clasele derivate din clasa curentă.O metodă sigilată nu mai poate fi redefinită în clasele derivate din clasa curentă. 1.5. Polimorfism. Metode virtuale Folosind o extensie a sensului etimologic, un obiect polimorfic este cel capabil să ia diferite forme, să se afle în diferite stări, să aibă comportamente diferite. Polimorfismul obiectual se manifestă în lucrul cu obiecte din clase aparţinând unei ierarhii de clase, unde,prin redefinirea unor date sau metode, se obţin membri diferiţi având însă acelaşi nume.Astfel, în cazul unei referiri obiectuale, se pune problema stabilirii datei sau metodei referite. Comportamentul polimorfic este un element de flexibilitate care permite stabilirea contextuală, în mod dinamic, a membrului referit. De exemplu, dacă este definită clasa numită PIESA (de şah), cu metoda nestatică muta(pozitie_initiala,pozitie_finala),atunci subclasele TURN şi PION trebuie să aibă metoda muta definită în mod diferit (pentru a implementa maniera specifică a pionului de a captura o piesă ”en passant”). Atunci, pentru un obiect T, aparţinând claselor derivate din PIESA, referirea la metoda muta pare nedefinită. Totuşi mecanismele POOpermit stabilirea, în momentul apelului, a clasei proxime căreia îi aparţine obiectul T şiapelarea metodei corespunzătore (mutare de pion sau turn sau altă piesă).Pentru a permite acest mecanism, metodele care necesită o decizie contextuală (în momentul apelului), se decalră ca metode virtuale (cu modificatorul virtual). În mod curent, în C# modificatorului virtual al funcţiei din clasa de bază, îi corespunde un specificator override al funcţiei din clasa derivată ce redefineşte funcţia din clasa de bază.O metodă ne-virtuală nu este polimorfică şi, indiferent de clasa căreia îi aparţine obiectul, va fi invocată metoda din clasa de bază. Principiile POO:  Abstractizarea – Este posibilitatea ca un program să ignore unele aspecte ale informației pe care o manipulează, adică

posibilitatea de a se concentra asupra esențialului. Fiecare obiect în sistem are rolul unui “actor” abstract, care poate executa acțiuni, își poate modifica și comunica starea și poate comunica cu alte obiecte din sistem fără a dezvălui cum au fost implementate acele facilitați. Procesele, funcțiile sau metodele pot fi de asemenea abstracte, și în acest caz sunt necesare o varietate de tehnici pentru a extinde abstractizarea:  Încapsularea – numită și ascunderea de informații: Asigură faptul că obiectele nu pot schimba starea internă a altor obiecte în mod direct (ci doar prin metode puse la dispoziție de obiectul respectiv); doar metodele proprii ale obiectului pot accesa starea acestuia. Fiecare tip de obiect expune o interfață pentru celelalte obiecte care specifică modul cum acele obiecte pot interacționa cu el.  Polimorfismul – Este abilitatea de a procesa obiectele în mod diferit, în funcție de tipul sau de clasa lor. Mai exact, este abilitatea de a redefini metode pentru clasele derivate. De exemplu pentru o clasă Figura putem defini o metodă arie. Dacă Cerc, Dreptunghi, etc. ce vor extinde clasa Figura, acestea pot redefini metoda arie.  Moștenirea – Organizează și facilitează polimorfismul și încapsularea, permițând definirea și crearea unor clase specializate plecând de la clase (generale) deja definite - acestea pot împărtăși (și extinde) comportamentul lor, fără a fi nevoie de a-l redefini. Aceasta se face de obicei prin gruparea obiectelor în clase și prin definirea de clase ca extinderi ale unor clase existente. Conceptul de moștenire permite construirea unor clase noi, care păstrează caracteristicile și comportarea, deci datele și funcțiile membru, de la una sau mai multe clase definite anterior, numite clase de bază, fiind posibilă redefinirea sau adăugarea unor date și funcții noi. Se utilizează ideea: ”Anumite obiecte sunt similare, dar în același timp diferite”. O clasă moștenitoare a uneia sau mai multor clase de bază se numește clasă derivată. Esența moștenirii constă în posibilitatea refolosirii lucrurilor care funcționează.

87.

STRUCTURA UNEI APLICAŢII ORIENTATĂ PE OBIECTE ÎN C#. Clasă de bază şi clase derivate.

În C#, funcționalitatea unei clase poate fi extinsă aplicînd moștenirea. Clasa derivată poate moșteni atributele clasei de bază, metodele acesteia. De asemenea pot fi suprascrise proprietățile sau metodele, la necesitate. Moștenirea se definește prin operatorul : . Nu este permisă moștenirea de la mai mult de o clasă de bază. public class Parent //clasa de bază { string parentString; public Parent() //constructorul clasei de bază { Console.WriteLine("Parent Constructor."); } public Parent(string myString) //metoda clasei de bază { parentString = myString; Console.WriteLine(parentString); } public void print() //metoda clasei de bază { Console.WriteLine("I'm a Parent Class."); } } public class Child : Parent //clasa derivată { public Child() : base("From Derived") //base este utilizat pentru a accesa metodele clasei de bază din clasa derivată { Console.WriteLine("Child Constructor."); } public new void print() { base.print(); //base accesează metoda print din clasa parent Console.WriteLine("I'm a Child Class."); } public static void Main() { Child child = new Child(); //se inițializează un obiect de tip Child child.print(); //se vor afișa 2 șiruri > unul prin base.print, altul prin writeline() ((Parent)child).print(); //se accesează metoda print din clasa de bază } }

88.

STRUCTURA UNEI APLICAŢII ORIENTATĂ PE OBIECTE ÎN C#. Constructori. Supraîncărcarea constructorilor şi definirea constructorilor în clasele derivate. Destructor. Metode.

Cîteva noţiuni legate de constructorii unei clase: Constructorul este o funcţie care face parte din corpul unei clase. Corpul constructorului este format din instrucţiuni care se execută la crearea unui nou obiect al clasei respective (sau la crearea clasei, în cazul constructorilor cu modificatorul static).  pot exista mai mulţi constructori care se pot diferenţia prin lista lor de parametri  constructorii nu pot fi moşteniţi  dacă o clasă nu are definit niciun constructor, se va asigna automat constructorul fără parametri al clasei de bază (clasa object, dacă nu este precizată clasa de bază)

Instanţierea presupune declararea unei variabile de tipul clasei respective şi iniţializarea acesteia prin apelul constructorului clasei (unul dintre ei, dacă sunt definiţi mai mulţi) precedat de operatorul new. public class Copil { protected string nume; //data accesibila numai in interiorul //clasei si a claselor derivate public Copil ( ) //constructorul fara parametrii ai clasei {nume = Console.ReadLine( );} public Copil (string s) //constructor cu parametru {nume = s;} } class Fetita: Copil { public Fetita (string s): base(s) //base semnifica faptul ca { //se face apel la nume = "Fetita "+ nume; //constructorul //din clasa de baza }} ... Copil c1 = new Copil ( ); //numele copilului se citeste de la //tastatura Copil c2 = new Copil ("Gigel"); //numele lui c2 va fi Gigel Fetita f1 = new Fetita ( ); Fetita f2 = new Fetita ("Maria"); Destructor: Corpul destructorului este format din instrucţiuni care se execută la distrugerea unui obiect al clasei respective. Pentru orice clasă poate fi definit un singur constructor. Destructorii nu pot fi moşteniţi. În mod normal, destructorul nu este apelat în mod explicit, deoarece procesul de distrugere a unui obiect este invocat şi gestionat automat de Garbage Collector

89.

CLASE ŞI FUNCŢII GENERICE. DERIVAREA CLASELOR (MOŞTENIRE). Principiile moştenirii. Accesibilitatea membrilor moşteniţi. 90. Metode. Interfeţe în C#.

Metodele sunt subroutine care prelucreaza datele definite in cadrul clasei si pot oferi accesul la acele date. De regula interactiunea dintre o clasa si celelalte entitati dintr-un program se face prin intermediul metodelor clasei. Cu ajutorul metodelor putem să organizăm codul. Fiecare metoda poate conţine mai multe instrucţiuni, poate returna sau nu o valoare, sau poate contine parametri. Utilizarea metodelor este utilă când avem nevoie de a repeta o bucată de cod. Nu vom scrie de 10 ori aceeaşi bucată de cod, ci vom avea o metoda ce conţine codul nostru, pe care o apelăm când avem nevoie. O interfata defineste un set de metode care vor fi implementate de una sau mai multe clase. O interfata nu implementeaza metode ci doar precizeaza ce anume va contine o clasa care implementeaza interfata. Din punct de vedere sintactic, interfetele sunt similare claselor abstracte. Insa, exista mai multe aspecte care le diferentiaza. Spre exemplu: daca in clasele abstracte unele metode erau implementate iar altele nu, in cazul interfetelor toate metodele nu pot avea corp (nu sunt implementate). O interfata poate contine doar: metode, proprietati, evenimente si indexari. Interfetele nu pot contine variabile, constructori sau destructori. Daca o clasa nu poate mosteni decat o clasa, in schimb o clasa poate implementa oricate interfete. De asemenea, o interfata poate fi implementata de oricate clase. Asadar, este posibil ca doua clase sa implementeze aceeasi interfata in moduri diferite. Daca o clasa implementeaza o interfata atunci aceasta trebuie sa implementeze toti membrii interfetei. Prin intermediul interfetelor, limbajul C# permite beneficierea la maximum de aspectul “o singura interfata mai multe metode” al

polimorfismului.

91.

TRATAREA EXCEPŢIILOR ÎN C#. Aruncarea şi prinderea excepţiilor.

O excepţie este un obiect care încapsulează informaţii despre o situaţie anormală. Excepţia se foloseşte pentru a semnala contextul în care apare acea situaţie deosebită. În C# se pot arunca ca excepţii obiecte de tip System.Exception sau derivate ale lui. Pe lângă ierarhia de excepţii pe care limbajul C# o are inclusă, programatorul îşi poate crea propriile sale tipuri excepţie. POO oferă o soluţie pentru gestionarea erorilor: folosirea blocurilor try şi catch. În scrierea codului, programatorul va separa acele instrucţiuni care sunt sigure (adică nu pot fi generatoare de excepţii), de cele care sunt susceptibile să conducă la erori. Partea de program care poate genera excepţii o vom plasa într-un bloc try, iar partea corespunzătoare tratării excepţiei, într-un bloc catch. În cazul în care blocul try generează o excepţie, Runtime întrerupe execuţia şi caută un bloc catch apropiat care, în funcţie de tipul său să poată trata respectiva eroare. În cazul în care este găsit respectivul bloc catch programul continuă cu instrucţiunile din corpul catch. În cazul în care nu se găseşte nici un catch corespunzător, execuţia programului este întreruptă. Având în vedere că într-un corp try pot să apară excepţii diferite, în program pot exista mai multe blocuri corespunzătoare catch. Programatorul poate să-şi compună modalităţi proprii de aruncare a erorilor folosind instrucţiunea throw: Limbajul C# permite ca la ieşirea dintr-un bloc try să fie executate obligatoriu, în cazul în care programatorul doreşte acest lucru, anumite instrucţiuni. Pentru acest lucru, respectivele instrucţiuni vor fi plasate întrun bloc finally. Blocul finally este util fie pentru a evita scrierea unor instrucţiuni de mai multe ori, fie pentru a elibera resursele după părăsirea excepţiei.

92.

POLIMORFISM. Polimorfismul parametric. Polimorfismul ad-hoc. Polimorfismul de moştenire.

Polimorfismul este capacitatea unor entitățide a lua forme diferite. Limbajul C# admite trei tipuri de polimorfism:

- polimorfism parametric Această formă de polimorfism este preluată de la limbajele neobiectuale: Pascal, C. Prin această formă de polimorfism, o funcţie va prelucra orice număr de parametri. Pentru aceasta se va folosi un parametru de tip params. - polimorfism ad-hoc Acest tip de polimorfism se mai numeşte şi supraîncărcarea metodelor. Prin acest mecanism se pot defini în cadrul unei clase mai multe metode, toate având acelaşi nume, dar cu tipul şi numărul de parametri diferiţi. La compilare, în funcţie de parametri folosiţi la apel, se va apela o funcţie sau alta.

- polimorfism de moştenire Polimorfismul de moștenire – mecanismul prin care o metodă din clasa de bază este redefinită cu aceiași parametri în clasele derivate. Selecția funcției se va realiza la rulare (legarea întârziată (late binding, dynamic binding, runtime binding)). În limbajul C++ este implementat cu ajutorul funcțiilor virtuale.

93.

Modificatorii virtual şi override. Modificatorul new. Metoda sealed.

Virtual este folosit in declararea unei metode sau a unei proprietati. Acestea se vor numi membri virtuali. Implementarea unui membru virtual poate fi schimbata prin suprascrierea membrului intr-o clasa derivata. Override se foloseste pentru a modifica o metoda sau o proprietate si furnizeaza o noua implementare a unui membru mostenit dintr-o clasa de baza. Metoda de baza suprascrisa si metoda de suprascriere trebuie sa aiba aceeasi signatura ( tip si numar de parametri ). Implicit, metodele nu sunt virtuale. Nu se pot suprascrie metodele care nu sunt virtuale.

Modificatorul new În cazul în care se doreşte ca o metodă dintr-o clasă derivată să aibă aceeaşi semnătură cu o metodă dintr-o clasă de bază, dar să nu fie considerată o suprascriere a ei, vom folosi modificatorul new. Exemplu: class Baza { public virtual void Afis() { Console.WriteLine("Apelul functiei Afis din clasa de baza\n"); } } class Derivata : Baza { // !!! new public new void Afis() { Console.WriteLine("Apelul functiei Afis din clasa derivata\n"); } }

O metodă având tipul override poate fi declarată sealed. În acest fel ea nu mai poate fi suprascrisă într-o clasă derivată.

94. CONCEPTE DE BAZĂ ALE PROGRAMĂRII VIZUALE.

Simplitatea: Interfaţa trebuie să fie cât mai uşor de înţeles şi de învăţat de către utilizator şi să permită acestuia să efectueze operaţiile dorite în timp cât mai scurt. În acest sens, este vitală culegerea de informaţii despre utilizatorii finali ai aplicaţiei şi a modului în care aceştia sunt obişnuiţi să lucreze. Poziţia controalelor: Locaţia controalelor dintr-o fereastră trebuie să reflecte importanţa relativă şi frecvenţa de utilizare. Astfel, când un utilizator trebuie să introducă nişte informaţii – unele obligatorii şi altele opţionale – este indicat să organizăm controalele astfel încât primele să fie cele care preiau informaţii obligatorii. Consistenţa: Ferestrele şi controalele trebuie să fie afişate după un design asemănător („template”) pe parcursul utilizării aplicaţiei. Înainte de a implementa interfaţa, trebuie decidem cum va arăta aceasta, să definim „template”-ul. Estetica: Interfaţa trebuie să fie pe cât posibil plăcută şi atrăgătoare.

95. MEDIUL DE DEZVOLTARE VISUAL C# (INTERFEŢA). Mediul de dezvoltare Microsoft Visual C# dispune de instrumente specializate de proiectare, ceea ce permite crearea aplicaţiilor în mod interactiv, rapid şi uşor. Pentru a construi o aplicaţie Windows (FileNew Project) se selectează ca template Windows Forms Application. O aplicaţie Windows conţine cel puţin o fereastră (Form) în care se poate crea o interfaţă cu utilizatorul aplicaţiei. Componentele vizuale ale aplicaţiei pot fi prelucrate în modul Designer (Shift+F7) pentru a plasa noi obiecte, a le stabili proprietăţile etc. Codul „din spatele” unei componente vizuale este accesibil în modul Code (F7).

În fereastra Solution Explorer sunt afişate toate fişierele pe care C# 2008 Express Edition le-a inclus în proiect. Form1.cs este formularul creat implicit ca parte a proiectului. Fişierul Form1.cs conţine un formular (fereastra Form1 derivata din clasa Form) care este reprezentată în formatul Design (Form1.cs[Design]), adică într-un format in care se poate executa proiectare vizuală, prin inserarea controalelor necesare selectate din fereastra Toolbox, care se activează atunci când este „atinsă” cu mouse-ul. Fişierul Form1.cs poate fi văzut ca fişier text sursă prin selectarea lui în fereastra Solution Explorer, clic dreapta cu mouse-ul şi selecţia opţiunii View Code. Fereastra Properties (Ctrl+W,P) este utilizată pentru a schimba proprietăţile obiectelor. Toolbox (Ctrl+W,X) conţine controale standard drag-and-drop şi componente utilizate în crearea aplicaţiei Windows. Controalele sunt grupate în categoriile logice din imaginea alăturată. Ferestrele care sunt afişate in fereastra principală se pot stabili prin selecţie din meniul View. La crearea unei noi aplicaţii vizuale, Microsoft Visual C# 2008 Express Edition generează un spaţiu de nume care conţine clasa statică Program, cu metoda statică ce constituie punctul de intrare (de lansare) a aplicaţiei: static void Main() { ... Application.Run(new Form1()); } Clasa Application este responsabilă cu administrarea unei aplicaţii Windows, punând la dispoziţie proprietăţi pentru a obţine informaţii despre aplicaţie, metode de lucru cu aplicaţia şi altele. Toate metodele şi proprietăţile clasei Application sunt statice. Metoda Run creează un formular implicit, aplicaţia răspunzând la mesajele utilizatorului până când formularul va fi închis. Compilarea modulelor aplicaţiei şi asamblarea lor într-un singur fişier „executabil” se realizează cu ajutorul opţiunilor din meniul Build, uzuală fiind Build Solution (F6). Odată implementată, aplicaţia poate fi lansată, cu asistenţă de depanare sau nu (opţiunile Start din meniul Debug). Alte facilităţi de depanare pot fi folosite prin umărirea pas cu pas, urmărirea până la puncte de întrerupere etc. (celelalte opţiuni ale meniului Debug). Ferestre auxiliare de urmărire sunt vizualizate automat în timpul procesului de depanare, sau pot fi activate din submeniul Windows al meniului Debug. Proiectarea vizuală a formularului se poate face inserând controale selectate din fereastra de instrumente (Toolbox) şi setând proprietăţile acestora.

96. ELEMENTELE POO ÎN CONTEXT VIZUAL. Elementele programarii orientate pe obiecte sunt pe larg utilizate si in contextul vizual chiar daca nu sunt deodata sesizabile.Exemplul perfect este insasi managementul unui proiect WindowsForm in C#.Dupa cum ne amintim pe ecranul aplicatiei putem gasi mai multe elemente … daca e sa le analizam atunci putem vedea elementele POO.Insasi fereastra SolutionExplorer ce la prima vedere contine doar codul nostru , in realitate reprezinta un organizator de fisiere ce contin clasele , formele etc (formele apropo sunt iarasi obiecte , deci iarasi vine vorba despre POO).Cel mai reprezentative elemente sunt Toolbox’ul si Proprietatile.Din Toolbox putem selecta diferite obiecte ce le putem aranja dupa dorinta in fereastra noastra(asa numita forma) , iar la general vobind în Toolbox există toate tipurile de controale care îi sunt necesare unui programator pentru a realiza o aplicaţie. Cele mai multe controale sunt obiecte de clase derivate din clasa System.Windows.Forms.Control. Datorită acestui fapt multe dintre proprietăţile şi evenimentele

diverselor controale vor fi identice. Fereastra Properties, din interfaţa mediului de programare, vom observa că va conţine atât proprietăţile cât şi evenimentele ataşate controalelor. Proprietăţile controalelor, sunt moştenite sau supraînscrise din clasa de bază Control. In acest mod vedem ca Programarea vizuala este nu altceva decit aceeasi programare orientata peobiecte doar ca simplificata si cu mult mai accesibila. 97. Barele de instrumente 98. CONSTRUIREA INTERFEŢEI UTILIZATOR. Ferestre. Controale

Ferestre

Spaţ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 stabili setâ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ă 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. Controale Unitatea 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 utilizator calendar 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/exclude etichetă 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.

99.

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. 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 ai 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 evenimente Un 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 Click Metoda Dispose() Metodele Clear() şi Add() Metoda ShowDialog() 100. 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 bidimensional Putem 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

Related Documents

Examen Pw
February 2021 1
Examen Pw
January 2021 3
Sertifikat Pw
February 2021 1
Pw Resa Rfbt
February 2021 1
Examen
February 2021 3
Examen
March 2021 0

More Documents from "INMA"

Examen Pw
January 2021 3