Visual C++ 6 Unleashed

Visual C++ 6 Unleashed

By MICKEY WILLIAMS and David Bennett

Message Dispatching

As mentioned in Chapter 2, "MFC Class Library Overview," the Run() function of the CWinThread class provides the message pump for your application. (For now, let's assume there is only one thread in your application. If you want to learn how to use threads to have more than one message pump in your app, see Chapter 16, "Multithreading." ) The only function of the message pump is to wait for messages and then send them where they should go to be handled—this is called dispatching the message.

When the message pump receives a Windows message, it identifies the class that should get first crack at handling the message by consulting an internal structure that maps the handles of existing windows to the class responsible for each window. MFC will then check to see whether this targeted class provides an entry for the message in its message map. If an entry is found, the message is passed to the handler, ending the dispatch process. If an entry for the message is not found, MFC will check the message map of the base class for the targeted class, moving farther up the class hierarchy until an entry is found.

For command messages, the search is quite a bit more complicated. When a command is routed to a class, it may allow another class to try to handle it before checking its own message map or routing the command to another command target. In most cases, a command target will route commands in the following order:

  1. To the currently active child command target object
  2. To itself
  3. To other command targets

Table 3.1 lists more specific routing for the usual command target classes. When a class is mentioned in the right side of the table, you should jump to that class on the left side, follow its routing, then go back to where you were to continue the routing.

Table 3.1. Standard Command Routing

This Object Type Routes Commands in This Order
MDI Main Frame 1. Active CMDIChildWnd
  2. This frame window
  3. Application (CWinApp)
MDI child frame 1. Active view
  2. This frame window
SDI Main Frame 1. Active view
  2. This frame window
  3. Application (CWinApp)
View 1. This view
  2. Document associated with this view
Document 1. This document
  2. Template associated with this document
Dialog Box 1. This dialog box
  2. Window that owns this dialog
  3. Application (CWinApp)

By now, this is as clear as mud, right? The following example will clear things up a bit.

Suppose you add a menu item that will send the ID_MY_COMMAND command message to the MDI main frame of your application:

  1. The command is first routed to the main frame, which will check the active child frame first.
  2. The child frame will first check the active view, which checks its own message map before routing the command to the associated document.
  3. The document will check its own message map before checking the message map of the associated document template.
  4. Going back to the child frame's routing, the child frame will check its own message map.
  5. Going back to the main frame's routing, the main frame will check its own message map.
  6. Ultimately, the message map of the application object is checked, where an entry for your message is found and the appropriate handler is called.

If you find that you must use a different command routing scheme, perhaps to include your own special command target classes, you can do so by overriding the OnCmdMsg()member of CCmdTarget. This may involve overriding OnCmdMsg() for several classes and is beyond the scope of this book; for more information, see Command Routing in the MFC online documentation.

I know this all seems horribly complicated, but it will make much more sense when you work with documents and views in the next chapter. In fact, it will seem much simpler even sooner, when you see how you can use ClassWizard to associate messages with the appropriate handler.

Share ThisShare This

Informit Network