MFC Library Message Mapping

Refer to the OnLButtonDown member function in the previous example application. You might think that OnLButtonDown would be an ideal candidate for a virtual function. A window base class would define virtual functions for mouse event messages and other standard messages, and derived window classes could override the functions as necessary. Some Windows class libraries do work this way.

The MFC library application framework doesn't use virtual functions for Windows messages. Instead, it uses macros to "map" specified messages to derived class member functions. Why the rejection of virtual functions? Suppose MFC used virtual functions for messages. The CWnd class would declare virtual functions for more than 100 messages. C++ requires a virtual function dispatch table, called a vtable, for each derived class used in a program. Each vtable needs one 4-byte entry for each virtual function, regardless of whether the functions are actually overridden in the derived class. Thus, for each distinct type of window or control, the application would need a table consisting of over 400 bytes to support virtual message handlers.

What about message handlers for menu command messages and messages from button clicks? You couldn't define these as virtual functions in a window base class because each application might have a different set of menu commands and buttons. The MFC library message map system avoids large vtables, and it accommodates application-specific command messages in parallel with ordinary Windows messages. It also allows selected nonwindow classes, such as document classes and the application class, to handle command messages. MFC uses macros to connect (or map) Windows messages to C++ member functions. No extensions to the C++ language are necessary.

An MFC message handler requires a function prototype, a function body, and an entry (macro invocation) in the message map. ClassWizard helps you add message handlers to your classes. You select a Windows message ID from a list box, and the wizard generates the code with the correct function parameters and return values.