| Tenouk C & C++ | MFC Home | MFC Intro 2 | MFC AppWizard 2 | Download | Site Index |


 

 

 

Module 2:

Getting Started with Visual C++ 6.0 AppWizard 1

 

 

 

Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below:

 

  1. The Windows Programming Model

  2. Window Procedure

  3. Messages

  4. Common Windows Messages

  5. Windows Messages

  6. Command Messages

  7. Ranges of Messages

  8. Message Categories Details

  9. Windows Messages and Control-Notification Messages

  10. Message Handling and Mapping

  11. Documents and Views Story

  12. Using Documents

  13. Using Views

  14. SDI and MDI

  15. More on View

  16. Using the AppWizard of the Visual C++ 6.0

 

The Windows Programming Model

 

Windows programs use the event-driven programming model illustrated in Figure 1, in which applications respond to events by processing messages sent by the operating system. An event could be a keystroke, a mouse click, or a command for a window to repaint itself, among other things. The entry point for a Windows program is a function named WinMain(), but most of the action takes place in a function known as the window procedure. The window procedure processes messages sent to the window. WinMain() creates that window and then enters a message loop, alternately retrieving messages and dispatching them to the window procedure. Messages wait in a message queue until they are retrieved. A typical Windows application performs the bulk of its processing in response to the messages it receives, and in between messages, it does little except wait for the next message to arrive.

The message loop ends when a WM_QUIT message is retrieved from the message queue, signaling that it's time for the application to end. This message usually appears because the user selected Exit from the File menu, clicked the close button (the small button with an X in the window's upper right corner), or selected Close from the window's system menu. When the message loop ends, WinMain() returns and the application terminates.

 

A simple Windows programming model

Figure 1: A simple Windows programming model.

 

Window Procedure

 

A window procedure is a function that receives and processes all messages sent to the window. Every window class has a window procedure, and every window created with that class uses that same window procedure to respond to messages.

The system sends a message to a window procedure by passing the message data as arguments to the procedure. The window procedure then performs an appropriate action for the message; it checks the message identifier (ID) and, while processing the message, uses the information specified by the message parameters.

A window procedure does not usually ignore a message. If it does not process a message, it must send the message back to the system for default processing. The window procedure does this by calling the DefWindowProc() function, which performs a default action and returns a message result. The window procedure must then return this value as its own message result. Most window procedures process just a few messages and pass the others on to the system by calling DefWindowProc(). Because a window procedure is shared by all windows belonging to the same class, it can process messages for several different windows. To identify the specific window affected by the message, a window procedure can examine the window handle passed with a message.

The window procedure typically calls other functions to help process the messages it receives. It can call functions local to the application, or it can call API functions provided by Windows. API functions are contained in special modules known as dynamic-link libraries, or DLLs. The Win32 API includes hundreds of functions that an application can call to perform various tasks such as creating a window, drawing a line, and performing file input and output. In C, the window procedure is typically implemented as a monolithic function containing a large switch statement with cases for individual messages. The code provided to process a particular message is known as a message handler.

 

Messages

 

Windows defines hundreds of different message types. Most messages have names that begin with the letters "WM_", as in WM_CREATE and WM_PAINT. These messages can be classified in various ways, but for the moment classification is not nearly as important as realizing the critical role messages play in the operation of an application. The following table shows 10 of the most common messages. A window receives a WM_PAINT message, for example, when its interior needs repainting. One way to characterize a Windows program is to think of it as a collection of message handlers. To a large extent, it is a program's unique way of responding to messages that gives it its personality.

 

Common Windows Messages

 

Message

Sent When

WM_CHAR

A character is input from the keyboard.

WM_COMMAND

The user selects an item from a menu, or a control sends a notification to its parent.

WM_CREATE

A window is created.

WM_DESTROY

A window is destroyed.

WM_LBUTTONDOWN

The left mouse button is pressed.

WM_LBUTTONUP

The left mouse button is released.

WM_MOUSEMOVE

The mouse pointer is moved.

WM_PAINT

A window needs repainting.

WM_QUIT

The application is about to terminate.

WM_SIZE

A window is resized.

 

Table 1: Windows messages example.

 

A message manifests itself in the form of a call to a window's window procedure. Bundled with the call are four input parameters:

  1. The handle of the window to which the message is directed,

  2. A message ID, and

  3. Two 32-bit parameters known as wParam and lParam.

 

The window handle is a 32-bit value that uniquely identifies a window. Internally, the value references a data structure in which Windows stores relevant information about the window such as its size, style, and location on the screen. The message ID is a numeric value that identifies the message type: WM_CREATE, WM_PAINT, and so on. wParam and lParam contain information specific to the message type. When a WM_LBUTTONDOWN message arrives, for example, wParam holds a series of bit flags identifying the state of the Ctrl and Shift keys and of the mouse buttons. lParam holds two 16-bit values identifying the location of the mouse pointer when the click occurred. Together, these parameters provide the window procedure with all the information it needs to process the WM_LBUTTONDOWN message.

A large portion of programming for the Windows environment involves message handling. Each time an event such as a keystroke or mouse click occurs, a message is sent to the application, which must then handle the event. The Microsoft Foundation Class Library offers a programming model optimized for message-based programming. In this model, "message maps" are used to designate which functions will handle various messages for a particular class. Message maps contain one or more macros that specify which messages will be handled by which functions. For example, a message map containing an ON_COMMAND macro might look something like this:

 

BEGIN_MESSAGE_MAP(CMyDoc, CDocument)

    ON_COMMAND(ID_MYCMD, OnMyCommand)

    // ... More entries to handle additional commands

END_MESSAGE_MAP( )

 

The ON_COMMAND macro is used to handle command messages generated by menus, buttons, and accelerator keys. Macros are available to map the following:

 

Windows Messages

Command Messages

Ranges of Messages

Although message-map macros are important, you generally won't have to use them directly. This is because the ClassWizard window automatically creates message-map entries in your source files when you use it to associate message-handling functions with messages. Any time you want to edit or add a message-map entry, you can use the ClassWizard. The ClassWizard does not support message-map ranges. You must write these message-map entries yourself.

 

Message Categories Details

 

There are three main categories of messages that you will write in Windows programming later:

 

  1. Windows messages

This includes primarily those messages beginning with the WM_ prefix, except for WM_COMMAND. Windows messages are handled by windows and views. These messages often have parameters that are used in determining how to handle the message.

 

  1. Control notifications

This includes WM_COMMAND notification messages from controls (buttons, list boxes, scroll bars etc.) and other child windows to their parent windows. For example, an edit control sends its parent a WM_COMMAND message containing the EN_CHANGE control-notification code when the user has taken an action that may have altered text in the edit control. The window's handler for the message responds to the notification message in some appropriate way, such as retrieving the text in the control. The framework routes control-notification messages like other WM_ messages. One exception, however, is the BN_CLICKED control-notification message sent by buttons when the user clicks them. This message is treated specially as a command message and routed like other commands.

 

  1. Command messages

This includes WM_COMMAND notification messages from user-interface objects: menus, toolbar buttons, and accelerator keys. The framework processes commands differently from other messages, and they can be handled by more kinds of objects.

 

Windows Messages and Control-Notification Messages

 

Messages in categories 1 and 2

Windows messages and control notifications are handled by windows: objects of classes derived from class CWnd. This includes CFrameWnd, CMDIFrameWnd, CMDIChildWnd, CView, CDialog, and your own classes derived from these base classes. Such objects encapsulate an HWND, a handle to a Windows window.

 

Messages in category 3 – commands

Can be handled by a wider variety of objects: documents, document templates, and the application object itself in addition to windows and views. When a command directly affects some particular object, it makes sense to have that object handle the command. For example, the Open command on the File menu is logically associated with the application: the application opens a specified document upon receiving the command. So the handler for the Open command is a member function of the application class.

 

Message Handling and Mapping

 

In traditional programs for Windows, Windows messages are handled in a large switch statement in a window procedure. MFC instead uses message maps to map direct messages to distinct class member functions. Message maps are more efficient than virtual functions for this purpose, and they allow messages to be handled by the most appropriate C++ object such as application, document, view, and so on. You can map a single message or a range of messages, command IDs, or control IDs.

WM_COMMAND messages - usually generated by menus, toolbar buttons, or accelerators, also use the message-map mechanism. MFC defines a standard routing of command messages among the application, frame window, view, and Active documents in your program. You can override this routing if you need to. Message maps also supply a way to update user-interface objects (such as menus and toolbar buttons), enabling or disabling them to suit the current context.

 

Documents and Views Story

 

Most of your MFC library applications will be more complex than the previous examples. Typically, they'll contain application and frame classes plus two other classes that represent the "document" and the "view." This document-view architecture is the core of the application framework and is loosely based on the Model/View/Controller classes from the Smalltalk world.

In simple terms, the document-view architecture separates data from the user's view of the data. One obvious benefit is multiple views of the same data. Consider a document that consists of a month's worth of stock quotes stored on disk. Suppose a table view and a chart view of the data are both available. The user updates values through the table view window, and the chart view window changes because both windows display the same information but in different views.

In an MFC library application, documents and views are represented by instances of C++ classes. Figure 2 shows three objects of class CStockDoc corresponding to three companies: AT&T, IBM, and GM. All three documents have a table view attached, and one document also has a chart view. As you can see, there are four view objects: three objects of class CStockTableView and one of class CStockChartView.

 

 

 

 

 

----------------------------------------------------------------------------------------------------------------------------------------------------

The document-view relationship

 

Figure 2: The document-view relationship.

 

 

Then, the document base class code interacts with the File Open and File Save menu items; the derived document class does the actual reading and writing of the document object's data.

 

The document’s File Open and application framework

 

Figure 3: The document’s File Open and application framework.

 

The application framework does most of the work of displaying the File Open and File Save dialog boxes and opening, closing, reading, and writing files. The view base class represents a window contained inside a frame window; the derived view class interacts with its associated document class and does the application's display and printer I/O. The derived view class and its base classes handle Windows messages. The MFC library orchestrates all interactions among documents, views, frame windows, and the application object, mostly through virtual functions. Don't think that a document object must be associated with a disk file that is read entirely into memory. If a "document" were really a database, for example, you could override selected document class member functions and the File Open menu item would bring up a list of databases instead of a list of files. At the heart of document/view are four key classes:

  1. The CDocument (or COleDocument) class supports objects used to store or control your program's data and provides the basic functionality for programmer-defined document classes. A document represents the unit of data that the user typically opens with the Open command on the File menu and saves with the Save command on the File menu.

  2. The CView (or one of its many derived classes) provides the basic functionality for programmer-defined view classes. A view is attached to a document and acts as an intermediary between the document and the user: the view renders an image of the document on the screen and interprets user input as operations upon the document. The view also renders the image for both printing and print preview.

  3. CFrameWnd (or one of its variations) supports objects that provide the frame around one or more views of a document.

  4. CDocTemplate (or CSingleDocTemplate or CMultiDocTemplate) supports an object that coordinates one or more existing documents of a given type and manages creating the correct document, view, and frame window objects for that type.

 

The following is another figure that shows the relationship between a document and its view.

 

The document-view relationship

 

Figure 4: The document-view relationship.

 

The document/view implementation in the class library separates the data itself from its display and from user operations on the data. All changes to the data are managed through the document class. The view calls this interface to access and update the data. Documents, their associated views, and the frame windows that frame the views are created by a document template. The document template is responsible for creating and managing all documents of one document type.

 

Using Documents

 

Working together, documents and views:

The document is particularly involved in managing data. Store your data, normally, in document class member variables. The view uses these variables to access the data for display and update. The document's default serialization mechanism manages reading and writing the data to and from files. Documents can also handle commands (but not Windows messages other than WM_COMMAND).

 

Using Views

 

The view's responsibilities are to display the document's data graphically to the user and to accept and interpret user input as operations on the document. Your tasks in writing your view class are to:

SDI and MDI

 

MFC supports two types of document/view applications.

 

  1. Single document interface (SDI) applications support just one open document at a time.

  2. Multiple document interface (MDI) applications permit two or more documents to be open concurrently and also support multiple views of a given document.

 

The WordPad applet is an SDI application; Microsoft Word is an MDI application. The framework hides many of the differences between the two user interface models so that writing an MDI application is not much different than writing an SDI application, but today developers are discouraged from using the multiple document interface because the SDI model promotes a more document-centric user interface. If the user is to edit two documents simultaneously, Microsoft would prefer that each document be displayed in a separate instance of your application.

SDI applications allow only one open document frame window at a time. MDI applications allow multiple document frame windows to be open in the same instance of an application. An MDI application has a window within which multiple MDI child windows, which are frame windows themselves, can be opened, each containing a separate document. In some applications, the child windows can be of different types, such as chart windows and spreadsheet windows. In that case, the menu bar can change as MDI child windows of different types are activated. Under Windows 95 and later, applications are commonly SDI because the operating system has adopted a "document-centered" view.

 

More on View

 

At this stage, we will concentrate on Views. From a user's standpoint, a view is an ordinary window that the user can size, move, and close in the same way as any other Windows-based application window. From the programmer's perspective, a view is a C++ object of a class derived from the MFC library CView class. Like any C++ object, the view object's behavior is determined by the member functions (and data members) of the class - both the application-specific functions in the derived class and the standard functions inherited from the base classes.

With Visual C++, you can produce interesting applications for Windows by simply adding code to the derived view class that the AppWizard code generator produces. When your program runs, the MFC library application framework constructs an object of the derived view class and displays a window that is tightly linked to the C++ view object. As is customary in C++ programming, the view class code is divided into two source modules: the header file (.h) and the implementation file (.cpp).

 

Using the AppWizard of the Visual C++ 6.0

 

The AppWizard tool generates the code for a functioning MFC library application. This working application simply brings up an empty window with a menu attached. Later you'll add code that draws inside the window. Follow the steps to build the application:

 

  1. Run the AppWizard to generate SDI application source code. Choose New from Visual C++'s File menu, and then click the Projects tab in the resulting New dialog box, as shown here. Make sure that MFC AppWizard (exe) is highlighted, and then type mymfc as shown in the Project Name edit box, modify the Location of your project as needed and then click the OK button.

 

 

 

 

 

 

----------------------------------------------------------------------------

Visual C++ AppWizard New project dialog

 

Figure 5: Visual C++ AppWizard New project dialog.

 

  1. Now you will step through a sequence of AppWizard screens, the first of which is shown here. Just follow the steps and options selected in the Figures.

 

Visual C++ AppWizard step 1 of 6

 

Figure 6: Visual C++ AppWizard step 1 of 6.

 

Visual C++ AppWizard step 2 of 6

 

Figure 7: Visual C++ AppWizard step 2 of 6.

 

Visual C++ AppWizard step 3 of 6

 

Figure 8: Visual C++ AppWizard step 3 of 6.

 

Visual C++ AppWizard step 4 of 6

 

Figure 9: Visual C++ AppWizard step 4 of 6.

 

Visual C++ AppWizard step 5 of 6

 

Figure 10: Visual C++ AppWizard step 5 of 6.

 

Notice that the class names and source-file names have been generated based on the project name MYMFC. You could make changes to these names at this point if you wanted to. Click the Finish button.

 

 

 

 

 

 

Visual C++ AppWizard step 6 of 6

 

Figure 11: Visual C++ AppWizard step 6 of 6.

 

Just before AppWizard generates your code, it displays the New Project Information dialog box, shown here.

 

Visual C++ AppWizard project summary information

 

Figure 12: Visual C++ AppWizard project summary information.

 

When you click the OK button, AppWizard begins to create your application's subdirectory (mymfc under \mfcproject\mymfc) and a series of files in that subdirectory. When AppWizard is finished, look in the application's subdirectory. Physically, the following files are of interest (for now).

 

mymfc physical project’s files

 

Figure 13: mymfc physical project’s files.

 

Some explanation for those files.

 

File

Description

mymfc.dsp

A project file that allows Visual C++ to build your application.

mymfc.dsw

A workspace file that contains a single entry for mymfc.dsp.

mymfc.rc

An ASCII resource script file.

mymfcView.cpp

A view class implementation file that contains CMymfcView class member functions.

mymfcView.h

A view class header file that contains the CMymfcView class declaration.

mymfc.opt

A binary file that tells Visual C++ which files are open for this project and how the windows are arranged (This file is not created until you save the project.).

mymfcDoc.cpp

A document class implementation file that contains CMymfcDoc class member functions.

mymfcDoc.h

A document class header file that contains the CMymfcDoc class declaration.

ReadMe.txt

A text file that explains the purpose of the generated files.

resource.h

A header file that contains #define constant definitions.

 

Table 2: Important Visual C++ project files.

 

Open the mymfcView.cpp and mymfcView.h files and look at the source code. Together, these files define the CMymfcView class, which is central to the application. An object of class CMymfcView corresponds to the application's view window, where all the "action" takes place.

 

 

 

Continue on next module for part 2...

 

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN What's New (MFC Feature Pack) - feature pack.

  3. Porting & Migrating your older programs.

  4. MSDN Library

  5. DCOM at MSDN.

  6. COM+ at MSDN.

  7. COM at MSDN.

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multi-byte character set: Story and program examples.

 

 


| Tenouk C & C++ | MFC Home | MFC Intro 2 | MFC AppWizard 2 | Download | Site Index |