Sunteți pe pagina 1din 6

Citirea hrii de mesaje Hrile de mesaje sunt pri ale modelului MFC de programare Windows.

n loc de a scrie funcia WinMain() care trimite mesaje la procedura fereastr (funcia) WindProc() i apoi s controlm ce mesaj a fost trimis pentru a activa funcia corespunztoare, vom scrie doar funcia care trateaz mesajul i vom aduga mesajul la harta de mesaje a clasei. Cadrul de lucru va face operaiunile necesare pentru a ruta acest mesaj n mod corect. Construirea hrii de mesaje Hrile de mesaje se construiesc n dou etape. Declaraia hrtii de mesaje (macro DECLARE_MESSAGE_MAP()) se face n fiierul .h al clasei, iar implementarea se face in fiierul .cpp al clasei (BEGIN_MESSAGE_MAP() ... END_MESSAGE_MAP()). Exemplu //{{AFX_MSG(CShowStringApp) afx_msg void OnAppAbout(); // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() Se declar funcia OnAppAbout() care este prefixat cu afx_msg ce constituie un comentariu pentru compilatorul de C++, dar care indic vizual c aceast funcie trateaz un mesaj. Aceast funcie o vom gsi i n cadrul macro-ului BEGIN_MESSAGE_MAP(), ca un parametru al macro-ului ON_COMMAND(). Primul parametru al acestui din urm macro este ID-ul mesajului (comenzii n acest caz), iar al doilea numele funciei ce trateaz acest mesaj. Cod in .cpp BEGIN_MESSAGE_MAP(CShowStringApp, CWinApp) //{{AFX_MSG_MAP(CShowStringApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

END_MESSAGE_MAP() Macro-ul DECLARE_MESSAGE_MAP() adaug date mebru i funcii la clasa respectiv. Practic se declar o tabel cu un numr de intrri variabil (sfritul tabelei este marcat (completat) de END_MESSAGE_MAP()) i funcii care opereaz cu acest elementele acestui tabel. Macro-uri pentru harta de mesaje BEGIN_MESSAGE_MAP i END_MESSAGE_MAP sunt macro-uri care ca i macro-ul DECLARE_MESSAGE_MAP din fiierul .h, declar anumite variabile membru i funcii pe care cadrul de lucru le va utiliza pentru a naviga prin hrile de mesaje ale tuturor obiectelor din sistem Printre macro-urile folosite n hrile de mesaje, enumerm: DECLARE_MESSAGE_MAPfolosit n fiierul .h pentru a declara c va exista o hartesaje in .cpp BEGIN_MESSAGE_MAPMarcheaz nceputul hrii de mesaje n fiierul surs. END_MESSAGE_MAPMarcheaz sfritul hrii de mesaje n fiierul surs. ON_COMMANDFolosit pentru a face legtura ntre comenzi i funciile care trateaz aceste comenzi. ON_COMMAND_RANGEFolosit pentru a face legtura ntre un grup de comenzi i funcia care le trateaz. ON_CONTROLFolosit pentru a face legtura ntre un mesaj de notificare al unui control i funcia ce-l trateaz. ON_CONTROL_RANGEFolosit pentru a face legtura ntre un grup de mesaje de notificare al unui control i funcia corespunztoare. ON_MESSAGEFolosit pentru a realiza legtura ntre un mesaj definit de utilizator i funcia care-l trateaz. ON_REGISTERED_MESSAGEFolosit pentru a realiza legtura ntre un mesaj defint de utilizator, dar nregistrat i funcia care-l trateaz. ON_UPDATE_COMMAND_UIFolosit pentru a indica funcia care va face actualizarea pentru o comand specific. ON_COMMAND_UPDATE_UI_RANGECa mai sus, dar pentru un grup de comenzi. ON_NOTIFYFolosit pentru a indica funcia ce va aduga informaii suplimentare, pentru un mesaj de notificare al unui control. ON_NOTIFY_RANGECa mai sus, dar pentru un grup de mesaje de notificare al unui control. ON_NOTIFY_EXCa la ON_NOTIFY, dar funcia va ntoarce TRUE sau FALSE pentru a indica dac notificarea poate fi trecut altui obiect pentru tratri suplimentare. ON_NOTIFY_EX_RANGECa mai sus, dar se refer la un grup de comenzi de notificare. n plus la ceste macro-uri, exist peste 100 de macro-uri, unul pentru fiecare din cele mai comune mesaje. De exemplu macro-ul ON_CREATE pentru mesajul WM_CREATE, etc. n mod obinuit aceste macro-uri sunt adugate la clas de ctre Class Wizard.

Cum lucreaz harta de mesaje Fiecare aplicaie are un obiect motenit din clasa CWinApp i o funcie membru Run(). Aceast funcie apeleaz funcia CWinThread::Run(), care apeleaz GetMessage(), TranslateMessage() i DispatchMessage(). Funcia fereastr (n SDK) tie handler-ul ferestrei pentru care este trimis mesajul. Fiecare obiect fereastr folosete acelai stil al clasei Windows i aceeai funcie WindProc, numit AfxWndProc(). MFC menine ceva asemntor, numit handle map, o tabel cu handler-ii ferestrelor i pointeri la obiecte, i framework-ul folosete aceasta pentru a trimite un pointer la obiectul C++, un CWnd*. n continuare el apeleaz WindowProc(), o funcie virtual a acestui obiect. Datorit polimorfismului, indiferent c este vorba de un Button sau o vizualizare se va apela funcia corect. WindowProc() apeleaz OnCmdMsg(), funcia C++ care efectiv manipuleaz mesajul. Mai nti caut dac acesta este un mesaj, o comand sau o notificare. Presupunnd c este un mesaj. caut n harta de mesage a clasei, folosind funciile i variabilele membru adugate la clas de DECLARE_MESSAGE_MAP, BEGIN_MESSAGE_MAP i END_MESSAGE_MAP. Modul de organizare al acestei tabele permite cutarea mesajului, dac este nevoie, n toat arborescena clasei. AfxWndProc()->WindowProc()->OnCmdMsg() Se va explica cum se adaug un mesaj la o clas i funcia corespunztoare acestuia, care clas trateaz mesajul, cum se scrie cod n funcie, etc. Recunoaterea mesajelor Exist aproximativ 900 mesaje Windows. Prefixele mesajului Windows i Tipuri fereastr Prefix ABM, ABN ACM, ACN BM, BN CB, CBN CDM, CDN CPL DBT DL DM EM, EN FM, FMEVENT HDM, HDN HKM IMC, IMN Window Type Appbar Animation control Button Combo box Common dialog box Control Panel application Any application (device change message) Drag list box Dialog box Edit box File Manager Header control HotKey control IME window

LB, LBN LVM, LVN NM PBM PBT PSM, PSN SB SBM STM, STN TB, TBN TBM TCM, TCN TTM, TTN TVM, TVN UDM WM

List box List view Any parent window (notification message) Progress bar Any application (battery power broadcast) Property sheet Status bar Scrollbar Static control Toolbar Track bar Tab control ToolTip Tree view Up Down control Generic window

Care e diferena ntre mesajele care se termin n M i cele care se termin n N? Primul este un mesaj la control (am apsat butonul, de exemplu), al doilea este un mesaj de notificare de la control la fereastra proprietar a controlului, care are semnificaia de am fost apsat, s-a ntmplat ceva n control.... Exist i mesaje care nu se termin n M (CB_) dar acioneaz la fel. nelegerea comenzilor O comand este un tip special de mesaj. Windows genereaz comenzi cnd utilizatorul alege un articol de meniu, apas un buton, sau altfel spune sistemului s fac ceva. Pentru un articol de meniu se primete mesajul WM_COMMAND iar pentru notificarea unui control WM_NOTIFY, cum ar fi selectarea dintr-un list box. Comenzile i notificrile sunt trecute prin SO ca orice alt mesaj, pn cnd acestea ajung la OnWndMsg(). n acest punct pasarea mesajului windows nceteaz i se starteaz rutarea comenzilor n MFC. Mesajele de comand au ca prim parametru, ID-ul articolului din meniu care a fost selectat sau a butonului care a fost apsat. Rutarea comenzilor este mecanismul pe care OnWndMsg() l folosete pentru a trimite comanda (sau notificarea) la obiectele care pot trata acest mesaj. Numai obiectele care sunt motenite din CWnd pot primi mesaje, dar toate obiectele care sunt motenite din CCmdTarget, incluznd CWnd i CDocument, pot primi comenzi sau notificri . Aceasta nseman c o clas motenit din CDocument poate avea o hart de mesaje. Pot s nu existe mesaje n aceast hart ci numai pentru comenzi i notificri, dar tot hart de mesaje se numete. Comenzile i notificrile ajung la clas prin mecanismul de rutare al comenzilor. OnWndMsg() apeleaz CWnd::OnCommand() sau CWnd::OnNotify().

OnCommand() apeleaz OnCmdMsg(). OnNotify() apeleaz de asemenea OnCmdMsg(). Bineneles c ambele funcii efectueaz anumite controale nainte de a face aceste apeluri. OnCmdMsg() este virtual, ceea ce nseamn c diferite comenzi au implementri diferite. Implementarea pentru fereastra cadru trimite comanda vizualizrilor i documentelor pe care le conine. Comanda pentru actualizri Folosit n special pentru actualizarea articolelor din meniu. De exemplu cnd se selecteaz text in vizualizare i opiunile de Copy, Cut, Paste, Undo sunt implementate aceste articole de menu vor fi afiate n starea enable sau disable (funcie de logica programului). Exist dou posibiliti de a face acest lucru: continuous update approach i update-on-demand approach. Continuous update approach presupune existena unei tabele mari ce conine cte o intrare pentru fiecare meniu i un flag care va indica dac opiunea este disponibil sau nu. Cea de-a doua posibilitate presupune controlarea tuturor condiiilor asupra unui articol de meniu nainte ca meniul s fie afiat. n acest caz obiectul care are meniul va ti mai multe despre acesta, n schimb nu toat aplicaia va avea acces la aceste informaii. Tehinca MFC-ului este de a utiliza un obiect numit CCmdUI, o comand a interfeei utilizatorului, i de a da acest obiect cnd se trimite mesajul CN_UPDATE_COMMAND_UI. n harta de mesaje va aprea macro-ul ON_UPDATE_COMMAND_UI. Ce se ntmpl in realitate? SO trimite mesajul WM_INITMENUPOPUP; clasa CFrameWnd va construi un obiect CCmdUI, seteaz variabilele membru ce corespund primului articol din meniu i apeleaz funcia membru DoUpdate(). DoUpdate() trimite mesajul CN_COMMAND_UPDATE_UI la ea nsi, cu un pointer la obiectul CCmdUI. Se vor seta variabilele membru ale obiectului CCmdUI cu articolul doi din meniu i procesul continu pn cnd este parcurs tot meniul. Obiectul CCmdUI este folosit pentru a valida (enable) sau invalida (disable) [ gray(disable) sau ungray(enable) ] articolele din meniu sau butoane. CCmdUI are urmtoarele funcii membru: Enable() Are un parametru care poate lua valorile TRUE sau FALSE (implicit TRUE). SetCheck() Marcheaz sau demarcheaz articolul. SetRadio() Seteaz sau nu unul din butoanele radio al unui grup. SetText()Seteaz textul unui meniu sau buton. DoUpdate()Genereaz mesajul. Exemplu:

BEGIN_MESSAGE_MAP(CWhoisView, CFormView) ... ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) ... END_MESSAGE_MAP() void CWhoisView::OnUpdateEditPaste(CCmdUI* pCmdUI) { pCmdUI->Enable(::IsClipboardFormatAvailable(CF_TEXT)); }