Sunteți pe pagina 1din 22

Capitolul 1 .....................................................................................................................................................................................

2
ÎNCEPUTUL ................................................................................................................................................................................. 2
PROVOCAREA PROGRAMATORULUI ................................................................................................................................... 2
REGULI DE BAZĂ ................................................................................................................................................................... 2
UN SCURT ISTORIC AL SISTEMULUI DE OPERARE WINDOWS .................................................................................. 3
ESTE TIMPUL SĂ ÎNCEPEM.................................................................................................................................................. 4
Capitolul 2. Hello, Windows 95! ................................................................................................................................................... 5
CE ADUCE NOU SISTEMUL DE OPERARE WINDOWS .................................................................................................... 5
Interfaţa grafică cu utilizatorul (GUI) ........................................................................................................................................ 5
Conceptele şi fundamentele GUI ............................................................................................................................................... 5
Consecvenţa privind interfaţă cu utilizatorul ............................................................................................................................. 5
Avantajul oferit de multitasking ................................................................................................................................................ 6
Gestionarea memoriei ................................................................................................................................................................ 6
Interfaţa grafică independentă de dispozitiv .............................................................................................................................. 6
Dacă optaţi pentru Windows... ................................................................................................................................................... 7
Apelurile de funcţii .................................................................................................................................................................... 7
Programarea orientată pe obiecte ............................................................................................................................................... 7
Arhitectura bazată pe mesaje ..................................................................................................................................................... 7
Procedura de fereastră ................................................................................................................................................................ 8
PRIMUL DUMNEAVOASTRĂ PROGRAM WINDOWS ...................................................................................................... 8
Ce este greşit în acest program? ................................................................................................................................................. 8
Fişierele programului HELLOWIN ........................................................................................................................................... 9
Fişierul de construcţie .............................................................................................................................................................. 11
Fişierul sursă C ........................................................................................................................................................................ 11
Apelurile de funcţii Windows .................................................................................................................................................. 11
Identificatori cu majuscule ....................................................................................................................................................... 12
Noi tipuri de date ..................................................................................................................................................................... 12
Câteva cuvinte despre variabilele handle ................................................................................................................................. 13
Notaţia ungară .......................................................................................................................................................................... 13
Punctul de intrare în program................................................................................................................................................... 13
Înregistrarea clasei de fereastră ................................................................................................................................................ 14
Crearea terestrei ....................................................................................................................................................................... 16
Afişarea ferestrei ...................................................................................................................................................................... 16
Ciclul de mesaje ....................................................................................................................................................................... 17
Procedura de fereastră .............................................................................................................................................................. 18
Prelucrarea mesajelor ............................................................................................................................................................... 18
Redarea unui fişier de sunet ..................................................................................................................................................... 19
Mesajul WM_PAINT............................................................................................................................................................... 19
Mesajul WM_DESTROY ........................................................................................................................................................ 20
PROBLEME LEGATE DE PROGRAMAREA SUB WINDOWS ......................................................................................... 20
Nu ne apela, te apelăm noi!...................................................................................................................................................... 20
Mesaje în coada de aşteptare şi în afara acesteia ..................................................................................................................... 21
Nu fiţi egoist! ........................................................................................................................................................................... 22
Ciclul de învăţare ..................................................................................................................................................................... 22

27.04.21 15:58 pag. 1 din 22


CAPITOLUL 1
Această carte se adresează utilizatorilor experimentaţi ai limbajului de programare C care doresc să înveţe să scrie aplicaţii
pentru sistemul de operare Windows 95. Experienţa în folosirea limbajului C este prima condiţie necesară pentru utilizarea
acestei cărţi. A doua cerinţă este să aveţi instalat pe calculator mediul de dezvoltare Microsoft Visual C++ versiunea 4.0 pentru
programarea pe 32 de biţi. În al treilea rând - dar nu ultimul - este important să cunoaşteţi sistemul de operare Windows 95 şi
să înţelegeţi elementele fundamentale de proiectare a interfeţei acestuia. Aşa cum probabil ştiţi Windows 95 este cea mai
recentă versiune a unui sistem de operare grafic prezentat pentru prima dată în noiembrie 1985 pentru calculatoarele IBM PC
sau compatibile cu acestea. Din punctul de vedere al competiţiei pe piaţă, Windows 95 a eliminat practic orice concurent din
ultimul deceniu şi a devenit standardul de facto pentru mediile de lucru ale calculatoarelor personale, în prezent, dacă scrieţi un
program pentru calculatoarele compatibile PC, atunci scrieţi un program pentru Windows.
Consideraţi acest capitol prima dumneavoastră zi la şcoală. Chiar dacă unii profesori mai ciudaţi încep prin predarea celor
mai dificile elemente ale unui curs, majoritatea preferă o introducere mai lejeră. Ca urmare, în acest capitol vom prezenta
câteva informaţii istorice despre Windows, principiile pe care s-a bazat elaborarea acestei cărţi şi chiar (dacă îmi permiteţi)
câteva lucruri despre mine însumi şi despre modul în care am ajuns să scriu cartea de faţă.
Totuşi, nu pot garanta că acest capitol nu vă va solicita vreun efort intelectual. Sunteţi programator, sunteţi inginer
software şi, la fel ca în cazul altor ingineri, rolul dumneavoastră principal este acela de a face mai uşoară viaţa utilizatorilor -
sarcină grea şi plină de provocări, dar deseori, din fericire, şi de satisfacţii. Dumneavoastră construiţi podurile şi drumurile care
îi aduc pe oameni mai aproape de destinaţii şi de scopuri - iar aceste structuri trebuie să fie solide, fiabile şi eficiente.
ÎNCEPUTUL
PROVOCAREA PROGRAMATORULUI
În filmul Marele canion un tată îşi învaţă fiul de 15 ani să conducă maşina şi îi spune:„O curbă la stânga în Los Angeles
este unul dintre cele mai dificile lucruri pe care trebuie să le înveţi în viaţă". Acelaşi lucru l-ar fi putut spune şi despre
programarea sub Windows. Nu mă refer aici anume la tehnicile de programare sub Windows - acest subiect neplăcut va fi
abordat abia începând din capitolul următor; mă gândesc mai mult la filozofia de proiectare a programelor, care uneori vă
obligă să „vă daţi peste cap" ca să faceţi lucrurile mai uşoare pentru utilizatori. Acesta este un concept relativ nou.
În primele zile ale calculatoarelor, utilizatorii erau şi programatori. Primele programe lucrau cam în felul următor:
înghiţeau nişte date, le măcinau puţin, apoi scuipau ceva pe hârtie. Utilizatorii naivi nici nu intrau în calcule. Chiar şi atunci
când programele au devenit puţin mai interactive şi au permis folosirea unei linii de comandă pe un monitor video, utilizatorii
erau nevoiţi să reţină o mulţime de comenzi şi de opţiuni criptice. Probabil adevărata revoluţie în proiectarea programelor
pentru calculator au constituit-o primele procesoare de texte (WordStar, de exemplu) şi primele programe de calcul tabelar
(VisiCalc) interactive, ce includeau forme primitive ale elementului fundamental de proiectare a interfeţelor moderne. Desigur,
este vorba despre meniuri. Meniurile din aceste prime aplicaţii interactive nu erau prea bine implementate, dar ideea apăruse şi
încet-încet a luat forme tot mai complexe. Privind retrospectiv, meniul pare acum un lucru elementar: un mijloc prin care
utilizatorului îi sunt prezentate toate posibilităţile programului. Desigur, pe atunci, lipsa memoriei restrângea posibilităţile
programatorilor de a crea o interfaţă cu utilizatorul prea sofisticată. Programele neprietenoase sunt mai scurte şi mai uşor de
scris; programele prietenoase cu utilizatorul sunt mari şi dificil de conceput.
Principiul NNEMBDOMG („Nimic Nu Este Mai Bun Decât O Masă Gratuită") este aplicabil şi aici, dar cineva trebuie să
facă şi lucrurile grele. Ca programator, dumneavoastră aţi ales să fiţi acel „cineva". Din fericire, o mare parte din lucrurile grele
au fost deja făcute de proiectanţii şi programatorii sistemului de operare Microsoft Windows 95. Aceşti eroi necunoscuţi au
implementat o parte din codul necesar pentru crearea obiectelor care formează interfaţa modernă cu utilizatorul şi pentru
afişarea rezultatelor programelor, folosind text formatat şi elemente grafice. Făcând aceste lucruri, ei au creat şi o interfaţă
pentru programe de aplicaţii (API - application programming interface) care îi poate intimida la început pe programatorii care
folosesc pentru prima dată mediul Windows. Nu este ceva specific sistemului de operare Windows - acest lucru este valabil
pentru orice interfaţă grafică modernă.
Mai demult se spunea că unui programator îi trebuie aproximativ 6 luni ca să poată scrie un program sub Windows. (Eu
glumesc uneori spunând că, folosind cartea mea, această perioadă ar putea fi redusă la 26 de săptămâni sau chiar la 180 de
zile.) În ultimii ani Windows a devenit un sistem de operare foarte complex, dar în acelaşi timp au apărut şi instrumente de
lucru care vă ajută în părţile mai grele, aşa că regula celor 6 luni probabil este încă aplicabilă. Vă spun aceste lucruri pentru că
nu vreau să vă simţiţi incompetent dacă nu „prindeţi" totul de la început. Dacă nu sunteţi obişnuit cu programarea în medii
grafice, Windows poate părea foarte ciudat. Cu timpul însă vă veţi obişnui.
REGULI DE BAZĂ
În această carte voi încerca să vă învăţ ceea ce eu numesc programare „clasică" sub Windows. În exemplele de programe
din această carte folosesc „bătrânul" limbaj de programare C (nu C++) şi interfaţa brută pentru programele de aplicaţii (API),
fără să apelez la funcţii de împachetare („wrappers") care maschează interfaţa API sub alte interfeţe mai simple. În ciuda
avantajelor pe care Windows 95 le oferă faţă de versiunile anterioare ale sistemului de operare, majoritatea programelor din
această carte nu sunt cu mult diferite de programele scrise pentru versiunea Microsoft Windows 1.0 acum 10 ani.
Dintr-un anumit punct de vedere, această carte prezintă un mod mai dificil de programare sub Windows - dar, în acelaşi
timp, cel mai puternic şi cel mai flexibil. Nu puteţi să cereţi mai mult sistemului de operare Windows pe nici o altă cale. Mai
mult, dacă învăţaţi programarea clasică sub Windows, folosind limbajul C şi interfaţa API brută, puteţi să înţelegeţi mai bine
modul în care interacţionează aplicaţia dumneavoastră cu sistemul de operare, iar această informaţie se dovedeşte utilă în multe
cazuri.
Deşi voi vorbi aici despre programarea clasică sub Windows, nu vă recomand să vă limitaţi la aceasta. În prezent aveţi la
dispoziţie diferite opţiuni care pot face programarea sub Windows mai uşoară. O variantă populară este limbajul C++, folosit,

27.04.21 15:58 pag. 2 din 22


în general, împreună cu biblioteci de clase precum Microsoft Foundation Classes (MFC) sau Borland Object Windows Library
(OWL). Alte variante sunt Microsoft Visual Basic sau Borland Delphi. De asemenea, există produse de generare a codului care
fac mai uşoară munca de programare. Puteţi chiar să creaţi aplicaţii Windows folosind limbaje script simple, precum limbajul
ToolBox al firmei Asymetrix.
Nu vă pot spune care dintre aceste variante este cea mai bună; depinde de aplicaţia pe care o scrieţi şi de cât de mult vreţi
să sacrificaţi izolându-vă de mediul în care lucraţi.
Un alt subiect pe care nu îl voi aborda în această carte este folosirea unor medii de dezvoltare interactivă (IDE - interactive
development environment), precum Microsoft Visual C++ versiunea 4.0. Aceste medii de lucru vă ajută deseori în operaţiile de
creare a resurselor (cum ar fi meniurile şi casetele de dialog), generând fişiere de construcţie (make files) şi oferindu-vă un
mediu integrat pentru scrierea, compilarea, rularea şi depanarea programelor. Nu am nimic împotriva mediilor de dezvoltare
interactivă. Ba chiar cred că sunt foarte bune. Totuşi, folosirea acestora mai degrabă vă împiedică decât vă ajută să învăţaţi
programarea clasică sub Windows. Pe scurt, nu vreau să vă învăţ cum să completaţi casete de dialog IDE, ci vreau să vă învăţ
cum să proiectaţi propriile dumneavoastră casete de dialog şi cum să prelucraţi intrările acestora.
Din acest motiv, codul de exemplificare din această carte este prezentat ca şi cum ar fi creat într-un editor de texte obişnuit
şi compilat din „demodata" linie de comandă. Acest lucru va deveni evident atunci când veţi ajunge la prezentarea fişierelor
script de resurse (resource script), care conţine descrierea sub formă de text a meniurilor, casetelor de dialog şi a altor resurse.
Fişierele script de resurse din această carte sunt scrise astfel încât să poată fi citite cu uşurinţă, lucru care nu este de obicei
valabil şi pentru fişierele de resurse generate de un mediu de dezvoltare. Am făcut acest lucru deoarece vreau să înţelegeţi ce
înseamnă fiecare instrucţiune din fişierul de resurse. Despre fişierele de construcţie (make files) - acele fişiere care conţin
instrucţiunile pentru compilarea codului sursă şi editarea legăturilor din program pentru crearea fişierului executabil - se ştie că
sunt lungi şi complexe atunci când sunt generate de un mediu de dezvoltare. Ale mele sunt scurte şi simple, şi nu-mi cer scuze
pentru acest lucru! Singurele resurse din această carte care nu sunt de tip text sunt pictogramele, indicatoarele de mouse şi
imaginile bitmap care prin natura lor trebuie create cu instrumente de lucru specializate.
Avantajul acestui mod de abordare este faptul că puteţi să copiaţi fişierele sursă pe hard-disc, să deschideţi o fereastră MS-
DOS ca să ajungeţi în linia de comandă, să rulaţi fişierul de construcţie ca să creaţi programul executabil şi să rulaţi programul
direct din linia de comandă.
Majoritatea programelor din această carte sunt foarte scurte, scopul lor fiind unul de ilustrare a câtorva concepte
importante. Unele dintre ele sunt chiar reduse la elementele de bază. Programele-exemplu sunt numai nişte instrumente cu rol
didactic, nu sunt modele reale pentru programe complete sub Windows. De exemplu, orice program sub Windows ar trebui să
aibă o pictogramă unică; foarte puţine dintre programele din această carte au o pictogramă, deoarece aceasta nu ar face decât să
aglomereze programul. De asemenea, ar trebui ca toate şirurile de text folosite de un program să fie stocate într-un fişier script
de resurse, pentru a facilita traducerea programului în alte limbi. Şi această abordare ar aglomera însă programele şi ar face mai
greu de înţeles ideea ilustrată de program. Din experienţă vă pot spune că, cu cât programul este mai scurt, cu atât şansele lui la
cititor sunt mai mari.
Această carte nu poate să acopere toate aspectele programării sub Windows 95. De asemenea, ea nu reprezintă un
înlocuitor pentru documentaţia oficială. Chiar şi după ce veţi parcurge această carte, va fi nevoie să mai studiaţi documentaţia
Windows privind caracteristicile şi apelurile de funcţii ale sistemului de operare.
Ultima caracteristică a acestei cărţi pe care vreau să o subliniez este faptul că nu am insistat asupra aspectelor
„nedocumentate" sau „neautorizate" ale programării sub Windows 95. Deşi uneori astfel de informaţii pot fi interesante, cred
că ele nu sunt semnificative decât pentru cele mai ciudate aplicaţii sub Windows. Pe măsură ce am căpătat mai multă
experienţă în programare, am învăţat să nu mă bazez pe detaliile de implementare, deoarece acestea se pot schimba în
versiunile ulterioare ale sistemului de operare. În schimb, am încercat să folosesc interfaţa API ca şi cum aceasta ar fi descrisă
complet de documentaţia tehnică. Acest lucru nu este întotdeauna adevărat, desigur, şi există deseori aspecte despre care nu se
pomeneşte nimic în documentaţie. De asemenea, mai există şi erori de programare. Nu voi ignora astfel de probleme.
UN SCURT ISTORIC AL SISTEMULUI DE OPERARE WINDOWS
Curând după apariţia pe piaţă a calculatorului IBM PC în toamna anului 1981, a devenit evident că sistemul de operare
predominant pentru calculatoarele PC şi compatibile va fi MS-DOS (prescurtarea de la Microsoft Disk Operating System).
Primele versiuni ale sistemului de operare MS-DOS ofereau utilizatorului o interfaţă în linie de comandă şi comenzi precum
DIR şi TYPE. Sistemul de operare putea să încarce programe în memorie şi oferea acestor programe servicii pentru accesul la
fişiere, citirea tastaturii, scrierea pe ecran (numai în mod caracter) şi la portul de imprimantă. Datorită memoriei insuficiente şi
posibilităţilor reduse ale componentelor hardware, mediile grafice sofisticate au întârziat să apară. Firma Apple Computers a
prezentat o soluţie lansând în ianuarie 1983 sistemul de operare Lisa, care însă nu a avut o soartă prea fericită, şi apoi a stabilit
în ianuarie 1984 un standard pentru mediile grafice, prezentând sistemul de operare Macintosh, care (în ciuda faptului că ocupă
un segment de piaţă în descreştere) este considerat a fi etalonul în domeniul mediilor grafice.
Crearea sistemului de operare Windows a fost anunţată de Microsoft Corporation în noiembrie 1983 (după Lisa, dar
înainte de Macintosh) ş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.
Versiunea Windows 2.0 a fost lansată în noiembrie 1987. Această versiune include câteva modificări asupra interfeţei cu
utilizatorul. Cea mai semnificativă dintre acestea este folosirea ferestrelor suprapuse în locul ferestrelor alăturate din versiunile
Windows 1.x. De asemenea. Windows 2.0 include unele îmbunătăţiri ale interfeţei cu mouse-ul şi cu tastatura, în special legate
de meniuri şi de casetele de dialog.

27.04.21 15:58 pag. 3 din 22


Pană în acest moment, Windows folosea procesorul Intel 8086 sau Intel 8088 în „mod real" pentru a obţine accesul la 1
megaoctet de memorie. Windows/386 (lansat la puţin timp după Windows 2.0) folosea modul „virtual 86" al
microprocesorului Intel 80386 ca să ruleze în ferestre, simultan, mai multe programe MS-DOS care aveau acces direct la
hardware. Pentru simetrie, versiunea Windows 2.1 a fost redenumită Windows/286.
Versiunea Windows 3.0 a fost prezentată pe data de 22 mai 1990. Această versiune le îngloba pe cele anterioare -
Windows/286 şi Windows/386 - într-un singur produs. Cea mai importantă modificare adusă de Windows 3.0 a fost acceptarea
modului de lucru protejat al microprocesoarelor Intel 80286, 80386 şi 80486. Acest mod de lucru a permis sistemului de
operare şi aplicaţiilor Windows accesul la 16 megaocteţi de memorie. Programele de tip shell pentru rularea programelor şi
întreţinerea fişierelor au fost complet revizuite. Windows 3.0 a fost prima versiune care s-a bucurat de un succes deplin,
devenind ceva obişnuit pe calculatoarele tuturor utilizatorilor, atât în birouri, cât şi acasă. Versiunea Windows 3.1 a fost lansată
în aprilie 1992. Printre modificările importante ale caracteristicilor se numără includerea tehnologiei TrueType pentru fonturi
(ceea ce a permis folosirea sub Windows a fonturilor scalabile), a tehnologiei multimedia (sunet şi muzică), a tehnologiei OLE
şi a casetelor de dialog comune. De asemenea. Windows 3.1 rulează numai în mod protejat şi are nevoie de un procesor 80286
sau 80386 cu cel puţin l megaoctet de memorie.
În orice istoric Windows ar trebui să fie menţionat şi sistemul de operare OS/2, o alternativă la MS-DOS şi Windows,
dezvoltat iniţial de Microsoft în colaborare cu IBM. Versiunea OS/2 1.0 (numai în mod caracter) a fost lansată la sfârşitul
anului 1987 şi rula pe microprocesoarele Intel 80286 sau mai noi. Mediul grafic Presentation Manager (PM) a apărut odată cu
versiunea OS/2 1.1 în octombrie 1988. PM a fost proiectat iniţial ca o variantă în mod protejat a mediului Windows, dar
interfaţa API s-a modificat atât de mult încât producătorii software nu au putut să susţină ambele platforme.
În septembrie 1990 conflictele dintre Microsoft şi IBM s-au acutizat şi fiecare a pornit pe propriul drum. IBM a preluat
sistemul de operare OS/2, iar Microsoft a declarat că în centrul strategiei proprii de dezvoltare a sistemelor de operare se va
situa Windows. Deşi OS/2 are încă admiratori înfocaţi, acest sistem de operare nu a ajuns nici pe departe la popularitatea atinsă
de Windows.
Windows NT, lansat în iulie 1993, a fost prima versiune Windows care acceptă modelul de programare pe 32 de biţi al
microprocesoarelor Intel 80386, 80486 şi Pentium. Windows NT foloseşte un spaţiu de adrese simplu pe 32 de biţi şi numere
întregi pe 32 de biţi. De asemenea Windows NT este portabil şi poate rula pe mai multe staţii de lucru de tip RISC.
Windows 95 (care a purtat anterior numele de cod Chicago şi este numit uneori Windows 4.0) a fost lansat în august 1995.
Ca şi Windows NT, Windows 95 acceptă modelul de programare pe 32 de biţi (şi, ca urmare, are nevoie de un microprocesor
80386 sau mai nou). Deşi Windows 95 nu egalează performanţele sistemului de operare Windows NT în anumite aspecte cum
ar fi securitatea sau portabilitatea pe calculatoarele RISC, Windows 95 are avantajul că poate fi rulat pe calculatoarele cu cel
puţin 4 megaocteţi de memorie.
Evident, programele scrise pentru versiunile pe 16 biţi ale sistemului de operare Windows (apărute înainte de Windows 95
şi Windows NT) nu sunt direct portabile către versiunile mai noi, pe 32 de biţi; în capitolele următoare vom discuta unele
dintre modificările care sunt necesare pentru a realiza acest lucru.
Microsoft a încercat să diferenţieze platformele prin definirea unor seturi de interfeţe API. Interfaţa Win16 API este
acceptată de versiunea Windows 3.1. Interfaţa Win32 API este acceptată de versiunile Windows 95 şi Windows NT. Dar
aşteptaţi - mai este ceva. Microsoft permite programatorilor să scrie programe pe 32 de biţi pentru Windows 3.1; apelurile de
funcţii pe 32 de biţi au fost convertite în apeluri pe 16 biţi de o bibliotecă cu legături dinamice (DLL). Această interfaţa API a
fost numită Win32s („s" de la „subset", deoarece această interfaţa acceptă numai funcţiile din Win16). Pentru o perioadă,
interfaţa API din Windows 95 a fost numită Win32c („c" de la „compatibil") dar acest nume a fost abandonat mai târziu.
În acest moment se consideră că atât Windows NT cât şi Windows 95 acceptă interfaţa Win32 API. Cu toate acestea,
fiecare dintre cele două sisteme de operare are unele caracteristici pe care celălalt sistem de operare nu le are. Partea comună
fiind considerabilă, scrierea programelor care rulează sub ambele sisteme este totuşi posibilă. De asemenea, o părere larg
răspândită susţine că cele două produse vor fi înglobate într-unul singur, în viitor.
ESTE TIMPUL SĂ ÎNCEPEM
OK, prima zi de şcoală se apropie de sfârşit. În capitolul următor vom începe studierea unor exemple de cod. Pentru
aceasta, trebuie să aveţi instalat pe calculator programul Microsoft Visual C++ versiunea 4.0. În fişierul AUTOEXEC.BAT
trebuie să includeţi instrucţiunea:CALL \HSDEV\BIN\VCVARS32.BAT
Acest fişier este inclus în Visual C++ şi stabileşte o serie de variabile de mediu folosite pentru compilarea programelor C
din linia de comandă. Aceste variabile precizează căile de acces la fişierele antet, la fişierele bibliotecă şi la fişierele binare. De
asemenea, tot în fişierul AUTOEXEC.BAT trebuie să includeţi o a doua instrucţiune CALL ca să rulaţi fişierul MSC.BAT,
prezentat în Figura 1-1. Acest fişier defineşte variabilele de mediu folosite de fişierele de construcţie, din capitolele care
urmează.
REM -------------------------------------------------------------
REM MSC.BAT -- Set up environment for Microsoft C/C++ 7.0 NMAKE
REM -------------------------------------------------------------
SET CC=cl
SET CFLAGS=-c -DSTRICT -G3 -Ow -W3 -Zp -Tp
SET CFLAGSMT=-c -DSTRICT -G3 -MT -Ow -W3 -Zp -Tp
SET LINKER=link
SET GUIFLAGS=-SUBSYSTEM:windows
SET DLLFLAGS=-SUBSYSTEM:windows -DLL
SET GUILIBS=-DEFAULTLIB:user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib
SET RC=rc

27.04.21 15:58 pag. 4 din 22


SET RCVARS=-r -DWIN32
Figura 1.1. Rulaţi fişierul de mai sus ca să compilaţi programele din această carte.

Fişierul MSC.BAT poate fi găsit în directorul CHAP01 de pe discheta care însoţeşte această carte.
Voi descrie rolul instrucţiunilor de mai sus în capitolele care urmează.

CAPITOLUL 2. HELLO, WINDOWS 95!


Dacă programaţi pentru prima dată sub un mediu grafic, aşa cum este Microsoft Windows 95, probabil veţi considera că
aveţi de-a face cu ceva cu totul nou. Windows are reputaţia de a fi un program simplu pentru utilizator, dar dificil pentru
programatori. Este normal ca noii-veniţi să se simtă neajutoraţi în faţa arhitecturii Windows şi a structurii aplicaţiilor care
rulează sub acest sistem de operare. Chiar dacă vi se întâmplă şi dumneavoastră, nu trebuie să credeţi că vă lipseşte acea parte
a creierului care v-ar permite să deveniţi un programator Windows de succes. Confuzia iniţială este ceva normal şi să nu
credeţi pe nimeni care vă spune altceva.
Programarea sub Windows este destul de ciudată, greoaie, încurcată şi uneori îţi torturează creierii. Lucrurile nu sunt
simple şi s-ar putea să fie nevoie de ceva timp până veţi putea să strigaţi „Evrika!". O estimare obişnuită spune că un
programator, în general, are nevoie de o perioadă de învăţare de aproximativ 6 luni înainte de a scrie un program sub Windows
şi, chiar şi după aceea, mai sunt lucruri de învăţat. Speranţa mea este că această carte vă va ajuta să reduceţi cu câteva
săptămâni (poate chiar luni) perioada iniţială de învăţare.
S-ar putea să vă întrebaţi „Dacă programarea sub Windows este atât de dificilă, de ce să ne mai batem capul?"
Răspunsul cel mai simplu este tot o întrebare: „Aveţi de ales?". Sistemul de operare Windows a deschis noi posibilităţi,
aşa încât programarea pentru MS-DOS (în mod caracter sau în mod grafic) nu mai este posibilă. Dacă scrieţi aplicaţii
comerciale, s-ar putea ca produsul dumneavoastră să fie ignorat dacă nu este scris pentru Windows. Dacă scrieţi programe
speciale pentru o firmă, utilizatorilor (sau poate chiar angajaţilor) dumneavoastră nu le va conveni faptul că programul nu se
integrează printre celelalte aplicaţii pentru Windows pe care le folosesc.
Dar există şi alte motive ca să alegeţi ca platformă sistemul de operare Windows.

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.
Interfaţa grafică cu utilizatorul (GUI)
Windows este o interfaţă grafică cu utilizatorul (GUI - graphical user interface), numită uneori şi „interfaţă vizuală" sau
„mediu grafic cu ferestre" („graphical windowing environment"). Conceptele care stau la baza acestui tip de interfaţă cu
utilizatorul datează de la mijlocul anilor '70, având la origine munca de pionierat a celor de la Centrul de cercetare al firmei
Xerox de la Palo Alto (PARC - Palo Alto Research Center) pentru calculatoare precum Alto şi Star şi medii ca Smalltalk.
Ideile au fost readuse în prim-plan şi popularizate de Apple Computer, Inc., mai întâi cu ghinionistul sistem de operare Lisa şi
un an mai târziu cu Macintosh, un sistem de operare de succes, prezentat în ianuarie 1984.
De la apariţia sistemului de operare Macintosh, interfeţele grafice au cunoscut o răspândire extraordinară în industria
calculatoarelor. Acum este evident faptul că interfaţă grafică cu utilizatorul este (citându-l pe Charles Simonyi de la Microsoft)
singurul „consens general" important din industria calculatoarelor personale.
Conceptele şi fundamentele GUI
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 (WYSIWYG - what you see is what
you get).
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.
Consecvenţa privind interfaţă cu utilizatorul
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.

27.04.21 15:58 pag. 5 din 22


După ce învăţaţi să folosiţi un program Windows, veţi fi capabil deja să utilizaţi orice alt program pentru Windows.
Meniurile şi casetele de dialog permit utilizatorului să experimenteze diferite funcţii ale programului şi să îi exploreze
posibilităţile. Majoritatea programelor Windows au interfaţă atât cu mouse-ul, cât şi cu tastatura. Deşi majoritatea funcţiilor
unui program pentru Windows pot fi controlate şi cu ajutorul tastaturii, mouse-ul este deseori mai convenabil pentru diferite
sarcini.
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.
Avantajul oferit de multitasking
Deşi unii continuă încă să se întrebe dacă multitaskingul este cu adevărat necesar pe un calculator folosit de un singur
utilizator, majoritatea utilizatorilor se bucură de existenţa acestei facilităţi şi pot să-i folosească avantajele. Acest lucru a fost
dovedit de popularitatea unor programe rezidente în memoria RAM sub MS-DOS, precum Sidekick. Deşi programele
derulante, în sens strict, nu sunt acelaşi lucru cu multitaskingul, acestea permit comutarea rapidă de la un context la altul,
proces care implică multe dintre conceptele multitaskingului.
Sub Windows, toate programele sunt, de fapt, programe rezidente în memoria RAM. Mai multe programe Windows pot fi
afişate şi rulate în acelaşi timp. Fiecare program ocupă o fereastră dreptunghiulară de pe ecran. Utilizatorul poate să mute
ferestrele pe ecran, poate să le schimbe dimensiunile, să treacă de la un program la altul şi să transfere date de la un program la
altul. Deoarece aceasta creează uneori aspectul spaţiului de lucru de pe un birou (desktop) - pe vremea când birourile nu erau
dominate încă de calculator - se spune uneori despre Windows că foloseşte pentru afişarea mai multor programe „metafora
suprafeţei de lucru (desktop)".
Versiunile anterioare ale sistemului de operare Windows foloseau un tip de multitasking numit „necontrolat". Aceasta
înseamnă că Windows nu folosea ceasul sistemului ca să aloce timpi de procesare diferitelor programe care rulează în sistem.
Programele trebuie să cedeze voluntar controlul, astfel încât alte programe să-şi poată continua execuţia. În Windows 95
multitaskingul este controlat şi programele se pot împărţi în mai multe fire de execuţie, care par să ruleze în acelaşi timp.
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.
Chiar şi prima versiune Windows, rulată pe un procesor 8088, putea să gestioneze memoria în acest mod. Ţinând seama de
faptul că microprocesorul 8088 lucra în mod real, aceasta trebuie privită ca o realizare uimitoare a ingineriei software.
Programele rulate sub Windows pot să depăşească memoria existentă; un program poate conţine mai mult cod decât încape în
memorie la un moment dat. Windows poate să elimine din memorie o parte din cod şi ulterior să reîncarce codul respectiv din
fişierul executabil de pe hard-disc. Un utilizator poate rula simultan mai multe copii ale aceluiaşi program, numite „instanţe";
toate aceste instanţe folosesc acelaşi cod din memorie. Programele rulate sub Windows pot să partajeze rutine stocate în alte
fişiere numite „biblioteci cu legături dinamice" (dynamic link libraries). Windows conţine un mecanism de editare a legăturilor
dintre program şi rutinele din bibliotecile cu legături dinamice, în timpul execuţiei. Chiar sistemul de operare este, în esenţă, o
colecţie de biblioteci cu legături dinamice.
În acest fel, chiar şi în Windows 1.0, limita de 640 kiloocteţi impusă de arhitectura calculatoarelor personale a fost extinsă
fără să fie nevoie de memorie suplimentară. Dar Microsoft nu s-a oprit aici: Windows 2 a permis aplicaţiilor Windows accesul
la memoria expandată (EMS) iar Windows 3 rulează în mod protejat, ceea ce permite aplicaţiilor Windows accesul la 16
megaocteţi de memorie. Windows 95 a depăşit toate aceste restricţii, fiind un sistem de operare pe 32 de biţi, cu un spaţiu de
memorie plată.
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.


Acest tip de multitasking se mai numeşte şi „multitasking cooperativ", (n.t)

27.04.21 15:58 pag. 6 din 22


Dacă optaţi pentru Windows...
Programarea sub Windows 95 este o propunere de tip „totul sau nimic". De exemplu, nu puteţi să scrieţi aplicaţii pentru
MS-DOS şi să utilizaţi facultăţile oferite de Windows numai pentru anumite grafice. Dacă vreţi să aveţi acces la toate
posibilităţile pe care le are mediul Windows, trebuie să vă hotărâţi şi să scrieţi programe complete pentru Windows.
Logica acestei opţiuni va deveni evidentă după ce veţi afla mai multe despre structura unui program pentru Windows.
Toate componentele sistemului Windows sunt interconectate. Dacă vreţi să desenaţi ceva pe ecran aveţi nevoie de un element
numit „variabilă handle a unui context de dispozitiv". Pentru aceasta aveţi nevoie de o „variabilă handle a unei ferestre". Pentru
a o obţine, trebuie să creaţi o fereastră şi să fiţi pregătit să recepţionaţi „mesajele" trimise către fereastră. Pentru recepţionarea
şi prelucrarea mesajelor aveţi nevoie de o „procedură de fereastră". A face toate aceste operaţii înseamnă a scrie un program
pentru Windows. Nu puteţi să zburaţi decât dacă vă dezlipiţi de pământ.
Apelurile de funcţii
Windows 95 asigură suportul pentru mai mult de o mie de apeluri de funcţii pe care le pot folosi aplicaţiile. Este foarte
puţin probabil ca cineva să memoreze sintaxa tuturor acestor apeluri. Majoritatea programatorilor Windows petrec cea mai
mare parte din timpul de lucru căutând diferite apeluri de funcţii, în documentaţia scrisă sau în surse.
Fiecare funcţie Windows are un nume sugestiv, scris atât cu majuscule, cât şi cu minuscule, cum ar fi CreateWindow.
Această funcţie, aşa cum probabil v-aţi dat seama, creează o fereastră. Un alt exemplu: funcţia IsClipboardFormatAvailable
determină dacă în memoria temporară (clipboard) sunt stocate date într-un anumit format.
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. Puteţi să tipăriţi o copie a fişierelor antet
sau să folosiţi un browser pentru o căutare rapidă.
Î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 (DLL - dynamic link
libraries).
Atunci când rulaţi un program pentru Windows, interconectarea acestuia cu sistemul de operare se face printr-un proces
numit „legare dinamică" (dynamic linking). Un fişier executabil al unui program Windows conţine referinţe la diferite
biblioteci cu legături dinamice, pe care le foloseşte şi la funcţiile conţinute de acestea. Majoritatea bibliotecilor DLL se află în
subdirectorul SYSTEM din directorul Windows. Atunci când un program pentru Windows este încărcat în memorie, apelurile
de funcţii din program sunt rezolvate astfel încât să indice intrările funcţiilor din bibliotecile cu legături dinamice, care sunt şi
ele încărcate în memorie, dacă este nevoie.
Atunci când editaţi legăturile unui program ca să creaţi un fişier executabil, trebuie să editaţi şi legăturile cu bibliotecile
speciale „de import" furnizate de mediul de programare folosit. Aceste biblioteci de import conţin numele funcţiilor Windows
folosite în bibliotecile cu legături dinamice şi informaţii de referinţă pentru acestea. Programul de editare a legăturilor foloseşte
aceste informaţii ca să construiască în fişierul executabil tabelul folosit de Windows pentru rezolvarea apelurilor de funcţii
Windows la încărcarea programului.
Programarea orientată pe obiecte
Programarea sub Windows este un tip de programare orientată pe obiecte (OOP -object-oriented programming). Acest
lucru devine evident dacă vă gândiţi la obiectul pe care îl veţi folosi cel mai mult în Windows - obiectul care dă numele
sistemului de operare, obsedanta „fereastră".
Aşa cum am menţionat mai devreme, ferestrele sunt nişte suprafeţe dreptunghiulare de pe ecran. O fereastră primeşte
intrări de la tastatură sau de la mouse şi afişează rezultate în zona proprie de pe suprafaţa ecranului.
Fereastra unei aplicaţii conţine, de obicei, bara de titlu a programului, meniul, chenarul de dimensionare şi, eventual,
barele de derulare. Casetele de dialog sunt ferestre adiţionale. Mai mult, suprafaţa unei casete de dialog conţine întotdeauna
câteva ferestre suplimentare, numite „ferestre descendent" („child windows"). Ferestrele descendent apar sub forma butoanelor
de apăsare, a butoanelor radio, a casetelor de validare, a câmpurilor pentru introducerea textului, casetelor-listă şi a barelor de
derulare.
Utilizatorul vede ferestrele ca obiecte pe ecran şi poate acţiona direct asupra lor, apăsând un buton sau manipulând o bară
de derulare. Interesant este faptul că perspectiva programatorului este foarte asemănătoare cu cea a utilizatorului. Fereastra
recepţionează intenţiile utilizatorului sub forma unor „mesaje". De asemenea, ferestrele folosesc mesaje pentru comunicarea cu
alte ferestre.
Înţelegerea acestor mesaje este unul dintre pragurile pe care va trebui să le depăşiţi ca să ajungeţi programator Windows.
Arhitectura bazată pe mesaje
Atunci când am văzut pentru prima dată în acţiune o interfaţă grafică cu utilizatorul, am fost uimit. Demonstraţia includea
rularea unui procesor de texte rudimentar într-o fereastră. Procesorul de texte rearanja textul atunci când dimensiunile ferestrei
erau modificate.
Era evident că sistemul de operare manipula detaliile „logicii" de redimensionare a ferestrei şi că programul putea să
răspundă la această funcţie a sistemului. Dar de unde ştia programul că fereastra a fost redimensionată? Ce mecanism folosea
sistemul de operare ca să transmită această informaţie către fereastra programului? Experienţa pe care o aveam atunci nu mă
ajuta să înţeleg acest mod de funcţionare.
S-a dovedit că răspunsul la aceste întrebări este esenţial pentru înţelegerea arhitecturii folosite la construirea interfeţelor
grafice cu utilizatorul. În Windows, atunci când utilizatorul redimensionează o fereastră, sistemul de operare trimite

27.04.21 15:58 pag. 7 din 22


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." Sper că nu aţi luat ad-litteram sensul acestei propoziţii. Ce poate să
însemne acest lucru? Pentru că nu este vorba despre un sistem de poştă electronică, ci despre cod, cum poate un sistem de
operare să „trimită" mesaje către un program?
Atunci când am spus că „sistemul de operare trimite programului un mesaj" m-am referit la faptul că 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ă
Desigur, sunteţi obişnuit cu ideea că un program apelează funcţii ale sistemului de operare. Acest lucru este făcut de un
program atunci când, de exemplu, deschide un fişier de pe hard-disc. S-ar putea să nu fiţi la fel de obişnuit, însă, şi cu ideea că
sistemul de operare apelează o funcţie a programului. Totuşi, aceasta este o idee fundamentală a arhitecturii orientate pe
obiecte a sistemului de operare Windows 95.
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.
Mai precis, o fereastră este creată întotdeauna pe baza unei „clase de fereastră". Clasa specifică procedura de fereastră care
prelucrează mesajele trimise către fereastră. Folosirea unei clase de fereastră permite ca pe baza aceleiaşi clase să se creeze mai
multe ferestre care, ca urmare, folosesc aceeaşi procedură de fereastră. De exemplu, toate butoanele din toate programele
pentru Windows sunt create pe baza aceleiaşi clase de fereastră. Această clasă 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.
În programarea orientată pe obiecte, un „obiect" este o combinaţie de cod şi date. O fereastră este un obiect. Codul
obiectului este procedura de fereastră. Datele obiectului sunt informaţiile păstrate de fereastră şi informaţiile păstrate de
Windows pentru fiecare fereastră şi pentru fiecare clasă de fereastră existentă în sistem.
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.
Dacă simţiţi că această descriere excesiv de abstractă a arhitecturii Windows vă depăşeşte, s-ar putea să fi sosit momentul
să vedeţi concret cum fereastra, clasa de fereastră, procedura de fereastră, coada de mesaje şi mesajele trimise ferestrei se
integrează în contextul real al unui program.
Să-i dăm drumul!
PRIMUL DUMNEAVOASTRĂ PROGRAM WINDOWS
În cartea devenită clasică Limbajul de programare C, Brian Kernighan şi Dennis Ritchie încep descrierea limbajului C cu
de-acum faimosul program „Hello, world!":

include <stdio.h>

main ()
{
printf ("Hello, world\n");
}

În acest capitol vă voi prezenta un program asemănător, scris pentru Microsoft Windows 95. Programul se numeşte
HELLOWIN, afişează pe ecran şirul de caractere „Hello, Windows 95!" şi redă un fişier de sunet cu vocea mea rostind
aceleaşi cuvinte.
Dacă nu v-aţi prăbuşit atunci când aţi văzut pentru prima dată codul programului HELLOWIN, vă avertizez că are mai
mult de 80 de linii. Majoritatea acestor linii reprezintă cod de întreţinere (overhead code) şi veţi include un asemenea cod în
toate programele Windows pe care le veţi scrie.
În loc să ne întrebăm de ce programul „Hello, Windows 95!" este atât de lung şi de complex, haideţi să vedem de ce
programul „Hello, world!" tradiţional este atât de scurt şi de simplu.
Ce este greşit în acest program?
Modelul de afişare pentru programul „Hello, world!" şi pentru alte programe C tradiţionale este o componentă hardware
antică numită teleimprimator. Teleimprimatorul seamănă cu o maşină de scris cu o rolă de hârtie continuă. Într-un trecut nu
prea îndepărtat, programatorii stăteau în faţa unui astfel de teleimprimator şi scriau comenzi al căror „ecou" apărea pe hârtie.
Calculatorul răspundea la comenzi prin tipărirea răspunsurilor tot pe hârtie.
Odată cu apariţia terminalelor sistemelor mainframe şi a calculatoarelor personale, ideea teleimprimatorului a fost extinsă
şi pentru monitoarele video. Monitoarele video erau folosite ca un „teleimprimator de sticlă" care, pur şi simplu, derula
imaginea în momentul când textul scris ajungea în partea de jos a ecranului.

27.04.21 15:58 pag. 8 din 22


Cum poate programul tradiţional „Hello, world!" să afişeze text fără să îi comunice sistemului de operare la ce dispozitiv
de ieşire să fie afişat textul? Simplu, deoarece există un singur dispozitiv de ieşire - ecranul, folosit ca teleimprimator. Dacă
utilizatorul doreşte ca rezultatele să fie trimise în altă parte, trebuie să le redirecţioneze folosind linia de comandă.
Cum poate programul să afişeze text fără să îi comunice sistemului de operare în ce poziţie urmează să fie afişat acesta?
Textul este afişat întotdeauna acolo unde se află cursorul - de obicei pe următoarea linie după comanda de executare a
programului. Dacă vreţi să afişaţi mesajul „Hello, world!" în centrul ecranului, trebuie să folosiţi o serie de coduri dependente
de dispozitiv ca să poziţionaţi mai întâi cursorul în poziţia dorită.
Să presupunem că vreţi să rulaţi mai multe programe „Hello, world!" în acelaşi timp. Ce mizerie! Copiile programului se
vor amesteca unele cu altele. Teleimprimatorul nu furnizează nici o metodă de separare a ieşirilor de la mai multe programe
rulate simultan.
Un alt lucru interesant este faptul că textul „Hello, world!" rămâne pe ecran chiar şi după terminarea programului, în loc să
cureţe ecranul după terminare, programul lasă „urme" ale existenţei sale.
Programul „Hello, world!" este atât de simplu pentru că este proiectat pentru calculatoare mai simple şi pentru dispozitive
de ieşire mai simple. Nu numai că nu este ceea ce numim astăzi un produs software modern, dar nici nu se află măcar pe
acelaşi teren.
Fişierele programului HELLOWIN
Două dintre cele trei fişiere necesare pentru crearea programului HELLOWIN sunt prezentate în Figura 2-1. Acestea sunt
fişierul „de construcţie " HELLOWIN.MAK şi fişierul sursă HELLOWIN.C. Cel de-al treilea fişier este stocat pe discheta
ataşată cărţii, cu numele HELLOWIN.WAV şi conţine varianta sonoră a textului afişat de program.
#------------------------
# HELLOWIN.MAK make file
#------------------------
hellowin.exe : hellowin.obj
$(LINKER) $(GUIFLAGS) -OUT:hellowin.exe hellowin.obj $(GUILIBS)
hellowin.obj : hellowin.c
$(CC) $(CFLAGS) hellowin.c
/*------------------------------------------------------------
HELLOWIN.C -- Displays "Hello, Windows 95!" in client area
(c) Charles Petzold, 1996
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "HelloWin" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx (&wndclass) ;
hwnd = CreateWindow (szAppName, // window class name
"The Hello Program", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;

27.04.21 15:58 pag. 9 din 22


UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (iMsg)
{
// case WM_CREATE :
//PlaySound ("hellowin.wav", NULL, SND_FILENAME | SND_ASYNC) ;//
//return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
DrawText (hdc, "Hello, Windows 95! ", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
Figura 2-1. Programul HELLOWIN.
În Capitolul 9 veţi întâlni un alt tip de fişier frecvent folosit pentru programele Windows, numit „fişier script" („resource
script") şi având extensia .RC. Până acolo, majoritatea programelor, fiind mai simple, vor folosi un fişier de construcţie, un
fişier sursă şi, eventual, un fişier antet.
Aşa cum am menţionat anterior, cea mai mare parte din codul programului HELLOWIN.C este cod de întreţinere
(overhead code) inclus în aproape toate programele Windows. Nimeni nu se străduieşte să ţină minte sintaxa acestui cod; în
general, programatorii Windows creează un nou program copiind un program existent şi făcând modificările necesare în
acesta. Sunteţi liber să folosiţi în acest mod oricare dintre programele de pe discheta care însoţeşte cartea.
Dacă aţi instalat pe calculatorul dumneavoastră sistemul de operare Windows 95 si mediul Microsoft Visual C++ 4.0 şi aţi
rulat fişierul de comenzi VCVARS32.BAT inclus în Visual C++ şi fişierul de comenzi MSC.BAT prezentat în acest capitol, ar
trebui să puteţi crea fişierul executabil HELLOWIN.EXE cu comanda:
Hello, Windows 95!
NMAKE HELLOWIN.MAK
din linia de comandă MS-DOS.
Dacă totul merge bine, puteţi să rulaţi programul din linia de comandă MS-DOS cu comanda:
HELLOWIN
Programul creează o fereastră normală, prezentată în Figura 2-2. În centrul zonei client a ferestrei este afişat textul „Hello,
Windows 95!". Dacă aveţi pe calculator o placă de sunet, veţi auzi şi mesajul vorbit. (Iar dacă nu aveţi încă, ce mai aşteptaţi?)

Figura 2-2. Rularea programului HELLOWIN sub Windows 95.

27.04.21 15:58 pag. 10 din 22


De fapt, această fereastră are o mulţime de funcţii pentru cele numai 80 de linii de cod. Puteţi să „agăţaţi" bara de titlu cu
mouse-ul şi să mutaţi fereastra pe ecran sau, trăgând chenarul ferestrei, puteţi redimensiona fereastra. Atunci când fereastra îşi
schimbă dimensiunea, programul repoziţionează automat textul în noul centru al zonei client. Puteţi să executaţi clic pe butonul
de mărire a ferestrei (maximize) si fereastra va umple ecranul. Puteţi să executaţi clic pe butonul de micşorare a ferestrei
(minimize) şi fereastra va elibera ecranul. Toate aceste opţiuni pot fi apelate şi din meniul sistem. De asemenea, puteţi să
închideţi programul selectând opţiunea Close din meniul sistem, executând clic pe butonul de închidere a ferestrei din partea
dreaptă a barei de titlu sau executând dublu clic pe pictograma din partea stângă a barei de titlu.
Deşi s-ar putea să vă placă faptul că programul HELLOWIN are toate funcţiile unui program Windows normal, probabil
nu veţi fi la fel de fericit atunci când veţi examina codul sursă necesar pentru crearea programului. Dar haideţi să ne luăm
inima în dinţi şi să „disecăm" acest program bucată cu bucată.

Fişierul de construcţie
Pentru simplificarea compilării programelor Windows puteţi să folosiţi utilitarul NMAKE, inclus în setul de programe
Microsoft Visual C++ 4.0. De fiecare dată când vreţi să modificaţi ceva în codul sursă al programului HELLOWIN.C trebuie
să rulaţi programul NMAKE, aşa cum am arătat mai sus, ca să creaţi un fişier executabil actualizat.
Un fişier de construcţie este format din una sau mai multe secţiuni, fiecare începând cu un rând de text aliniat la stânga,
care conţine un fişier destinaţie, urmat de două puncte şi de unul sau mai multe fişiere dependente. Această linie este urmată de
una sau mai multe linii de comandă aliniate mai în interior. Aceste comenzi creează fişierul destinaţie din fişierele dependente.
Dacă data sau ora de modificare ale oricăruia dintre fişierele dependente este ulterioară datei sau orei de creare a fişierului
destinaţie, programul NMAKE execută liniile de comandă.
În mod normal, programul NMAKE actualizează numai fişierul destinaţie din prima secţiune a fişierului de construcţie.
Totuşi, dacă unul sau mai multe dintre fişierele dependente sunt la rândul lor fişiere destinaţie în alte secţiuni ale fişierului de
construcţie, NMAKE le va actualiza întâi pe acestea.
Fişierul HELLOWIN.MAK conţine două secţiuni. Prima secţiune rulează programul de editare a legăturilor dacă
HELLOWIN.OBJ a fost modificat mai recent decât HELLOWIN.EXE. A doua secţiune rulează compilatorul C dacă
HELLOWIN.C a fost modificat mai recent decât HELLOWIN.OBJ. Deoarece fişierul HELLOWIN.OBJ este fişier dependent
în prima secţiune şi fişier destinaţie în a doua secţiune, programul NMAKE va verifica mai întâi dacă HELLOWIN.OBJ
trebuie să fie actualizat înainte ca fişierul HELLOWIN.EXE să fie re-creat. În această situaţie, fişierul de construcţie este de
fapt executat de la un capăt la celălalt. Rularea compilatorului C creează modulul obiect HELLOWIN.OBJ din fişierul sursă
HELLOWIN.C. Rularea programului de editare a legăturilor creează fişierul executabil HELLOWIN.EXE din
HELLOWIN.OBJ.
În Capitolul 1 am arătat cum sunt furnizaţi macro-identificatorii din fişierul de construcţie de către variabilele de mediu
stabilite de fişierele de comenzi prezentate în capitolul respectiv. Aceasta înseamnă stabilirea unor indicatori flag de compilare
şi a numelor de biblioteci folosite de programul de editare a legăturilor. Dacă doriţi amănunte, reveniţi la secţiunea respectivă
din Capitolul 1.
Fişierul sursă C
Al doilea fişier prezentat în Figura 2-1 este HELLOWIN.C, fişierul care conţine codul sursă C. Va trece un timp pană
când vă veţi da seama că acest program este într-adevăr scris în limbaj C!
Înainte de a intra în detalii, haideţi să aruncăm o privire generală asupra fişierului HELLOWIN.C. Fişierul conţine numai
două funcţii: WinMain şi WndProc. 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.
WndProc este „procedura de fereastră" a ferestrei create de programul HELLOWIN. Orice fereastră - indiferent dacă este
fereastra principală a aplicaţiei sau fereastra unui mic buton de apăsare - are o procedură de fereastră. Procedura de fereastră
este un mod de încapsulare a codului care răspunde intrărilor (în general de la tastatură şi de la mouse) şi afişează elementele
grafice pe ecran. Aşa cum veţi vedea, procedura de fereastră face acest lucru prin prelucrarea „mesajelor" trimise către
fereastră. Pentru moment nu vă bateţi capul cu modul de funcţionare a acestui mecanism. Veţi avea destul timp să vă luptaţi cu
acest concept.
Nici o instrucţiune din fişierul HELLOWIN.C nu apelează direct funcţia WndProc: WndProc este apelată de sistemul de
operare Windows. Totuşi, în funcţia WinMain apare o referire la funcţia WndProc, acesta fiind motivul pentru care WndProc
este declarată în partea de început a programului, înainte de WinMain.
Apelurile de funcţii Windows
HELLOWIN 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 programul HELLOWIN:
 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ă.

27.04.21 15:58 pag. 11 din 22


 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.
Aceste funcţii sunt documentate în cărţi şi în sursele incluse de compilator şi sunt declarate în diferite fişiere antet incluse
în fişierul WINDOWS.H.
Identificatori cu majuscule
Veţi observa că în fişierul HELLOWIN.C sunt folosiţi câţiva identificatori scrişi cu majuscule. Aceşti identificatori sunt
definiţi în fişierele antet din Windows. Câţiva dintre ei conţin un prefix de două sau trei litere, urmat de o liniuţă de subliniere:
CS_HREDRAW DT_VCENTER WM_CREATE
CS_VREDRAW IDC_ARROW WM_DESTROY
CW_USEDEFAULT IDI_APPLICATION WM_PAINT
DT_CENTER SND_ASYNC WS_OVERLAPPEDWINDOW
DT_SINGLELINE SND_FILENAME
Acestea sunt simple constante numerice. Prefixul indică o categorie generală căreia îi aparţine constanta respectivă, aşa
cum se arată în tabelul următor:

Prefix Categorie
CS Opţiune pentru stilul clasei
IDI Număr de identificare pentru o pictogramă
IDC Număr de identificare pentru un cursor
WS Stil de fereastră
CW Opţiune de creare a unei ferestre
WM Mesaj de fereastră
SND Opţiune pentru sunete
DT Opţiune de desenare a textului

În mod normal nu este nevoie să reţineţi nici o constantă numerică pentru scrierea unui program pentru Windows. De fapt,
toate constantele numerice folosite în Windows au un identificator definit în fişierele antet.
Noi tipuri de date
Alţi identificatori folosiţi în fişierul HELLOWIN.C sunt noi tipuri de date, definite în fişierele antet cu ajutorul
instrucţiunii typedef sau #define. Aceste definiţii au fost stabilite iniţial pentru a simplifica tranziţia programelor Windows
originale de la sistemele pe 16 biţi originale la viitoarele sisteme pe 32 de biţi, sau la cele bazate pe o altă tehnologie. Această
tranziţie nu s-a făcut chiar atât de uşor şi de transparent cum ar fi crezut unii la momentul respectiv, dar conceptul este destul
de bun.
Uneori aceste noi tipuri de date sunt doar abrevieri mai uşor de folosit. De exemplu, tipul de date UINT folosit pentru al
doilea parametru al funcţiei WndProc este prescurtarea de ia unsigned int, ceea ce în Windows 95 înseamnă o valoare întreagă
pe 32 de biţi. Tipul de date PSTR folosit pentru al treilea parametru al funcţiei WinMain este un pointer la un şir de caractere,
adică înlocuieşte tipul char*.
Alte tipuri de date nu sunt la fel de evidente. De exemplu, al treilea şi al patrulea parametri ai funcţiei WndProc sunt
definiţi cu tipurile de date WPARAM si LPARAM. Originea acestor nume ţine oarecum de istoria sistemului Windows: pe
când Windows era un sistem pe 16 biţi, al treilea parametru al funcţiei WndProc era definit ca WORD, adică un număr întreg
scurt, fără semn, pe 16 biţi (unsigned short) iar al patrulea parametru era definit ca LONG, adică un număr întreg pe 32 de biţi
(long) - de aici provenind prefixele „W" şi „L" ale cuvântului „PARAM". În Windows 95, WPARAM este definit ca UINT iar
LPARAM este definit ca LONG (care este chiar tipul long din C), aşa că ambii parametri ai procedurii de fereastră sunt valori
pe 32 de biţi. Deoarece tipul de date WORD este definit în Windows 95 ca un număr întreg fără semn pe 16 biţi (unsigned
short), prefixul „W" din WPARAM este oarecum impropriu şi poate crea confuzii.
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.
Programul HELLOWIN foloseşte patru structuri de date (despre care vom discuta mai târziu în acest capitol) definite în
fişierele antet din Windows. Aceste structuri de date sunt:

Structura Semnificaţie
MSG Structura mesajului
WNDCLASSEX Structura clasei de fereastră
PAINTSTRUCT Structură pentru desenare
RECT Dreptunghi
Primele două structuri sunt folosite în funcţia WinMain pentru definirea a două structuri numite msg şi wndclass. Celelalte
două sunt folosite în funcţia WndProc pentru definirea altor două structuri, numite ps şi rect.

27.04.21 15:58 pag. 12 din 22


Câteva cuvinte despre variabilele handle
Î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
Variabilele handle sunt folosite destul de des în Windows. În acest capitol veţi face cunoştinţă cu variabila handle a unei
pictograme (HICON), variabila handle a unui cursor (HCURSOR) şi cea a unei pensule (HBRUSH).
O variabilă handle este pur şi simplu un număr (de obicei pe 32 de biţi) care face trimitere la un obiect. Variabilele handle
din Windows sunt asemănătoare cu cele folosite pentru fişiere (file handles) în programele convenţionale C sau MS-DOS. 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.
Notaţia ungară
S-ar putea să fi observat că unele dintre variabilele folosite în programul HELLOWIN.C au nume ciudate. Un astfel de
exemplu este szCmdLine, transmis ca parametru funcţiei WinMain.
Mulţi programatori Windows folosesc „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.
Atunci când denumiţi variabilele de tip structură, puteţi să folosiţi numele de tip al structurii (sau o abreviere a acestuia) ca
prefix al numelui variabilei sau chiar ca nume al variabilei. 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.
Notaţia ungară vă ajută să descoperiţi erorile înainte ca acestea să ajungă în programele finale. Deoarece numele unei
variabile descrie atât modul de folosire a acesteia, cât şi tipul de date, este mai puţin probabil să faceţi erori de programare care
implică amestecarea unor tipuri de date incompatibile.
Prefixele folosite pentru variabilele din această carte sunt prezentate în tabelul următor:

Prefix Tip de date


c char
by BYTE (unsigned char)
n short
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)
dw DWORD (unsigned long)
fn funcţie
s şir de caractere
sz sir de caractere terminat cu zero
h variabilă handle
p pointer

Punctul de intrare în program


După ce v-aţi format o idee generală despre programul HELLOWIN.C, putem să disecăm programul linie cu linie. Codul
începe cu o instrucţiune #include pentru includerea fişierului antet WINDOWS.H:

#include <windows.h>

Fişierul WINDOWS.H include la rândul lui mai multe fişiere antet care conţin declaraţiile funcţiilor, structurilor, noilor
tipuri de date şi constantelor numerice din Windows.
Instrucţiunea #include este urmată de declaraţia avansată a funcţiei WndProc:


Într-un program C funcţiile pot fi declarate înainte de a fi definite. Declaraţia unei funcţii precizează tipul parametrilor primiţi de funcţie şi tipul valorii
returnate de aceasta, fără să definească şi corpul acesteia. Acest lucru este necesar atunci când funcţia este indicată înainte de a fi definită, dar uşurează şi
citirea programului, (n.t.)

27.04.21 15:58 pag. 13 din 22


LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

Declararea în avans a acestei funcţii este necesară deoarece WndProc este referită în cadrul funcţiei WinMain.
Punctul de intrare al unui program C scris pentru un mediu convenţional este o funcţie numită main. De la această funcţie
începe execuţia programului. (De fapt, funcţia main este punctul de intrare la acea parte a programului scrisă de programator.
De obicei, compilatorul C inserează în fişierul executabil unele secvenţe de cod pentru lansarea în execuţie. Funcţia main este
apoi apelată de acest cod de lansare). 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. Variabila handle a instanţei este
asemănătoare cu „identificatorul de operaţie" („task ID") sau „identificatorul de proces" („process ID") din alte sisteme de
operare multitasking.
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. În Windows 95, parametrul hPrevInstance are
întotdeauna valoarea 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ă. Puteţi să rulaţi un program Windows cu parametri incluzând parametrii respectivi după
numele programului în linia de comandă MS-DOS sau specificându-i în caseta de dialog Run apelată din meniul Start.
Parametrul iCmdShow este un număr care indică modul iniţial de afişare a ferestrei în Windows. Acest număr este atribuit
de programul care lansează în execuţie programul aflat în discuţie. Programele verifică rareori valoarea acestui parametru, dar
o pot face dacă este nevoie. În majoritatea cazurilor, iCmdShow are valoarea 1 sau 7. Dar cel mai bine este să nu vă gândiţi la
aceste valori numerice. 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. Aceasta
este o versiune extinsă (de aici sufixul „Ex") a funcţiei RegisterClass din versiunile anterioare ale sistemului de operare
Windows. Totuşi, funcţia RegisterClass poate fi încă folosită în Windows 95.
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 ;

Sunt necesare câteva observaţii privind tipurile de date şi notaţia ungară folosită în această structură: prefixele LP şi lp
sunt prescurtări pentru „long pointer" şi sunt „rămăşiţe" din versiunile Windows pe 16 biţi, în cazul cărora programatorii
trebuie să facă diferenţa între pointerii de tip short (sau near) pe 16 biţi şi pointerii de tip long (sau far) pe 32 de biţi. În
Windows 95 toţi pointerii au valori pe 32 de biţi. Am încercat să elimin toate prefixele l ale tipurilor de pointeri din exemplele
de programe pe care le-am ales pentru această carte, dar cu siguranţă că le veţi mai întâlni în alte programe.

27.04.21 15:58 pag. 14 din 22


Remarcaţi şi alte moduri de folosire a notaţiei ungare: lpfn vine de la „long pointer to a function" („pointer de tip long la o
funcţie"). Prefixul cb provine de la „count of bytes" („contor de octeţi"). Prefixul hbr vine de la „handle to a brush" („variabilă
handle a unei pensule").
Î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ă
(şi în programele care creează o singură fereastră are, de obicei, acelaşi nume ca şi programul). Al treilea câmp (lpfnWndProc)
este adresa procedurii de fereastră folosită pentru toate ferestrele create pe baza acestei clase (care este funcţia WndProc din
programul HELLOWIN.C). Celelalte câmpuri descriu caracteristicile tuturor ferestrelor create pe baza acestei clase.
Câmpul cbSize reprezintă dimensiunea structurii. Instrucţiunea: wndclass.style = CS_HREDRAW | CS_VREDRAW ; combină
doi identificatori pentru „stilul de clasă" („class style") folosind operatorul SAU orientat pe biţi din limbajul C. În fişierele
antet din Windows sunt definiţi mai mulţi identificatori cu prefixul CS_. Acestea sunt constante pe 32 de biţi în care un singur
bit are valoarea 1. De exemplu, identificatorul CS_VREDRAW este definit ca 0x0001 iar CS_HREDRAW este definit ca
0x0002. Identificatorii definiţi în acest fel sunt numiţi uneori „identificatori pe biţi". Aceştia pot fi combinaţi cu ajutorul
operatorului SAU orientat pe biţi din limbajul C.
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. Dacă redimensionaţi fereastra programului HELLOWIN veţi vedea că textul este redesenat, astfel încât să apară în
centrul noii ferestre. Acest lucru este asigurat de cei doi identificatori de stil. Vom vedea imediat cum este informată procedura
de fereastră privind modificarea dimensiunii ferestrei.
Al treilea câmp al structurii WNDCLASSEX este iniţializat prin instrucţiunea:
wndclass.lpfnWndProc = WndProc ;
Această instrucţiune stabileşte ca procedură de fereastră funcţia WndProc, adică a doua funcţie definită în fişierul
HELLOWIN.C. 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".
Următoarele două instrucţiuni:
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. Programul HELLOWIN nu foloseşte această posibilitate, aşa
că nu se rezervă nici un spaţiu suplimentar. În alte situaţii, aşa cum indică şi notaţia ungară, câmpurile vor avea rolul de
„contor de octeţi".
Următorul câmp este variabila handle a instanţei (care este chiar unul dintre parametrii funcţiei WinMain):
wndclass.hInstance = hinstance ;
Instrucţiunea:
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
şi instrucţiunea:
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. Mai târziu veţi învăţa cum să creaţi pictograme proprii
pentru programele Windows. Pentru moment, vom aborda o metodă mai simplă şi vom folosi o pictogramă predefinită.
Pentru obţinerea unei variabile handle a unei pictograme predefinite apelaţi funcţia LoadIcon cu primul parametru având
valoarea NULL. (Atunci când încărcaţi o pictogramă proprie, acest parametru va conţine variabila handle a instanţei
programului.) Al doilea parametru este un identificator cu prefixul IDI_ definit în fişierele antet din Windows. Pictograma
IDI_APPLICATION este o mică imagine a unei ferestre. Funcţia LoadIcon returnează o variabilă handle a acestei pictograme.
Nu ne interesează valoarea reală a acestei variabile, ci doar o stocăm în câmpurile hIcon şi hIconSm. Aceste câmpuri sunt
definite în structura WNDCLASSEX de tipul HICON („handle to an icon").
Instrucţiunea:
wndclass.hCursor = LoadCursor (NULL, IDC_ ARROW) ;
este foarte asemănătoare cu cele două instrucţiuni anterioare. 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.
Următorul câmp precizează culoarea fondului zonei client a ferestrelor create pe baza acestei clase. Prefixul hbr al
numelui hbrBackground vine de la „handle to a brush" („variabilă handle a unei pensule"). O pensulă este un termen grafic
care se referă la un model colorat de pixeli folosit pentru umplerea unei suprafeţe. Windows are mai multe pensule standard
(sau pensule „de stoc"). Funcţia GetStockObject returnează o variabilă handle a unei pensule albe:
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
Aceasta înseamnă că fondul zonei client a ferestrei va fi colorat cu alb, ceea ce este un lucru obişnuit.
Următorul câmp specifică meniul ferestrei. Programul HELLOWIN nu are nici un meniu, aşa că acest câmp are valoarea
NULL:
wndclass.lpszMenuName = NULL ;

27.04.21 15:58 pag. 15 din 22


În sfârşit, clasei trebuie să i se dea un nume. Pentru programele mai mici, acesta poate fi chiar numele programului, deci în
variabila szAppName este stocat şirul de caractere „HelloWin":
wndclass.IpszClassName = szAppName ;
După iniţializarea celor 12 câmpuri ale structurii, HELLOWIN înregistrează clasa de ferestre prin apelarea funcţiei
RegisterClassEx. Singurul parametru al funcţiei este un pointer către structura WNDCLASSEX:
RegisterClassEx (&wndclass) ;
Crearea terestrei
Clasa de fereastră defineşte caracteristicile generale ale unei ferestre, permiţând astfel folosirea aceleiaşi clase pentru
crearea mai multor ferestre. Atunci când creaţi o fereastră apelând funcţia Create Window, puteţi să specificaţi mai multe
detalii despre fereastra respectivă.
Programatorii Windows mai noi sunt uneori derutaţi de diferenţele între o clasă de fereastră şi o fereastră, şi nu înţeleg de
ce nu pot să specifice toate caracteristicile unei ferestre printr-o singură operaţie. De fapt, împărţirea informaţiilor în acest fel
este foarte convenabilă. De exemplu, toate butoanele de apăsare sunt create pe baza unei singure clase de fereastră. Procedura
de fereastră asociată acestor butoane este localizată chiar în Windows. Clasa de fereastră are ca sarcini prelucrarea tuturor
mesajelor de la tastatură şi de la mouse trimise către butonul de apăsare şi definirea aspectului vizual al butonului pe ecran. Din
acest punct de vedere, toate butoanele de apăsare funcţionează în acelaşi mod. Acestea însă pot avea diferite dimensiuni,
diferite poziţii pe ecran şi diferite etichete. Aceste caracteristici fac parte din definiţia ferestrei.
În loc să folosească o structură de date, aşa cum face funcţia RegisterClassEx, funcţia CreateWindow cere ca toate
informaţiile să fie transmise ca parametri. Iată cum este apelată funcţia CreateWindow în programul HELLOWIN.C:

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

Pentru o citire mai uşoară, am folosit simbolul // pentru notarea comentariilor pe o singură linie care descriu parametrii
funcţiei Create Window.
Parametrul notat cu „numele clasei de fereastră" este szAppName, care conţine şirul de caractere „HelloWin" - numele
clasei de fereastră pe care tocmai am înregistrat-o. În acest fel, fereastra este asociată unei clase de fereastră.
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 ferestrelor, 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
parametri indicăm sistemului de operare să folosească valorile prestabilite pentru o fereastră suprapusă. (CW_USEDEFAULT
este definit ca 0x80000000.) În mod prestabilit, Windows poziţionează mai multe ferestre suprapuse succesive la o distanţă
crescătoare pe verticală şi pe orizontală faţă de colţul din stânga-sus al ecranului. La fel, 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. Puteţi
să folosiţi acest parametru pentru adresarea unor date folosite ulterior în program.
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. Multe funcţii Windows au un parametru hwnd, care specifică fereastra la
care se referă funcţia respectivă. Dacă un program creează mai multe ferestre, fiecare are o variabilă handle diferită. Variabila
handle a unei ferestre este una dintre cele mai importante variabile folosite în Windows.
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.

27.04.21 15:58 pag. 16 din 22


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.
Dacă în câmpul message este transmisă orice altă valoare decât WM_QUIT (egală cu 0x0012), funcţia GetMessage
returnează o valoare diferită de zero. Mesajul WM_QUIT determină ieşirea din ciclul de mesaje. Programul se încheie,
returnând valoarea parametrului wParam al structurii msg.
Instrucţiunea:
TranslateMessage (&msg) ;

27.04.21 15:58 pag. 17 din 22


retransmite structura msg sistemului de operare, pentru convertirea unor mesaje de la tastatură. (Vom discuta mai multe despre
aceasta în Capitolul 5.)
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.
Procedura de fereastră
Tot codul descris până în acest moment este cod de întreţinere: a fost înregistrată clasa de fereastră, a fost creată fereastra,
care apoi a fost afişată pe ecran şi programul a intrat în ciclul de tratare a mesajelor în vederea preluării mesajelor din coada de
aşteptare.
Operaţiile reale au loc însă în procedura de fereastră. Procedura de fereastră arată ce afişează fereastra în zona client şi
cum răspunde fereastra la intrările utilizatorului.
În programul HELLOWIN procedura de fereastră este funcţia WndProc. O procedură de fereastră poate avea orice nume
(cu condiţia ca numele respectiv să nu existe deja). Un program pentru Windows poate conţine mai multe proceduri de
fereastră. O procedură de fereastră este întotdeauna asociată unei clase de fereastră, înregistrată cu ajutorul funcţiei
RegisterClassEx. Funcţia CreateWindow creează o fereastră pe baza unei anumite clase. Pe baza aceleiaşi clase pot fi create
mai multe ferestre.
Procedura de fereastră este definită întotdeauna astfel:
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam. LPARAM lParam)
Remarcaţi faptul că cei patru parametri ai procedurii de fereastră sunt identici cu primele patru câmpuri ale structurii
MSG.
Primul parametru este hwnd, variabila handle a ferestrei care recepţionează mesajul. Aceasta este aceeaşi variabilă cu cea
returnată de funcţia CreateWindow. Pentru un program care creează o singură fereastră, precum HELLOWIN, aceasta este
singura variabilă handle cunoscută de program. Dacă programul creează mai multe ferestre pe baza aceleiaşi clase (şi deci
foloseşte aceeaşi procedură de fereastră), atunci hwnd identifică fereastra care primeşte mesajul.
Al doilea parametru este un număr (mai precis, un întreg fără semn - UINT - pe 32 de biţi) care identifică mesajul. Ultimii
doi parametri (wParam, de tipul WPARAM si lParam, de tipul LPARAM) furnizează mai multe informaţii despre mesaj.
Aceştia sunt numiţi „parametri de mesaj". Conţinutul acestor parametri este specific fiecărui tip de mesaj.
Prelucrarea mesajelor
Fiecare mesaj recepţionat de o procedură de fereastră este identificat printr-un număr, acesta fiind parametrul iMsg al
procedurii de fereastră. În fişierele antet din Windows sunt definiţi identificatori, cu prefixul WM („window message"), pentru
fiecare parametru de mesaje.
În general, programatorii Windows folosesc o construcţie switch sau case ca să determine ce mesaje a primit fereastra şi să
stabilească modul de prelucrare a fiecărui mesaj. Atunci când prelucrează un mesaj, procedura de fereastră trebuie să returneze
valoarea 0. Orice mesaj pe care procedura de fereastră nu-l prelucrează este transmis unei funcţii Windows numită
DefWindowProc. Valoarea returnată de funcţia DefWindowProc trebuie să fie returnată şi de procedura de fereastră.
În programul HELLOWIN, procedura de fereastră (WndProc) prelucrează numai trei mesaje: WM_CREATE,
WM_PAINT şi WM_DESTROY. Procedura de fereastră este structurată astfel:

switch (iMsg)
{
case WM_CREATE :
[prelucrează mesajul WM_CREATE]
return 0 ;

case WM_PAINT :
[prelucrează mesajul WM_PAINT]
return 0 ;

case WM_DESTROY :
[prelucrează mesajul WM_DESTROY]
return 0 ;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam) ;

Este esenţial să apelaţi funcţia DefWindowProc pentru prelucrarea tuturor mesajelor ignorate de procedura de fereastră a
programului.

27.04.21 15:58 pag. 18 din 22


Redarea unui fişier de sunet
Primul mesaj pe care îl primeşte o procedură de fereastră - şi primul mesaj prelucrat de funcţia WndProc - este
WM_CREATE. WndProc recepţionează acest mesaj în timp ce Windows execută funcţia CreateWindow din WinMain.
Aceasta înseamnă că atunci când HELLOWIN 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. Windows poate apoi să încheie execuţia funcţiei CreateWindow
şi să se întoarcă la programul HELLOWIN pentru alte operaţii din funcţia WinMain.
Deseori, procedurile de fereastră fac toate operaţiile de iniţializare a ferestrei în timpul prelucrării mesajului
WM_CREATE. În timpul prelucrării acestui mesaj, programul HELLOWIN redă un fişier de sunet, numit HELLOWIN.WAV.
Acest lucru se face prin apelarea funcţiei PlaySound. Primul parametru al funcţiei este numele fişierului. Acesta ar putea să fie
şi un alias (nume de înlocuire) definit în secţiunea Sounds a panoului de control (Control Panel) sau o resursă de program. Al
doilea parametru este folosit numai dacă fişierul de sunet este o resursă. Al treilea parametru specifică un set de opţiuni. În
acest caz am indicat faptul că primul parametru este un nume de fişier şi că sunetul trebuie să fie redat asincron, adică funcţia
PlaySound trebuie să returneze controlul imediat după începerea operaţiei de redare, fără să aştepte terminarea acesteia.
WndProc încheie prelucrarea mesajului WM_CREATE cu returnarea valorii zero din procedura de fereastră.
Mesajul WM_PAINT
Al doilea mesaj prelucrat de funcţia WndProc este 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ă.
Cum poate să devină invalidă o zonă client? Atunci când fereastra este creată, întreaga zonă client a ferestrei este invalidă,
deoarece programul nu a desenat încă nimic în fereastră. Primul mesaj WM_PAINT (care apare, în mod normal, atunci când
programul apelează funcţia UpdateWindow din WinMain) cere procedurii de fereastră să deseneze ceva în zona client.
Zona client devine invalidă şi atunci când redimensionaţi fereastra programului HELLOWIN. Vă amintiţi că parametrul de
stil al structurii wndclass din HELLOWIN conţine identificatorii CS_VREDRAW şi CS_HREDRAW. Aceşti identificatori
determină sistemul de operare Windows să invalideze întreaga fereastră atunci când aceasta îşi schimbă dimensiunea şi apoi să
trimită un mesaj WM_PAINT către procedura de fereastră.
Dacă micşoraţi la o pictogramă fereastra programului HELLOWIN şi apoi îi refaceţi dimensiunea iniţială. Windows nu
salvează conţinutul zonei client. Într-un mediu grafic ar fi mult prea multe date de salvat. De aceea, Windows invalidează
fereastra. Procedura de fereastră primeşte mesajul WM_PAINT şi reface conţinutul acesteia.
Atunci când mutaţi ferestrele astfel încât să se suprapună. Windows nu salvează porţiunea unei ferestre care a fost
acoperită de o altă fereastră. În schimb, atunci când fereastra respectivă este readusă la suprafaţă, porţiunea anterior acoperită
este invalidată. Procedura de fereastră primeşte un mesaj WM_PAINT pentru redesenarea porţiunii respective.
Aproape întotdeauna, prelucrarea mesajului WM_PAINT începe prin apelarea funcţiei BeginPaint:
hdc = BeginPaint (hwnd, &ps) ;

şi se termină cu apelarea funcţiei EndPaint:

EndPaint (hwnd, &ps) ;

În ambele situaţii, primul parametru este variabila handle a ferestrei programului, iar al doilea parametru este un pointer la
o structură de tip PAINTSTRUCT. Structura PAINTSTRUCT conţine unele informaţii pe care programul le poate folosi
pentru redesenarea zonei client. (Vom discuta despre acest câmp al structurii în următorul capitol.)
În timpul apelării funcţiei BeginPaint, Windows şterge fondul zonei client, dacă acesta nu a fost deja şters. Fondul este
şters folosindu-se pensula specificată în câmpul hbrBackground al structurii WNDCLASSEX, folosită pentru înregistrarea
clasei de fereastră, în cazul programului HELLOWIN, aceasta este o pensulă de stoc albă, ceea ce înseamnă că Windows
şterge fondul ferestrei colorându-l, în acelaşi timp, cu alb. Funcţia BeginPaint validează întreaga zonă client şi returnează o
„variabilă handle a contextului de dispozitiv". Un context de dispozitiv se referă la un dispozitiv fizic de ieşire (cum ar fi un
monitor video) împreună cu driverul care controlează acest dispozitiv. Aveţi nevoie de o variabilă handle a contextului de
dispozitiv ca să afişaţi text şi elemente grafice în zona client a ferestrei. Folosind variabila handle a contextului de dispozitiv
returnată de funcţia BeginPaint nu puteţi să desenaţi în afara zonei client a ferestrei, chiar dacă încercaţi. Funcţia EndPaint
eliberează variabila handle a contextului de dispozitiv, astfel încât aceasta nu mai este validă.
Dacă procedura de fereastră nu prelucrează mesajele WM_PAINT - ceea ce se întâmplă foarte rar - acestea trebuie să fie
transmise funcţiei DefWindowProc. Funcţia DefWindowProc apelează funcţiile BeginPaint şi EndPaint, astfel încât zona client
a ferestrei să fie din nou validată.
După funcţia BeginPaint, WndProc apelează funcţia GetClientRect:
GetClientRect (hwnd, &rect) ;
Primul parametru al funcţiei GetClientRect este variabila handle a ferestrei programului. Al doilea parametru al funcţiei
este un pointer la o variabilă numită rect, de tipul RECT, definită în WndProc.
RECT este o structură pentru un „dreptunghi" definit în fişierele antet din Windows. Structura conţine patru câmpuri de tip
LONG, numite left, top, right şi bottom. Funcţia GetClientRect atribuie acestor câmpuri valorile corespunzătoare dimensiunilor
zonei client a ferestrei. Câmpurile left şi top au întotdeauna valoarea 0. Câmpurile right şi bottom conţin lăţimea şi înălţimea
zonei client, în pixeli.
WndProc transmite funcţiei DrawText un pointer către structura RECT, prin cel de-al patrulea parametru al funcţiei:
DrawText (hdc, "Hello, Windows 95!", -1, &rect,

27.04.21 15:58 pag. 19 din 22


DT_SINGLELINE : DT_CENTER ! DT_VCENTER) ;
Funcţia DrawText, aşa cum arată şi numele, este folosită pentru „desenarea" unui text. Deoarece funcţia desenează ceva,
primul parametru este o variabilă handle a contextului de dispozitiv, returnatâ de funcţia BeginPaint. Al doilea parametru este
textul care urmează să fie afişat, iar al treilea parametru are valoarea -1, ceea ce indică faptul că textul de afişat se termină cu
un octet 0.
Ultimul parametru al funcţiei este o combinaţie de indicatori flag pe biţi, definiţi în fişierele antet din Windows. Indicatorii
flag folosiţi determină afişarea textului pe o singură linie, centrată orizontal şi vertical relativ la dreptunghiul specificat prin al
patrulea parametru. Ca urmare, funcţia DrawText afişează textul „Hello, Windows 95!" în centrul zonei client a ferestrei.
De fiecare dată când zona client devine invalidă (aşa cum se întâmplă atunci când modificaţi dimensiunea ferestrei),
funcţia WndProc recepţionează un mesaj WM_PAINT. WndProc obţine noua dimensiune a ferestrei şi afişează din nou textul
în centrul acesteia.
Mesajul 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:
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.
PROBLEME LEGATE DE PROGRAMAREA SUB WINDOWS
Chiar şi după explicaţiile legate de programul HELLOWIN, structura şi modul de funcţionare ale programelor Windows s-
ar putea să fi rămas ceva misterios. Într-un scurt program C scris pentru un mediu convenţional, întregul program poate fi
conţinut de funcţia main. În programul HELLOWIN, funcţia WinMain conţine numai codul de întreţinere (overhead) necesar
pentru înregistrarea clasei, crearea ferestrei şi obţinerea şi livrarea mesajelor din coada de mesaje.
Toată „acţiunea" programului se desfăşoară în procedura de fereastră. În programul HELLOWIN, aceasta nu face prea
multe - redă un fişier de sunet şi afişează un text în fereastră. În următoarele capitole veţi vedea cam tot ce poate face un
program Windows ca răspuns la un mesaj. Prelucrarea mesajelor este unul dintre principalele obstacole pe care trebuie să le
depăşiţi atunci când scrieţi un program pentru Windows.
Nu ne apela, te apelăm noi!
Aşa cum am menţionat mai devreme, programatorii sunt obişnuiţi cu ideea apelării unor funcţii ale sistemului de operare,
pentru îndeplinirea unei anumite operaţii. De exemplu, programatorii C folosesc funcţia fopen ca să deschidă un fişier.
Funcţiile de bibliotecă livrate odată cu compilatorul conţin secvenţe de cod care apelează funcţii ale sistemului de operare
pentru deschiderea unui fişier. Nici o problemă.
În Windows, însă, lucrurile se petrec altfel. Deşi sistemul de operare are mai mult de o mie de funcţii pe care programele
le pot apela, şi Windows poate să apeleze funcţii ale programului. Mai precis, Windows poate să apeleze procedurile de
fereastră, precum WndProc. Procedura de fereastră este asociată unei clase de fereastră pe care programul o înregistrează prin
apelarea funcţiei RegisterClassEx. O fereastră creată pe baza acestei clase foloseşte procedura de fereastră specificată de clasă
pentru prelucrarea tuturor mesajelor recepţionate. Windows trimite un mesaj către o fereastră prin apelarea procedurii de
fereastră a acesteia.
Windows apelează funcţia WndProc atunci când fereastra este creată. Windows apelează funcţia WndProc atunci când
fereastra este distrusă. Windows apelează funcţia WndProc atunci când fereastra este redimensionată, mutată sau redusă la o
pictogramă. Windows apelează funcţia WndProc atunci când utilizatorul selectează o opţiune dintr-un meniu. Windows
apelează funcţia WndProc atunci când o bară de derulare este manipulată sau când utilizatorul execută clic pe aceasta.
Windows apelează funcţia WndProc pentru a-i comunica ferestrei că trebuie să redeseneze zona client.
Toate aceste apeluri sunt făcute sub forma unor mesaje. În majoritatea programelor Windows, cea mai mare parte a
codului este folosit pentru tratarea mesajelor. Windows poate trimite unei proceduri de fereastră peste 200 de mesaje. Aceste
mesaje sunt identificate prin nume care încep cu literele WM şi sunt definite în fişierele antet din Windows.
De fapt, ideea includerii într-un program a unei proceduri care să poată fi apelată din exterior există şi în programarea
convenţională. Funcţia signal din limbajul C interceptează codul combinaţiei de taste Ctrl+Break. Probabil aţi folosit metode
de interceptare a întreruperilor hardware în limbaj de asamblare sau una dintre construcţiile ON din Microsoft BASIC.
Driverul Microsoft Mouse conţine o metodă pe care o pot folosi programele non-Windows pentru a fi „la curent" cu activitatea
mouse-ului.
În Windows, acest concept este extins, acoperind orice operaţie. Toate evenimentele legate de o fereastră sunt transmise
procedurii de fereastră sub forma unor mesaje. Procedura de fereastră răspunde la aceste mesaje sau le retransmite către
procedura DefWindowProc, pentru operaţii de prelucrare prestabilite.
Parametrii wParam şi lParam ai procedurii de fereastră nu sunt folosiţi în programul HELLOWIN decât pentru a fi
retransmişi funcţiei DefWindowProc. Aceşti parametri furnizează procedurii de fereastră informaţii suplimentare despre
mesajul primit. Semnificaţia acestor parametri este dependentă de mesaj.
Haideţi să vedem un exemplu. Ori de câte ori zona client a unei ferestre îşi modifică dimensiunea, Windows apelează
procedura ferestrei respective. Parametrul hwnd al procedurii de fereastră este variabila handle a ferestrei care şi-a modificat
dimensiunea. Parametrul iMsg are valoarea WM_SIZE. Parametrul wParam poate conţine unul dintre identificatorii
SIZENORMAL, SIZEICONIC, SIZEFULLSCREEN, SIZEZOOMSHOW şi SIZEZOOMHIDE (definiţi în fişierele antet din

27.04.21 15:58 pag. 20 din 22


Windows cu valori de la 0 la 4). Parametrul wParam arată dacă fereastra a fost redusă la o pictogramă, a fost mărită la
dimensiunea ecranului sau a fost mascată (în urma acoperirii de către o altă fereastră). Parametrul lParam conţine noua
dimensiune a ferestrei. Noua lăţime (o valoare pe 16 biţi) şi noua înălţime (tot o valoare pe 16 biţi) sunt împachetate în
parametrul lParam, care este o valoare pe 32 de biţi. În fişierele antet din Windows este definită o macroinstrucţiune care vă
ajută să extrageţi cele două valori din parametrul lParam. Vom face acest lucru în capitolul următor.
Uneori mesajele generează alte mesaje ca rezultat al prelucrării în funcţia DefWindowProc. De exemplu, să presupunem că
rulaţi programul HELLOWIN şi selectaţi opţiunea Close din meniul sistem, folosind tastatura sau mouse-ul. Funcţia
DefWindowProc prelucrează intrările de la tastatură sau de la mouse. Atunci când detectează selectarea opţiunii Close, trimite
un mesaj WM_SYSCOMMAND către procedura de fereastră. WndProc retransmite acest mesaj funcţiei DefWindowProc.
Funcţia DefWindowProc răspunde prin trimiterea unui mesaj WM_CLOSE către procedura de fereastră. WndProc retransmite
şi acest mesaj către funcţia DefWindowProc. Funcţia DefWindowProc răspunde la acest mesaj prin apelarea funcţiei Destroy
Window. Funcţia Destroy Window determină sistemul de operare să trimită un mesaj WM_DESTROY către procedura de
fereastră. WndProc răspunde la acest mesaj apelând funcţia PostQuitMessage, care inserează un mesaj WM_QUIT în coada de
aşteptare. Acest mesaj determină ieşirea din ciclul de tratare a mesajelor şi închiderea programului.
Mesaje în coada de aşteptare şi în afara acesteia
Am vorbit despre faptul că Windows trimite mesaje către o fereastră, ceea ce înseamnă că Windows apelează procedura de
fereastră. Dar un program Windows are si un ciclu de tratare a mesajelor care preia mesajele din coada de aşteptare apelând
funcţia GetMessage şi le distribuie procedurii de fereastră apelând funcţia DispatchMessage.
Aşadar, un program Windows interoghează coada de aşteptare (aşa cum un program convenţional interoghează bufferul de
intrare de la tastatură) şi apoi retransmite mesajele în anumite locuri? Sau primeşte mesajele direct din exterior? Ei bine, sunt
folosite ambele metode.
Mesajele pot fi trimise prin coada de aşteptare sau direct. Mesajele trimise prin coada de aşteptare sunt preluate de
program şi sunt distribuite în ciclul de tratare a mesajelor. Mesajele care nu trec prin coada de aşteptare sunt trimise ferestrei
direct, atunci când Windows apelează procedura de fereastră. Rezultatul este faptul că procedura de fereastră primeşte toate
mesajele, indiferent dacă sunt trimise prin coada de aşteptare sau direct. Din punct de vedere structural, programele Windows
sunt foarte clare, deoarece prelucrarea mesajelor se face centralizat, într-un singur punct. Aşadar, mesajele preluate de funcţia
GetMessage sunt inserate în coada de aşteptare, iar mesajele care nu trec prin coada de aşteptare sunt trimise procedurii de
fereastră.
Mesajele din coada de aşteptare sunt, în principal, rezultatul acţionării tastelor (aşa sunt, de pildă, WM_KEYDOWN şi
WM_KEYUP) sau caractere trimise de la tastatură (WM_CHAR), rezultatul deplasării mouse-ului (WM_MOUSEMOVE) şi
al apăsării butoanelor mouse-ului (WM_LBUTTONDOWN). Tot în categoria mesajelor inserate în coada de aşteptare intră şi
mesajele trimise de la ceas (WM_TIMER), mesajele de redesenare (WM_PAINT) şi mesajele de încheiere (WM_QUIT).
Mesajele trimise direct sunt cele rezultate din alte evenimente. În multe cazuri, mesajele trimise direct sunt rezultatul unor
mesaje din coada de aşteptare. Atunci când transmiteţi un mesaj din procedura de fereastră către funcţia DefWindowProc, de
multe ori Windows prelucrează mesajul prin trimiterea altor mesaje către procedura de fereastră.
Evident, acest proces este foarte complex dar, din fericire, de cea mai mare parte răspunde sistemul de operare, nu
programul. Din perspectiva procedurii de fereastră, aceste mesaje sunt recepţionate în ordine, şi sincronizat. Procedura de
fereastră poate să prelucreze mesajele sau să le ignore. Din acest motiv, este numită uneori „ultimul hop". Prin mesaje,
procedura de fereastră este informată privind aproape toate evenimentele care afectează fereastra.
Mesajele care nu trec prin coada de aşteptare rezultă din apelarea unor funcţii Windows sau din expedierea în mod explicit
a unui mesaj, prin apelarea funcţiei SendMessage. (Mesajele din cealaltă categorie sunt inserate în coada de aşteptare prin
apelarea funcţiei PostMessage.)
De exemplu, atunci când WinMain apelează funcţia CreateWindow, Windows creează fereastra şi trimite procedurii de
fereastră un mesaj WM_CREATE. Atunci când WinMain apelează funcţia ShowWindow, Windows trimite procedurii de
fereastră mesajele WM_SIZE şi WM_SHOWWINDOW. Atunci când WinMain apelează funcţia UpdateWindow, Windows
trimite procedurii de fereastră un mesaj WM_PAINT.
Mesajele nu seamănă cu întreruperile hardware. În timpul prelucrării unui mesaj într-o procedură de fereastră, programul
nu poate fi întrerupt de un alt mesaj. Procedura de fereastră va prelucra un alt mesaj înainte de returnarea controlului numai
dacă apelează o funcţie care generează un nou mesaj.
Ciclul de mesaje şi procedura de fereastră nu sunt executate simultan. Atunci când procedura de fereastră prelucrează un
mesaj extras din coada de aşteptare, acest mesaj este rezultat în urma apelării funcţiei DispatchMessage în WinMain. Funcţia
DispatchMessage nu returnează controlul decât după ce procedura de fereastră termină prelucrarea mesajului.
Remarcaţi faptul că procedura de fereastră trebuie să fie reentrantă. Windows trimite deseori funcţiei WndProc un nou
mesaj atunci când aceasta apelează funcţia DefWindowProc pentru mesajul anterior. În majoritatea cazurilor reentranţa
procedurii de fereastră nu este o problemă, dar trebuie să fiţi conştient de această posibilitate.
De exemplu, să presupunem că în procedura de fereastră stabiliţi valoarea unei variabile în timpul prelucrării unui mesaj,
apoi apelaţi o funcţie Windows. După returnarea din funcţia apelată, puteţi fi sigur că valoarea variabilei a rămas aceeaşi? Nu
este obligatoriu - de exemplu, este posibil ca funcţia Windows apelată să genereze un alt mesaj, iar procedura de fereastră să
modifice valoarea aceleiaşi variabile în timpul prelucrării acestui mesaj. Acesta este unul dintre motivele pentru care unele
forme de optimizare ale compilatorului trebuie să fie dezactivate atunci când compilaţi programe Windows.
În multe situaţii, procedura de fereastră poate să reţină anumite informaţii în timpul prelucrării unor mesaje şi să le
folosească pentru prelucrarea altor mesaje. Aceste informaţii trebuie să fie stocate fie în variabile statice definite în procedura
de fereastră, fie în variabile globale.

27.04.21 15:58 pag. 21 din 22


Desigur, veţi înţelege mai bine toate aceste lucruri în următoarele capitole, pe măsură ce vom extinde procedurile de
fereastră astfel încât să prelucreze şi alte mesaje.
Nu fiţi egoist!
Windows 95 este un mediu care asigură multitaskingul controlat. Aceasta înseamnă că atunci când un program execută o
operaţie de durată, sistemul de operare permite utilizatorului să treacă în alt program. Acesta este un lucru bun şi este unul
dintre avantajele oferite de Windows 95 faţă de versiunile Windows bazate pe MS-DOS.
Totuşi, datorită structurii Windows, multitaskingul controlat nu funcţionează întotdeauna aşa cum ar trebui. De exemplu,
să presupunem că programul are nevoie de mai multe minute pentru prelucrarea unui mesaj. Este adevărat că utilizatorul poate
trece într-un alt program, dar nu poate face nimic cu programul respectiv. Utilizatorul nu poate să mute fereastra programului,
să o redimensioneze sau să o închidă. Nu poate face absolut nimic, deoarece aceste operaţii trebuie să fie executate de
procedura de fereastră, iar procedura de fereastră este ocupată cu o operaţie de durată, chiar dacă nu ea pare a fi cea care
execută operaţiile de mutare şi de redimensionare. Aceste operaţii sunt executate de funcţia DefWindowProc, care trebuie
considerată o parte a procedurii de fereastră.
Dacă programul trebuie să execute o operaţie de durată în timpul prelucrării unui anumit mesaj, puteţi să faceţi acest lucru
şi într-un mod mai politicos, aşa cum vom vedea în Capitolul 14. Chiar şi într-un mediu cu multitasking controlat, nu este o
idee prea bună să blocaţi o fereastră pe ecran. Acest lucru deranjează utilizatorii şi îi face să gândească lucruri urâte despre
programul dumneavoastră.

Ciclul de învăţare
Aşa cum v-aţi dat seama din acest capitol, programarea sub Windows este foarte diferită de programarea pentru un mediu
convenţional, cum ar fi MS-DOS, şi nu pretinde nimeni că programarea sub Windows este uşoară.
Atunci când am început să învăţ programarea sub Windows, am vrut să fac ceea ce făceam de obicei pentru a învăţa un
nou sistem de operare sau un nou limbaj de programare - să scriu un program simplu, care să afişeze conţinutul hexazecimal al
unui fişier. Sub MS-DOS, un astfel de program implică lucrul de la linia de comandă, operaţii rudimentare de intrare/ieşire cu
fişiere şi formatarea rezultatelor pe ecran. Programul de afişare sub Windows s-a dovedit a fi ceva monstruos. A trebuit să
învăţ o mulţime de lucruri despre meniuri, casete de dialog, bare de derulare şi altele. Desigur, acest prim efort de învăţare care
se impunea nu era un punct în favoarea programării sub Windows.
Cu toate acestea, odată terminat, programul de afişare hexazecimală nu semăna cu nici unul dintre programele pe care le
scrisesem până atunci în acelaşi scop. În loc să obţină numele fişierului din linia de comandă, WINDUMP (acesta era numele
pe care l-am dat programului) folosea o casetă de dialog în care erau prezentate toate fişierele din directorul curent, în loc să
scrie rezultatele pe ecran după modelul unui teleimprimator, WINDUMP avea bare de derulare ce permiteau deplasarea în
orice parte a fişierului. Ca un avantaj suplimentar, puteam să rulez simultan două copii ale programului WINDUMP, ceea ce
îmi permitea să compar două fişiere afişate în două ferestre alăturate. Pe scurt, WINDUMP a fost primul program de afişare
hexazecimală de care am fost cu adevărat mândru.
Trebuie să vă puneţi următoarea întrebare: doresc să folosesc o interfaţă modernă şi eficientă, care să includă meniuri,
casete de dialog, bare de derulare şi elemente grafice? Dacă răspunsul este afirmativ, trebuie să vă puneţi o altă întrebare:
doresc să scriu chiar eu codul pentru aceste meniuri, casete de dialog, bare de derulare şi elemente grafice? Sau voi profita de
faptul că acest cod există deja în Windows? Cu alte cuvinte, ce este mai uşor - să învăţaţi să folosiţi 1000 de funcţii, sau să le
scrieţi chiar dumneavoastră? Este mai uşor să vă orientaţi gândirea către arhitectura bazată pe mesaje a sistemului de operare
Windows, sau preferaţi să luptaţi cu aceasta folosind diverse surse de intrare, după modelul tradiţional?
Dacă doriţi să scrieţi codul unei interfeţe proprii, mai bine închideţi această carte şi apucaţi-vă de treabă. În acest timp, noi
ceilalţi vom învăţa cum să afişăm şi să derulăm textul într-o fereastră.

27.04.21 15:58 pag. 22 din 22

S-ar putea să vă placă și