Biologie | Chimie | Didactica | Fizica | Geografie | Informatica | |
Istorie | Literatura | Matematica | Psihologie |
Windows API (Win32 API)este un set de functii oferite de sistemul de operare Windows pentru manipularea resurselor calculatorului.Aceste functii pot fi utlizate de catre programatori pentru dezvoltarea aplicatiilor utilizator. Functiile din interfata Win32 API sunt implementate in urmatoarele trei biblioteci: user32.dll, kernel32.dll si gdi.dll.Ele pot fi folosite in orice program daca fisierul header Windows.h este inclus in program si linkeditarea programului se face cu fisierul de exporturi corespunzator) user32.lib, kernel32.lib sau si gdi32.lib. Aceste trei biblioteci sunt trecute in mod automat in lista de module a linkeditorului, in orice proiect generat de mediul Visual C Functiile din interfata Win32 API sunt impartite in mai multe categorii. Dintre acestea cele mai importante sunt User Interface Services si Windows Base Services.
Tipuri de date noi folosite de functiile Win32 API.
Tipul HANDLE - tip generic, utilizat pentru manipularea obiectelor folosite in program (fisiere, ferestre, alte resurse). Pentru a manipula un astfel de obiect, este necesara obtinerea unui astfel de HANDLE, in urma apelarii unei functii care returneaza un astfel de obiect.
Exemplu: Se creaza un fisier in care se scrie "Hello world"
HANDLE hFile CreateFile("numeFisier", GENERIC_READ,0, NULL,
CREATE_ALWAYS, FILE_ATRIBUTE_NORMAL,NULL);
char buf[]="Hello world";
DWORD nr_octeti_scrisi;
WriteFile(hFile,(LPVOID)buf,9,&nr_octeti_scrisi,NULL);
CloseHandle(hFile)
Tipul LPVOID - definit ca: typedef void * LPVOID
Tipul LPSTR - este definit ca typedef char * LPSTR
Tipul HWND este definit ca typedef HANDLE HWND - este folosit in manipularea ferestrelor.
Tipurile WPARAM si LPARAM - cuvinte cu lungimea de 32 de biti.
Un proces (task) este imaginea unui program executabil in memoria calculatorului. Sistemul de operare Windows este un sistem de operare multitasking pentru ca poate rula mai multe procese simultan. De exemplu, poate rula simultan un mediu de dezvoltare si un editor de texte. Daca in memoria calculatorului exista mai multe procese care provin din acelasi fisier executabil, ele sunt numite instante ale acelui program. Windows permite rularea mai multor instante ale unui program. Toate instantele unui program au aceeasi zona de cod dar fiecare instanta are propria ei zona de date si stiva. De aceea fiecare instanta poate rula independent de celelalte instante aflate in memoria calculatorului. Windows furnizeaza mecanisme pentru comunicatia intre procese. Acestea sunt descrise in WindowsBase Services->InterprocessComunication.
In cazul in care un program trebuie sa execute mai multe sarcini simultan se creaza fire de executie separate care executa fiecare din aceste sarcini (task-uri). Acestea se numesc fire de executie. De axemplu, un program de calcul tabelar trebuie sa gestioneze interfata grafica si in acelasi timp sa execute un calcul care dureaza un interval de timp indelungat. De aceea se creaza cel putin doua fire de executie (thread) care se executa in paralel. Spre deosebire de procese firele de executie impart aceeasi zona de memorie si de aceea pot comunica usor (de ex. prin intermediul variabilelor globale). Atat firele de executie ale unui proces cat si procesele din sistem , se pot manipula prin intermediul unui HANDLE. De ex., programul de mai jos creaza o noua instanta a sa folosind functia CreateProcess si o manipuleaza folosind functia TerminateProcess.
Exemplu:
#include <Windows.h>
#include <conio.h>
#include <stdio.h>
void main()
printf("Proces creat.Apasati o tasta pentru oprire!n");
getch(
TerminateProcess(pi.hProcess,0L);
Ferestre in sistemul de operare Windows
O fereastra este elementul fundamental pe baza caruia se construieste orice interfata utilizator. Interfata sisteelor de operare Windows este bazata pe ferestre. Majoritatea aplicatiilor Windows poseda o fereastra principala, in care ruleaza. O fereastra aloca unei aplicatii un spatiu in forma dreptunghiulara pe ecran. Elementele principale ale unei ferestre sunt:
bara de titlu - afiseaza titlul aplicatiei si eventual denumirea documentului deschis pentru prelucrare; este o zona activa care permite mutarea ferestrei pe ecran;
butoanele de minimizare, maximizare si inchidere - apar de obicei in bara de titlu;
meniul sistem - continut tot de bara de titlu (in partea stanga a acesteia);
marginea ferestrei - este o zona activa, care permite redimensionarea ferestrei;
zona client a ferestrei - este zona pusa la dispozitie pentru aplicatia respectiva.
Ferestrele au doua dimensiuni: X pe orizontala si Y pe verticala. Multimea ferestrelor afisate pe ecran la un moment dat trebuie privita ca fiind in spatiu. Toate ferestrele au o a treia dimensiune comuna, Z, si sunt caracterizate de o anumita ordine in care sunt afisate pe axa Z. In cazul unui click stanga (cu mouse-ul) in interiorul unei ferestre care nu era activa si era partial ascunsa, aceasta este activata (i se deseneaza bara de titlu cu o alta culoare) si seschimba ordinea Z a ferestrelor, de asa maniera incat fereastra activata devine ultima fereastra din ordinea Z (fereastra din fata). La un moment dat, o singura fereastra poate fi activa. Aceasta este ultima in ordinea Z si primeste input focus-ul, adica poate receptiona evenimentele de la tastatura.
Exista doua tipuri de ferestre: top-level si child. Ferestrele top-level sunt ferestrele principale in care ruleaza o aplicatie. Ferestrele child sunt butoanele si alte elemente de control dintr-o caseta de dialog.
O fereastra este unic identificata in sistem printr-un handle (o variabila de tip HWND) care se obtine in urma apelarii functiei API CreateWindow.
Fiecare fereastra are asociata o structura de tip coada numita coada de mesaje. In aceasta structura sistemul de operare pune mesajele care sunt de interes pentru fereastra respectiva. De aceea, programele Windows se mai numesc si orientate pe mesaje.
Pentru prelucrarea mesajelor se creaza o structura de tip bucla de mesaje. Aceasta presupune apelarea continua a functiilor API GetMessage (care extrage un mesaj din coada de mesaje) si DispatchMessage. Functia API DispatchMessage apeleaza o functie speciala numita procedura fereastra, cu urmatoarea semnatura:
LRESULT CALLBACK Wndproc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
unde: hwnd este handle de fereastra apelanta, uMsg este identificator de mesaj, wParam este primul parametru al mesajului si lParam este al doilea parametru al mesajului.
Aceasta functie este declarata si definita in cadrul fiecarui program Windows. Mai multe ferestre care au aceleasi caracteristici (dimensiune, stare initiala, daca se pot redimensiona sau nu) formeaza o clasa de ferestre. Clasa de ferestre se specifica la fiecare apel al functiei CreateWindow. Pentru a putea folosi o clasa deferestre este necesara inregistrarea ei, cu functia API RegisterClass. La inregistrarea unei clase de ferestre, se specifica, printre alte caracteristici si procedura fereastra care se va folosi de catre ferestrele din clasa respectiva. Procedura fereastra primeste fiecare mesaj extras de catre functia GetMessage si transmis cu functia DispatchMessage si il proceseaza. Pentru mesajele a caror tratare nu necesita actiuni speciale, se apeleza functia API DefWindowProc (cu aceeasi semnatura ca orice procedura fereastra obisnuita). Dupa tratarea mesajului se revine in bucla de mesaje.
Mesajele sistemului de operare Windows sunt definite ca si constante simbolice de tip WM_*(de ex. WM_CHAR, WM_PAINT, etc.). Ele pot transmite, pe langa tipul mesajului si alte informatii utile, prin cei doi parametri de tip WPARAM, respectiv LPARAM, care se transmit procedurii fereastra. De ex., mesajul WM_LBUTTONDOWN, generat la apasarea butonului stang al mouse-ului transmite coordonatele (in pixeli, relativ coltul stanga sus al zonei client) punctului in care s-a apasat butonul stang al mouse-ului.
Asa cum un program C/C++ necesita declararea unei functii main, programele Windows necesita declararea unei functii WinMain cu urmatoarea semnatura:
int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
unde hInstance este handle de instanta curenta a programului, lpCmdLine este un pointer la linia de comanda, nCmdShow arata cum sa fie prezentata initial fereastra principala a aplicatiei.
Exemplu de inregistrare a unei clase de ferestre si de utilizare a ei pentru crearea unei ferestre simple.
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
return msg.wParam;
Daca dorim sa tratam un alt eveniment functia Wndproc trebuie modificata astfel incat mesajul asociat sa fie interceptat. De ex., pentru a genera mesajul Ati apasat o tasta la fiecare apasare a unei taste trebuie tratat mesajul WM_KEYDOWN, astfel:
LRESULT CALLBACK WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Pentru implementarea programului anterior s-a deschis un proiect de tip Win32 Application.
Microsoft Foundation Class (MFC)
Microsoft Foundation Class este o biblioteca de clase, dezvoltata de firma Microsoft pentru a simplifica programarea aplicatiilor Windows API.
Multe dintre clasele MFC incapsuleaza functiile Windows API. Astfel, programatorul are posibilitatea de a se concentra numai asupra aspectelor particulare ale aplicatiei, lasand aspectele standard (clase de ferestre, proceduri fereastra) in seama claselor MFC.
Clasele continute de biblioteca MFC se clasifica astfel:
clase de uz general - clase pentru manipularea fisierelor (CFile) si sirurilor de caractere (CString), clase exceptii (CException), clase pentru reprezentarea unor zone de pe ecran (CRect, CPoint);
clase de obiecte vizuale - aceste clase manevreaza aproape tot ce este vizibil intr-un program Windows. In aceasta categorie intra clasele de ferestre (CWnd si clasele derivate din ea), meniuri (CMenu), controale (CButton, CEdit, CListBox, etc. - derivate din clasa CWnd) si obiecte de desenare, cum ar fi creioanele (CPen) si pensulele (CBrush);
clase de aplicatie - clasele care gestioneaza obiectele fir de executie (CWinThread), aplicatie (CWinApp - derivata din CWinThread), precum si clasele care implementeaza arhitectura Document-View (CDocument, CView si clasele derivate din acestea )
clase de tip colectie - aceste clase se folosesc la stocarea altor obiecte de tip structuri de date de tip tablou (CArray), lista (CList), sau harta (CMap).
clase suport OLE2 - pentru scrierea aplicatiilor care necesita facilitati OLE2;
clase pentru baze de date - pentru manipularea bazelor de date (Cdatabase, CRecordset, CdaoDatabase, CdaoRecordset);
clase pentru dezvoltarea aplicatiilor distribuite (in retea) - CSocket (pentru deschiderea unui canal de comunicatie intre doua calculatoare) CFTPConnection si CHTTPConnection (pentru deschiderea unei sesiuni de lucru FTP, respectiv HTTP).
In cadrul bibliotecii MFC se foloseste mostenirea multipla. Majoritatea claselor MFC sunt derivate din clasa CObject. Toate clasele care reprezinta ferestre sau controale sunt derivate din clasa CWnd. Clasele CObject si CWnd utilizeaza functiile virtuale. Aceasta permite obiectelor din program sa acceseze functii de uz general, prin intermediul unui pointer de baza.
Un program care utilizeaza MFC se scrie mai usor decat daca se folosesc functiile Windows API si presupune urmatoarele etape:
- se creaza un proiect Win32 Application
- din meniul Project->Settings se selecteaza Settings for: all configurations, iar de la tab-ul General se selecteaza Using MFC in a shared library.
- se introduce codul programului, se compileaza si se linkediteaza.
Exemplu:
#include <afxwin.h>
class CFirstApp: public CWinApp
class CFirstWnd: public CFrameWnd
BOOL CFirstApp::InitInstance()
CFirstWnd::CFirstWnd()
CFirstApp theApp;
Este necesara includerea in fisierul sursa a fisierului header afxwin.h care contine declaratiile claselor MFC.
Orice program MFC are o clasa derivata public din clasa CWinApp. De obicei, aceasta clasa redefineste metoda InitInstance a clasei CWinApp. Metoda InitInstance, dupa cum sugereaza si numele sau, este apelata automat de cadrul aplicatie la pornirea unei instante a aplicatiei. Ea este declarata virtuala in cadrul clasei CWinApp, asa incat se va apela varianta corecta (cea redefinita in noua clasa aplicatie). Este neaparat necesara redefinirea functiei InitInstance cu semnatura: BOOL InitInstance() pentru a nu se pierde caracterul de functie virtuala. De obicei, functia InitInstance are rolul de a crea fereastra principala a aplicatiei si de o a afisa pe ecran. Pentru aceasta, in functia InitInstance se foloseste variabila m_pMainWnd, membra a clasei CWinApp si mostenita de clasa aplicatie (CFirstApp in cazul de mai sus). Aceasta variabila este de tip CWnd*. Ea este initializata folosind o linie de program de forma: m_pMainWnd = new CFirstWnd; unde in operatorul new se apeleaza constructorul unei clase derivata, direct sau indirect, in mod public din clasa CWnd. Aceasta permite conversia explicita de la un obiect de tip CFirstWnd* (returnat de operatorul new, in exemplu) la un obiect de tip CWnd* (m_pMainWnd).
Dupa crearea obiectului de tip fereastra, acesta este afisat pe ecran folosind functiile ShowWindow si UpdateWindow, membre ale clasei CWnd. Functia ShowWindow primeste ca parametru un intreg care specifica modul de afisare initiala a ferestrei aplicatiei (normal, minimizat, maximizat).
Dupa succesiunea normala a operatiilor sus-mentionate, functia InitInstance returneaza TRUE, semnalizand faptul ca aplicatia poate continua normal.
Folosirea unei clase derivate (direct sau indirect) din clasa CWnd nu este obligatorie. Se pot folosi una dintre clasele fereastra furnizate de MFC: CWnd, CFrameWnd, sau alta clasa fereastra. Totusi, exemplul de mai sus defineste o noua clasa fereastra, bazata pe clasa CFrameWnd. Motivul este prezentat in paragraful urmator. Clasa CFrameWnd este derivata direct din clasa CWnd, si reprezinta o fereastra cadru a unei aplicatii. Constructorul clasei CFirstWnd apeleaza functia Create (membra a clasei CFrameWnd). Primul parametru se refera la clasa de ferestre pe care dorim sa o folosim pentru fereastra cadru a aplicatiei. El este NULL, si se va folosi o clasa de ferestre inregistrata de MFC. Cel de-al doilea parametru este titlul ferestrei principale a aplicatiei. Ceilalti parametri ai functiei CFrameWnd::Create iau valori implicite.
Orice program MFC poseda un obiect (si numai unul) derivat din clasa aplicatie (CfirstApp::theApp, in cazul exemplului de mai sus). Declararea unui asemenea obiect (sub forma unei variabile globale) duce la declansarea mecanismului MFC de desfasurare a unei aplicatii (apelul functiei InitInstance, urmat de alte apeluri de metode, ascunse programatorului). Putem considera acest obiect aplicatie ca fiind echivalent functiei main dintr-un program consola, sau functiei WinMain dintr-un program Windows scris folosind Windows API.
Manipularea mesajelor in MFC
Se poate observa ca aceasta aplicatie nu trateaza nici un mesaj adresat ei, si lasa tratarea mesajelor in seama procedurilor implicite. Mesajele Windows pot fi tratate dupa cum ilustreaza programul de mai jos:
#include <afxwin.h>
class CFirstApp: public CWinApp
class CFirstWnd: public CFrameWnd
BOOL CFirstApp::InitInstance()
BEGIN_MESSAGE_MAP(CFirstWnd, CFrameWnd)
ON_WM_CLOSE()
END_MESSAGE_MAP()
CFirstWnd::CFirstWnd()
void CFirstWnd::OnClose()
CFirstApp theApp;
Pentru a putea trata mesajele adresate unei ferestre, este necesara definirea unei harti de mesaje. O harta de mesaje este utilizata pentru a stabili legaturi intre mesajele transmise unei ferestre si functiile destinate procesarii acestor mesaje. Declararea unei harti de mesaje se face in interiorul unei clase derivate din clasa CWnd, folosind macroul DECLARE_MESSAGE_MAP, astfel: DECLARE_MESSAGE_MAP().
Clasa fereastra, derivata din clasa CWnd va trata mesajele Windows intr-un mod specific aplicatiei. Declararea hartii de mesaje si a functiilor de tratare a mesajelor se face in cadrul unei sectiuni protejate a clasei fereastra. Functiile de tratare a mesajelor au semnaturi predefinite. Declararea lor incepe cu cuvantul afx_msg, care semnalizeaza compilatorului faptul ca este vorba despre o functie de tratare a mesajelor. Ce urmeaza dupa acest cuvant cheie este specific fiecarui mesaj tratat. Functia de tratare a mesajului WM_CLOSE are semnatura afx_msg void OnClose() si este de fapt o functie membra a clasei CWnd. Aceasta functie este redefinita de clasa CFirstWnd. Functia OnClose redefinita apeleaza versiunea sa de baza (prin intructiunea CFrameWnd::OnClose), dar inainte de aceasta, apeleaza functia MessageBox. Functia MessageBox apelata nu este functia MessageBox din Windows API. Este vorba despre functia CWnd::MessageBox. Se observa ca cele doua functii au semnaturi diferite:
int MessageBox(HWND, LPCSTR, LPCSTR, UINT); //Win API
int MessageBox(LPCSTR, LPCSTR, UINT); //membru CWnd
Functia Windows API MessageBox, poate fi apelata in programul de mai sus sub forma:
::MessageBox(this->m_hWnd, "", "", MB_OK);
Functia API MessageBox solicita ca prim parametru o variabila de tip HWND. Forma this->m_hWnd se refera la un membru de tip HWND, numit m_hWnd, mostenit de clasa CFirstWnd din clasa CWnd.
De retinut faptul ca orice functie Windows API care este redefinita intr-o clasa MFC se poate apela (in interiorul acelei clase, sau al unei clase derivate din ea) folosind constructia
::Nume_Functie_API(lista_parametri_actuali);
Definirea hartii de mesaje se face in exteriorul clasei. Se folosesc macrourile BEGIN_MESSAGE_MAP si END_MESSAGE_MAP, care marcheaza inceputul, respectiv sfarsitul hartii de mesaje.
Macroul BEGIN_MESSAGE_MAP primeste doi parametri: numele clasei derivate si numele clasei de baza. Macroul END_MESSAGE_MAP nu primeste nici un parametru. Aceste doua macrouri apar la inceputul, respectiv sfarsitul oricarei harti de mesaje.
La receptionarea unui mesaj, se incearca tratarea lui printr-o functie definita in clasa derivata. Daca clasa derivata nu furnizeaza o functie de tratare a mesajului, tratarea mesajului este lasata in seama clasei de baza. Acest mecanism se repeta in cazul clasei de baza (daca aceasta este la randul ei derivata dintr-o alta clasa).
Harta de mesaje contine, intre macrourile de inceput si sfarsit, intrari care specifica ce mesaje sunt tratate de clasa respectiva. Intrarile in harta de mesaje sunt de fapt macrouri. Fiecare mesaj general Windows are asociat in MFC un astfel de macrou. Regula de numire a macroului asociat este urmatoarea: se adauga la numele mesajului (scris cu litere mari) prefixul ON_. Rezulta astfel macrouri de forma:
ON_WM_CLOSE()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
Pentru fiecare dintre aceste macrouri (folosite in harta de mesaje), clasa fereastra trebuie sa declare si sa defineasca o functie de tratare a mesajului respectiv (cu o semnatura predefinita). Pentru mesajele WM_CLOSE, WM_PAINT si WM_LBUTONDOWN, aceste functii au semnaturile:
afx_msg void OnClose();
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
Toate aceste functii sunt functii membre ale clasei CWnd. Datorita faptului ca ele sunt redefinite si incluse in harta de mesaje a clasei CFirstWnd, se apeleaza versiunea corecta a lor (fara a fi nevoie de declararea lor ca functii virtuale).
In cele ce urmeaza, vom extinde programul prezentat anterior, astfel incat sa trateze mesajul WM_PAINT. Mesajul WM_PAINT este transmis unei ferestre ori de cate ori este necesara redesenarea sa (de exemplu, cand este afisata pentru prima data fereastra, sau cand este mutata sau redimensionata). Iata cum se trateaza acest mesaj folosind MFC:
#include <afxwin.h>
class CFirstApp: public CWinApp
class CFirstWnd: public CFrameWnd
BOOL CFirstApp::InitInstance()
BEGIN_MESSAGE_MAP(CFirstWnd, CFrameWnd)
ON_WM_CLOSE()
ON_WM_PAINT()
END_MESSAGE_MAP()
CFirstWnd::CFirstWnd()
void CFirstWnd::OnClose()
void CFirstWnd::OnPaint()
CFirstApp theApp;
Functia CFirstWnd::OnPaint() obtine un context de dispozitiv (device context) folosit pentru desenare. In acest scop, se creeaza un obiect de tip CPaintDC (CPaintDC dc(this)). Clasa CPaintDC este derivata din clasa CDC, care contine majoritatea functiilor folosite pentru desenarea intr-un context dispozitiv (afisare de texte, trasare de linii, figuri geometrice, etc). De asemenea, aceasta functie obtine dimensiunile curente ale ferestrei, folosind un obiect de tip CRect, si functiile CRect::Width(), CRect::Height(), CWnd::GetClientRect(CRect&); In final, functia afiseaza textul "Hello!" centrat in fereastra aplicatiei, folosind functia CDC::TextOut(int x, int y, LPCSTR txt, int count).
Pentru a desena intreaga zona client cu culoarea alba, se utilizeaza:
dc.FillSolidRect(rcClient, RGB(255, 255, 255));
prin care se apeleaza functia CDC::FillSolidRect(CRect, COLORREF). Cel de-al doilea parametru este o variabila de tip COLORREF (un cuvant de 32 de biti, care specifica continutul de rosu, verde si albastru). Pentru obtinerea sa, se foloseste macroul RGB(unsigned char red, unsigned char green, unsigned char blue).
Copyright © 2024 - Toate drepturile rezervate