Documente Academic
Documente Profesional
Documente Cultură
Introducere n MFC 83
3. Introducere n MFC
Clasele incluse n biblioteca MFC sunt dispuse n mai multe categorii, dintre care
putem aminti:
clase de uz general - clase pentru manipularea fiierelor (CFile) i irurilor de
caractere (CString), clase excepii (CException), clase pentru reprezentarea unor
zone de pe ecran (CRect, CPoint);
clase de obiecte vizuale - aceste clase manevreaz aproape tot ce este vizibil ntr-
un program Windows. n aceast categorie intr clasele de ferestre (CWnd,
CFrameWnd i clasele derivate din ele), meniuri (CMenu), controale (CButton,
CEdit, CListBox etc. derivate din clasa CWnd) i obiecte de desenare, cum ar fi
creioanele (CPen) i pensulele (CBrush);
clase de aplicaie - n aceast categorie sunt incluse clasele care gestioneaz
obiectele fir de execuie (CWinThread), aplicaie (CWinApp derivat din
CWinThread), precum i clasele care implementeaz arhitectura Document-
Reprezentare (CDocument, CView, i clasele derivate din ele). Arhitectura
Document-Reprezentare este folosit de majoritatea programelor Windows;
clase de tip colecie - aceste clase se folosesc pentru stocarea altor obiecte n
structuri de date de tip tablou (CArray), list (CList) sau hart (CMap);
clase suport OLE2 - aceste clase simplific scrierea aplicaiilor care beneficiaz
de facilitile OLE2;
clase pentru baze de date - aceste clase faciliteaz manipularea bazelor de date
(CDatabase, CRecordset, CDaoDatabase, CDaoRecordset);
clase pentru dezvoltarea aplicaiilor distribuite (n reea) - cteva dintre aceste
clase sunt: CAsyncSocket, CSocket (pentru deschiderea unui canal de comunicaie
ntre dou calculatoare), CFTPConnection i CHTTPConnection (pentru
deschiderea unei sesiuni de lucru FTP, respectiv HTTP);
H. Vlean, 2004
84 Visual C++. Programarea Interfeelor Utilizator
deschidem un nou proiect de tip Win32 Application, care nu conine nici un fiier
(An empty project);
din meniul Project->Settings, selectm Settings for: all configurations, iar de la
tab-ul General, n caseta combinat Microsoft Foundation Classes: vom alege
Using MFC in a shared library;
introducem codul programului, compilm, editm legturile i lansm n execuie.
S facem un prim exemplu. Vom crea un proiect dup paii descrii mai sus, pe
care-l vom numi PrimulMFC. Vom aduga proiectului un fiier header, numit
PrimulMFC.h:
#include <afxwin.h>
#include "PrimulMFC.h"
BOOL CPrimaAplicatie::InitInstance()
{
m_pMainWnd = new CPrimaFereastra;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
Capitolul 3. Introducere n MFC 85
CPrimaFereastra::CPrimaFereastra()
{
Create(NULL, "Prima mea aplicatie MFC");
}
CPrimaAplicatie primaApp;
BOOL InitInstance();
unde n operatorul new se apeleaz constructorul unei clase derivat, direct sau
indirect, n mod public, din clasa CWnd sau CFrameWnd. Aceasta permite
conversia explicit de la un obiect de tip CPrimaFereastra* (returnat de operatorul
new, n exemplu) la un obiect de tip CWnd* (respectiv m_pMainWnd).
Dup crearea obiectului de tip fereastr, acesta este afiat pe ecran folosind
funciile ShowWindow() i UpdateWindow(), membre ale clasei CWnd. Funcia
ShowWindow() primete ca parametru un ntreg (int m_nCmdShow, definit n clasa
CWinApp) care specific modul de afiare iniial a ferestrei aplicaiei (normal,
minimizat, maximizat,etc.).
Dup succesiunea normal a operaiilor sus-menionate, funcia InitInstance()
returneaz TRUE, semnaliznd faptul c aplicaia poate continua normal.
folosirea unei clase derivate (direct sau indirect) din clasa CWnd nu este
obligatorie. Se pot folosi una dintre clasele fereastr furnizate de MFC: CWnd,
CFrameWnd, sau alt clas fereastr. Totui, exemplul de mai sus definete o nou
clas fereastr, bazat pe clasa CFrameWnd. Motivul utilizrii acestei clase ca i
H. Vlean, 2004
86 Visual C++. Programarea Interfeelor Utilizator
Pentru a putea trata mesajele adresate unei ferestre, este necesar definirea unei
hri de mesaje. O hart de mesaje este utilizat pentru a stabili legturi ntre mesajele
transmise unei ferestre i funciile destinate procesrii acestor mesaje. Declararea unei
Capitolul 3. Introducere n MFC 87
hri de mesaje se face n interiorul unei clase derivate din clasa CWnd (uzual n
fiierul header), folosind macroul DECLARE_MESSAGE_MAP, astfel:
DECLARE_MESSAGE_MAP()
Declararea hrii de mesaje se face n clasa derivat din clasa fereastr, deoarece,
s ne reamintim, Windows trimite toate mesajele ctre fereastra asociat programului
aplicaie. Declararea hrii de mesaje i a funciilor de tratare a mesajelor se face n
cadrul unei seciuni protejate a clasei fereastr. Funciile de tratare a mesajelor au
semnturi predefinite i declararea lor ncepe ntotdeauna cu cuvntul afx_msg. Acest
cuvnt semnalizeaz compilatorului faptul c este vorba despre o funcie ce trateaz
mesaje. Ceea ce urmeaz dup acest cuvnt cheie, este specific fiecrui mesaj tratat.
Nu este necesar nvarea semnturilor tuturor funciilor de tratare a mesajelor.
Visual C++ posed un program vrjitor, numit ClassWizard, care permite inserarea
automat a funciilor de tratare a mesajelor n cadrul unei clase. Pentru folosirea
ClassWizard, proiectele trebuie s fi fost generate cu AppWizard, un alt program
vrjitor. Din pcate, nseamn c nu putem folosi ClassWizard n exemplul de mai sus.
Din fericire ns, uzual proiectele MFC se genereaz folosind AppWizard, tocmai n
ideea de a beneficia de suportul oferit de ClassWizard (i alte utilitare).
i este de fapt o funcie membr a clasei CWnd. Aceast funcie este redefinit de
clasa CPrimaFereastraWnd. Este necesar ca funcia OnClose() redefinit s apeleze
versiunea sa de baz, prin instruciunea CFrameWnd::OnClose(), pentru c aceasta din
urm distruge obiectul fereastr i dealoc memoria. Dac nu am apela aceast
funcie, ar trebui s avem noi grij de aceste operaii.
Semntura funciei de tratare a mesajului WM_KEYDOWN este
#include <afxwin.h>
#include "PrimulMFC.h"
BOOL CPrimaAplicatie::InitInstance()
{
return TRUE;
}
BEGIN_MESSAGE_MAP(CPrimaFereastra, CFrameWnd)
ON_WM_CLOSE()
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
H. Vlean, 2004
88 Visual C++. Programarea Interfeelor Utilizator
CPrimaFereastra::CPrimaFereastra()
{
Create(NULL, "Prima mea aplicatie MFC");
}
void CPrimaFereastra::OnClose()
{
MessageBox("Aplicatie terminata", "Gata", MB_OK|MB_ICONSTOP);
CFrameWnd::OnClose();
}
void CPrimaFereastra::OnKeyDown(UINT nChar)
{
CString text;
switch(nChar){
case VK_BACK: text="Ati apasat tasta BackSpace"; break;
case VK_TAB: text="Ati apasat tasta Tab"; break;
case VK_LEFT: text="Ati apasat tasta SageataStinga";break;
case VK_RIGHT: text="Ati apasat tasta SageataDreapta"; break;
case VK_UP: text="Ati apasat tasta SageataSus"; break;
case VK_DOWN: text="Ati apasat tasta SageataJos"; break;
case VK_RETURN: text="Ati apasat tasta Enter"; break;
case VK_ESCAPE: text="Ati apasat tasta Escape"; break;
case VK_CONTROL: text="Ati apasat tasta Control"; break;
default: text="Ati apasat alta tasta"; break;
}
MessageBox(text, "Mesaj",MB_OK|MB_ICONEXCLAMATION);
}
CPrimaAplicatie primaApp;
Prima semntur aparine funciei API, iar a doua funciei CWnd. Dac am fi dorit
s apelm funcia Windows API MessageBox(), ar fi trebuit s scriem:
::Nume_Functie_API(lista_parametri_actuali);
ON_WM_CLOSE()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
Pentru fiecare dintre aceste macrouri (folosite n harta de mesaje), clasa fereastr
trebuie s declare i s defineasc o funcie de tratare a mesajului respectiv (cu o
semntur predefinit). Pentru mesajele WM_CLOSE, WM_PAINT i WM_LBUTTONDOWN,
exemplificate mai sus, aceste funcii au semnturile:
Toate aceste funcii sunt funcii membre ale clasei CWnd. Datorit faptului c ele
sunt redefinite i incluse n harta de mesaje a clasei CPrimaFereastraWnd, se
apeleaz versiunea corect a lor (fr a fi nevoie de declararea lor ca funcii virtuale).
Nu se folosete mecanismul funciilor virtuale din urmtorul considerent: dac o clas
H. Vlean, 2004
90 Visual C++. Programarea Interfeelor Utilizator
de baz declar o funcie virtual, toate clasele derivate din acea clas de baz vor
conine cte un tablou de pointeri la versiunea corect de funcie virtual care trebuie
apelat. Avnd n vedere faptul c sunt cteva sute de mesaje Windows, dimensiunea
acestui tablou de funcii virtuale ar fi fost foarte mare i de aceea s-a recurs la soluia
hrilor de mesaje.
Din cele artate mai sus, putem trage concluzia c MFC lucreaz cu dou tipuri de
funcii:
funcii obinuite, care pot fi fie funcii membre ale unei clase, fie funcii din afara
clasei. Pentru aceste funcii sunt necesare urmtoarele operaii:
1. declararea lor, uzual n fiiere header;
2. definirea lor, uzual n fiiere surs;
3. apelarea funciei n cadrul programului;
funcii care rspund la mesaje, care se execut la transmiterea unui mesaj de
ctre sistemul de operare ctre program. Pentru aceste funcii, sunt necesare
urmtoarele operaii:
1. declararea lor, uzual n fiiere header, obligatoriu ca i funcii afx_msg;
2. inserarea n harta de mesaje a macroului ON_... corespunztor, pentru a
specifica programului ce mesaje sunt interceptate;
3. definirea lor, uzual n fiiere surs;
CPointeste o clas avnd structura de date format din variabilele publice long x
i long y.Este utilizat pentru a ncapsula coordonatele unui punct de pe ecran.
CString este o clas care ncapsuleaz iruri de caractere. irurile pot fi formatate
respectnd tehnica de formatare din funcia printf(). Aceste clase vor fi descrise mai pe
larg n capitolele urmtoare.