MFC Event handling

MFC uses very limited number of callback events via virtual functions. A wide range of events can be implemented by event message array. There is a static array of type AFX_MSGMAP_ENTRY named as _ messageEntries. AFX_MSGMAP_ENTRY is a structure which has all necessary members needed to represent a windows message.

Message Data Structure

struct AFX_MSGMAP_ENTRY
{
  UINT nMessage;   /* windows message */
  UINT nCode;      /* control code or WM_NOTIFY code */
  UINT nID;        /* control ID (or 0 for windows messages) */
  UINT nLastID;    /* used for entries specifying a range of control id's */
  UINT nSig;       /* signature type (action) or pointer to message # */
  AFX_PMSG pfn;    /* routine to call (or special value) */
};

MFC Message Map

User declares this array with DECLARE_MESSAGE_MAP and defines this with starting with BEGIN_MESSAGE_MAP and ends with END_MESSAGE_MAP. BEGIN_MESSAGE_MAP declares array name and opens static array entries. User defines event maps one by one. Then this array declaration is closed with END_MESSAGE_MAP which is an array element where all the member elements are zeros. MFC framework iterates through these array elements and calls the callback event function when a proper match is found. It stops if it reaches till the last element.

#define DECLARE_MESSAGE_MAP() \
private: \
  static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
  static AFX_DATA const AFX_MSGMAP messageMap; \
  virtual const AFX_MSGMAP* GetMessageMap() const; \

#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
  const AFX_MSGMAP* theClass::GetMessageMap() const \
    { return &theClass::messageMap; } \
  AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \
  { &baseClass::messageMap, &theClass::_messageEntries[0] }; \
  AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \
  { \

#define END_MESSAGE_MAP() \
    {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)} \
  }; \

#define ON_WM_PAINT() \
  { WM_PAINT, 0, 0, 0, AfxSig_vv, \
    (AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(void))&OnPaint },

Message Map Example

/* Use of MESSAGE_MAP */
class CMyDialog : public CDialog
{
  CMyDialog();
  void OnPaint();
  DECLARE_MESSAGE_MAP()
};

BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_WM_PAINT()
END_MESSAGE_MAP()
"; format_source($code, strlen($code)); ?>

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#