Home Index  | Back

New Page 1
Lesson 1 -Building Your First Windows Application

1.1 : Creating a Windows Application

1.2 : Creating a Dialog-Based Application

1.3 : Creating DLLs, Console Applications, and More

1.4 : Changing Your AppWizard Decisions
 1.5 : Understanding AppWizard’s Code
 1.6 : Understanding a MDI Application
 1.7 : Understanding the Components of a Dialog-Based Application

Lesson 2 - Dialogs and Controls

2.1 : Understanding Dialog Boxes

2.2 : Creating a Dialog Box Resource

 2.3 : Writing a Dialog Box Class
 2.4 : Using the Dialog Box Class
Lesson 3 - Messages and Commands

3.1 : Understanding Message Routing

3.2 : Understanding Message Loops

 3.3 : Reading Message Maps
 3.4 : Learning How ClassWizard Helps You Catch Messages
 3.5 : Recognizing Messages
 3.6 : Understanding Commands
 3.7 : Understanding Command Updates
 3.8 : Learning How ClassWizard Helps You Catch Commands and Command Updates

Lesson 4 - Documents and Views

4.1 : Understanding the Document Class

4.2 : Understanding the View Class

4.3 : Creating the Rectangles Application

 4.4 : Other View Classes

4.5 : Document Templates, Views, and Frame Windows

Lesson 5 - Drawing on the Screen

5.1 :Understanding Device Contexts

 5.2 : Introducing the Paint1 Application
 5.3 : Building the Paint1 Application
 5.4 : Scrolling Windows
 5.5 : Building the Scroll Application
Lesson 6 - Building a Complete Application: ShowString

6.1 : Building an Application That Displays a String

 6.2 : Building the ShowString Menus
 6.3 : Building the ShowString Dialog Boxes
 6.4 : Making the Menu Work
 6.5 : Making the Dialog Box Work
 6.6 : Adding Appearance Options to the Options Dialog Box
Lesson 7 -  Status Bars and Toolbars

7.1 : Working with Toolbars

 7.2 : Working with Status Bars
Lesson 8 - Common Controls

8.1 : The Progress Bar Control

 8.2 : The Up-Down Control
 8.3 : The Image List Control
 8.4 : The List View Control
 8.5 : The Tree View Control
 8.6 : The Rich Edit Control
 8.7 : The Date Picker Control
 8.8 : Month Calendar Control
 8.9 : Scrolling the View
Lesson 9 - Property Pages and Sheets

9.1 : Introducing Property Sheets

 9.2 : Creating the Property Sheet Demo Application
 9.3 : Running the Property Sheet Demo Application
Lesson 10 - ActiveX Concepts

10.1 : The Purpose of ActiveX

10.2 : Object Linking

10.3 : Object Embedding

 10.4 : Containers and Servers
 10.5 : Toward a More Intuitive User Interface
 10.6 : The Component Object Model  

10.7 : Automation

 10.8 : ActiveX Controls

Lesson 11 -  Building an ActiveX Control

11.1 : Creating a Rolling-Die Control

11.2 : Displaying the Current Value

11.3 : Reacting to a Mouse Click and Rolling the Die 

 11.4 : Creating a Better User Interface
 11.5 : Generating Property Sheets
Lesson 12 - Database Access

12.1 : Understanding Database Concepts

12.2 : Creating an ODBC Database Program

 12.3 : Choosing Between ODBC and DAO
 12.4 : OLE DB

Lesson - 3:Messages and Commands

3.3 : Reading Message Maps

Message maps are part of the MFC approach to Windows programming. Instead of writing a WinMain() function that sends messages to your WindProc and then writing a WindProc that checks which kind of message this is and then calls another of your functions, you just write the function that will handle the message, and you add a message map to your class that says, in effect, "I will handle this sort of message." The framework handles whatever routing is required to send that message to you.

Message maps come in two parts: one in the .h file for a class and one in the corresponding .cpp. Typically, they are generated by wizards, although in some circumstances you will add entries yourself. Listing 3.4 shows the message map from the header file of one of the classes in a simple application called ShowString.

Listing 3.4 Message Map from showstring.h

//{{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()

This declares a function called OnAppAbout(). The specially formatted comments around the declarations help ClassWizard keep track of which messages are caught by each class. DECLARE_MESSAGE_MAP() is a macro, expanded by the C++ compiler’s preprocessor, that declares some variables and functions to set up some of this magic message catching.

The message map in the source file, as shown in Listing 3.5, is quite similar.

Listing 3.5 Message Map from Unit 6’s showstring.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()

3.3.1 Message Map Macros

BEGIN_MESSAGE_MAP and END_MESSAGE_MAP are macros that, like DECLARE_MESSAGE_MAP in the include file, declare some member variables and functions that the framework can use to navigate the maps of all the objects in the system. A number of macros are used in message maps, including these:

  • DECLARE_MESSAGE_MAP—Used in the include file to declare that there will be a message map in the source file.
     

  • BEGIN MESSAGE MAP—Marks the beginning of a message map in the source file.
     

  • END MESSAGE MAP—Marks the end of a message map in the source file.
     

  • ON_COMMAND—Used to delegate the handling of a specific command to a member function of the class.
     

  • ON_COMMAND_RANGE—Used to delegate the handling of a group of commands, expressed as a range of command IDs, to a single member function of the class.
     

  • ON_CONTROL—Used to delegate the handling of a specific custom control-notification message to a member function of the class.
     

  • ON_CONTROL_RANGE—Used to delegate the handling of a group of custom control-notification messages, expressed as a range of control IDs, to a single member function of the class.
     

  • ON_MESSAGE—Used to delegate the handling of a user-defined message to a member function of the class.
     

  • ON_REGISTERED_MESSAGE—Used to delegate the handling of a registered user-defined message to a member function of the class.
     

  • ON_UPDATE_COMMAND_UI—Used to delegate the updating for a specific command to a member function of the class.
     

  • ON_COMMAND_UPDATE_UI_RANGE—Used to delegate the updating for a group of commands, expressed as a range of command IDs, to a single member function of the class.
     

  • ON_NOTIFY—Used to delegate the handling of a specific control-notification message with extra data to a member function of the class.
     

  • ON_NOTIFY_RANGE—Used to delegate the handling of a group of control-notification messages with extra data, expressed as a range of child identifiers, to a single member function of the class. The controls that send these notifications are child windows of the window that catches them.
     

  • ON_NOTIFY_EX—Used to delegate the handling of a specific control-notification message with extra data to a member function of the class that returns TRUE or FALSE to indicate whether the notification should be passed on to another object for further reaction.
     

  • ON_NOTIFY_EX_RANGE—Used to delegate the handling of a group of control-notification messages with extra data, expressed as a range of child identifiers, to a single member function of the class that returns TRUE or FALSE to indicate whether the notification should be passed on to another object for further reaction. The controls that send these notifications are child windows of the window that catches them.

  • In addition to these, there are about 100 macros, one for each of the more common messages, that direct a single specific message to a member function. For example, ON_CREATE delegates the WM_CREATE message to a function called OnCreate(). You cannot change the function names in these macros. Typically, these macros are added to your message map by ClassWizard.

    3.3.2 How Message Maps Work

    The message maps presented in Listings 3.3 and 3.4 are for the CShowStringApp class of the ShowString application. This class handles application-level tasks such as opening a new file or displaying the About box. The entry added to the header file’s message map can be read as "there is a function called OnAppAbout() that takes no parameters." The entry in the source file’s map means "when an ID_APP_ABOUT command message arrives, call OnAppAbout()." It shouldn’t be a big surprise that the OnAppAbout() member function displays the About box for the application.

    If you don’t mind thinking of all this as magic, it might be enough to know that adding the message map entry causes your code to run when the message is sent. Perhaps you’re wondering just how message maps really work. Here’s how. Every application has an object that inherits from CWinApp, and a member function called Run(). That function calls CWinThread::Run(), which is far longer than the simple WinMain() presented earlier but has the same message loop at its heart: call GetMessage(), call TranslateMessage(), call DispatchMessage(). Almost every window object uses the same old-style Windows class and the same WindProc, called AfxWndProc(). The WindProc, as you’ve already seen, knows the handle, hWnd, of the window the message is for. MFC keeps something called a handle map, a table of window handles and pointers to objects, and the framework uses this to send a pointer to the C++ object, a CWnd*. Next, it calls WindowProc(), a virtual function of that object. Buttons or views might have different WindowProc() implementations, but through the magic of polymorphism, the right function is called.

    WindowProc()calls OnWndMsg(), the C++ function that really handles messages. First, it checks to see whether this is a message, a command, or a notification. Assuming it’s a message, it looks in the message map for the class, using the member variables and functions set up by DECLARE_MESSAGE_MAP, BEGIN_MESSAGE_MAP, and END_MESSAGE_MAP. Part of what those macros arrange is to enable access to the message map entries of the base class by the functions that search the message map of the derived class. That means that if a class inherits from CView and doesn’t catch a message normally caught by CView, that message will still be caught by the same CView function as inherited by the derived class. This message map inheritance parallels the C++ inheritance but is independent of it and saves a lot of trouble carrying virtual functions around.

    The bottom line: You add a message map entry, and when a message arrives, the functions called by the hidden message loop look in these tables to decide which of your objects, and which member function of the object, should handle the message. That’s what’s really going on behind the scenes.

    3.3.3 Messages Caught by MFC Code

    The other great advantage of MFC is that the classes already catch most of the common messages and do the right thing, without any coding on your part at all. For example, you don’t need to catch the message that tells you that the user has chosen File, Save As—MFC classes catch it, put up the dialog box to obtain the new filename, handle all the behind-the-scenes work, and finally call one of your functions, which must be named Serialize(), to actually write out the document.You need only to add message map entries for behavior that is not common to all applications.

     

    Next>>
     
    © Dewsoft Overseas