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 Window Type
ABM, ABN Appbar
ACM, ACN Animation control
BM, BN Button
CB, CBN Combo box
CDM, CDN Common dialog box
CPL Control Panel application
DBT Any application (device change message)
DL Drag list box
DM Dialog box
EM, EN Edit box
FM, FMEVENT File Manager
HDM, HDN Header control
HKM HotKey control
IMC, IMN IME window
LB, LBN List box
LVM, LVN List view
NM Any parent window (notification message)
PBM Progress bar
PBT Any application (battery power broadcast)
PSM, PSN Property sheet
SB Status bar
SBM Scrollbar
STM, STN Static control
TB, TBN Toolbar
TBM Track bar
TCM, TCN Tab control
TTM, TTN ToolTip
TVM, TVN Tree view
UDM Up Down control
WM 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));
}

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