Teach Yourself Visual C++® 5 in 24 Hours

Previous chapterNext chapterContents


- Hour 4 -
Dialog Boxes and C++ Classes

In this hour, you will learn about two fundamental concepts used when creating Windows programs using C++: object-oriented design and dialog boxes. The following topics are covered in this hour:

Also during this hour, you will create two sample projects that demonstrate how you can use dialog boxes in your applications.

What Is Object-Oriented Design?

One of the design goals for the C++ language was to provide a language that supported object-oriented programming and design. Object-oriented design involves classifying real-world objects and actions as classes that can be created, manipulated, and destroyed.

The data that makes up an object, and the functions that are performed on that object, are combined to form a class, or a description of that object. Classes can inherit functionality from other objects, and you easily can add new classes that leverage existing classes.


Just a Minute: Object-oriented programming is not new; the first language to support object-oriented programming, Simula, has been around since the mid-1960s.

Why Use Object-Oriented Design?

In traditional, structured design, the data manipulated by a program and the functions that manipulate the data are separate. Reusing parts of a design built with structured design techniques often is difficult unless the new design is very similar to the old design.

Object-oriented design is useful because it can be used to create designs that can be reused and extended. A design, or a portion of a design, can be reused in future programs much like a hardware component, such as a computer chip, a disk drive, or a sound card. Object-oriented designs describe the object's class completely, so each class is easily reused because the data and functions described by the class are integrated.

Because you can hide the implementation of a class behind an interface, changing the implementation details of a class without affecting users of that class--as long as the interface doesn't change--is easy. For example, the Tab control was not available in versions of Windows before Windows 95. The MFC CPropertyPage class was rewritten for MFC 4.0 to take advantage of the new Tab control without impacting users of that class, except that the class is now more efficient.

Describing Objects in a Class

New Term: In C++, objects are described by a class. A class is just a description of the object that can be created and the actions that can be performed on it.

A C++ class has two main parts:

What Is a Dialog Box?

New Term: A dialog box is a specialized window that is used to provide feedback or collect input from the user. Dialog boxes come in all shapes and sizes, ranging from simple message boxes that display single lines of text to large dialog boxes that contain sophisticated controls.

New Term: The most commonly used type of dialog box is a modal dialog box. A modal dialog box prevents the user from performing any other activity with the program until the dialog box is dismissed.

Dialog boxes are also used for one-way communication with a user, such as "splash screens" used to display copyright and startup information as a program is launched. The opening screen displayed by the Visual C++ Developer Studio and Microsoft Word are two examples of dialog boxes used for one-way communication. Dialog boxes are sometimes used to notify the user about the progress of a lengthy operation.


Just a Minute: Dialog boxes provide a convenient way for users to interact with Windows programs. Users expect most interaction with a Windows program to take place through dialog boxes. All dialog boxes have certain things in common; these common characteristics make the user's life easier, because users don't need to learn and relearn how dialog boxes work from program to program.

There are several different types of dialog boxes, and each of them has a specific purpose. This hour covers three main types of dialog boxes:

Understanding Message Boxes

The simplest type of dialog box is the message box, which is used to display information. This type of dialog box is so simple you can call it with just one line of code using the MFC class library. For example, to display a message box using default parameters supplied by MFC, just use this line:

AfxMessageBox( "Hello World" );

This line of code creates a message box with an exclamation mark inside a yellow triangle. There are several additional options for the icon displayed in a message box, as you will see later.

Using Dialog Boxes for Input

When most people think of dialog boxes, they think of the dialog boxes that collect input from a user. Dialog boxes are often used to contain controls that are used to handle user input. You can include in a dialog box a wide range of controls. In fact, a major portion of this book covers the various types of controls available in Windows.

New Term: Some dialog boxes are needed so often in Windows programs that they have been included as part of the operating system. These dialog boxes, known as common dialog boxes, are available by calling a function and don't require you to create a dialog box resource. There are common dialog boxes for opening and selecting files, choosing fonts and colors, and performing find and replace operations. Many of the common dialog boxes are covered later in the book. For example, in Hour 13, "Fonts," you will use a common dialog box to select a font.

New Term: A dialog box that is modeless enables other activities to be carried out while the dialog box is still open.

An example of a modeless dialog box is the Find and Replace common dialog box used by Developer Studio. When the dialog box is open, you can still make selections from the main menu, and even open other dialog boxes. In contrast, all other Developer Studio dialog boxes are modal. As long as they are open, the user cannot interact with the other parts of Developer Studio.

How Are Dialog Boxes Used?

Developer Studio makes using dialog boxes in a Windows program easy. All the necessary steps are automated, and the tools used to create the dialog box and include it in a project are all integrated.

Adding Message Boxes

As discussed earlier, you can add message boxes to your program using a single line of code. You must supply at least a single parameter: the text that is displayed inside the dialog box. Optionally, you can also specify an icon style and a button arrangement pattern. The types of icons that are available for message boxes are shown in Figure 4.1.

Figure 4.1.
Icons you can include in a message box.

Each of the icons in Figure 4.1 has a specific meaning. When most Windows programs display a message box, they use a standard icon for each message. When programs use the same icons consistently, users find it much easier to understand the meanings of information provided with message boxes. The meaning and style name for each icon is shown in Table 4.1.

Table 4.1. Icons used in Windows message-box dialog boxes.

Icon Displayed Meaning Message Box Style
Exclamation mark Warning MB_ICONEXCLAMATION
An "i" in a circle Information MB_ICONINFORMATION
Question mark Question MB_ICONQUESTION
Stop sign Error MB_ICONSTOP

In addition, you can specify a button arrangement to be used in the message box. By default, a single button labeled OK is included in the message box. However, sometimes it's convenient to ask a user a simple question and collect an answer. One use for these button arrangements is to ask the user what action to take during an error. For example, the following code displays a message box that contains a question mark icon and asks the user whether the current file should be deleted:

int nChoice = AfxMessageBox( "Overwrite existing file?",
                             MB_YESNOCANCEL | MB_ICONQUESTION );
if( nChoice == IDYES )
{
    // Overwrite file
}

The user can choose between buttons marked Yes, No, and Cancel. Table 4.2 gives the different button arrangements possible for a message box.

Table 4.2. Button arrangements.

Message Box Style Buttons Included in Dialog Box
MB_ABORTRETRYIGNORE Abort, Retry, and Ignore
MB_OK OK
MB_OKCANCEL OK and Cancel
MB_RETRYCANCEL Retry and Cancel
MB_YESNO Yes and No
MB_YESNOCANCEL Yes, No, and Cancel

The message-box return value indicates the button selected by the user. Table 4.3 is a list of possible return values and the choice made by the user.

Table 4.3. Message-box return values.

Return Value Button Pressed
IDABORT Abort
IDCANCEL Cancel
IDIGNORE Ignore
IDNO No
IDOK OK
IDRETRY Retry
IDYES Yes

Using the Bitwise OR Operator

In an earlier code fragment, a vertical bar was used to separate two different options for the AfxMessageBox function. The vertical bar is the bitwise OR operator, which is used to combine the bit patterns of two or more values.

Unlike adding two operands, the values are combined "bitwise," meaning that the two values are compared bit by bit. If a particular bit is high in either operand, the result will have that bit enabled. If a particular bit is low in both operands, the result will be zero. For example, this expression is equal to 7:

4 | 3

However, the result of the following is also equal to 7:

4 | 7

Each possible parameter has a unique bit pattern, enabling you to use the bitwise OR operator when you combine parameter values in AfxMessageBox or other MFC function calls.

When using the bitwise OR operator with AfxMessageBox, you can combine one icon style and one button style. You can't combine two icon styles or two button styles. If no styles are provided, the message box will contain the exclamation-mark icon and an OK button.

Adding a Dialog Box

Adding a dialog box to a program usually takes four steps:

1. Design and create a dialog box resource using the Developer Studio resource tools.

2. Use ClassWizard to create a C++ class derived from CDialog that will manage the dialog box.

3. Add functions to handle messages sent to the dialog box, if needed.

4. If the dialog box is selected from the main menu, the menu resource must be modified and message-handling functions must be created using ClassWizard.

Each of these steps is covered in the following sections.

Understanding Resources

Dialog boxes are just specialized types of windows. However, because they commonly are used for short periods of time they usually are stored as program resources and loaded only when needed. You can see this behavior when running a Windows program on a machine that has little free memory. Every time a dialog box is opened, the hard disk is accessed to load the dialog box resources from the EXE.

Menus and accelerators, which are covered in Hour 10, "Menus," are two types of resources. Here are some of the other resource types used by Windows programs:

In this hour you will learn how to create and use dialog box resources. Later hours deal with the other resource types.

Creating a Dialog Box Resource Using Developer Studio

Developer Studio enables you to create a dialog box and configure it visually. You can add and size controls by using a mouse. You can set attributes for the dialog box and its controls with a click of a mouse button.

Before using the following steps, create a Single Document MFC AppWizard application named HelloSDI, following the steps presented in the first hour. Create a new dialog box resource for the HelloSDI project using either of the following methods:

With either of these methods the dialog box editor is displayed, as shown in Figure 4.2.

Figure 4.2.
The Developer Studio dialog box editor.

The dialog box that is displayed for editing initially contains two button controls, one labeled OK and another labeled Cancel. As you will learn in Hour 5, "Button Controls," these are two standard dialog box controls. The MFC class library usually handles the operation of these controls.

Customizing the Dialog Box's Properties

Every dialog box has properties that you can display by right-clicking and selecting Properties from the pop-up menu. Here are the dialog box properties under the tab labeled General:


Time Saver: There is also a pushbutton labeled Font... that you can use to change the default font for the dialog box. However, just because you can doesn't mean that you should. Windows enables users to set the font style used in dialog boxes; many users, such as the visually impaired, might need specific fonts to be able to use your dialog box.

Like all windows, a dialog box has several style attributes. You can display these attributes by selecting the tab labeled Styles. Here are the default values for the following attributes:

The tab labeled More Styles contains additional properties for the dialog box:

Advanced styles are located under the tab labeled Extended Styles. These styles are rarely used and aren't discussed in this book.

Adding a Static Text Control

A simple control that you can add to the dialog box is a static text control. The static text control requires no interaction with the dialog box; it is often used as a plain text label for other controls contained by the dialog box. To add a static text control, follow these steps:

1. Select the Static Text control icon on the control toolbar. The cursor changes shape to a plus sign when moved over the dialog box.

2. Center the cursor over the dialog box, and click the left mouse button. A static text control is created and contains the label Static.

3. Change the label of the static text control by right-clicking the control and selecting Properties from the shortcut menu; change the caption to "Hello World".

The static text control is visible whenever the dialog box is displayed. Text controls are an excellent choice for labeling controls or messages that are not likely to change. Experiment with changing the size and position of the static text control by dragging its edges with the mouse.

Creating a Class for the Dialog Box

You can use the CDialog class to manage most of the interaction with a dialog box in your program. The CDialog class provides member functions that make a dialog box easy to use. You should use ClassWizard to derive a class from CDialog that is specifically tailored for your dialog box.

To start ClassWizard, use any of these methods:

If ClassWizard knows that a new resource has been added, such as IDD_HELLO, a dialog box asks you to choose between two options for the new dialog box resource:

You should almost always choose to create a new dialog box class unless you are reusing some existing code. A New Class dialog box is displayed, as shown in Figure 4.3.

Values provided to the New Class dialog box are used by ClassWizard to create a class that will manage the new dialog box resource. Use the values from Table 4.4 to fill in the values for the IDD_HELLO dialog box.

Table 4.4. Sample values for the New Class dialog box.

Control Value
Name CHelloDlg
File Name HelloDlg.cpp
Base Class CDialog
Dialog ID IDD_HELLO
OLE Automation None

Figure 4.3.
The New Class dialog box.

Click the button labeled OK. The CHelloDlg class is generated, and two files will be added to your project:

Adding a Message Handler for WM_INITDIALOG

Dialog boxes receive the WM_INITDIALOG message from the operating system when all the controls owned by the dialog box have been created. Most dialog boxes use the WM_INITDIALOG message to perform any initialization that is needed.

After you have added the CHelloDlg class to the HelloSDI project, you can use ClassWizard to add a message-handling function for messages such as WM_INITDIALOG.

To add a message handler for WM_INITDIALOG, follow these steps:

1. Open ClassWizard by pressing Ctrl+W or by right-clicking in a source code window and selecting ClassWizard from the menu.

2. Select the tab labeled Message Maps and select from the Class Name combo box the class that will handle the message--in this case, CHelloDlg.

3. Select the object that is generating the message from the Object ID list box--in this case, CHelloDlg. A list of messages sent to the dialog box will be displayed in the Messages list box.

4. Select the WM_INITDIALOG message from the Messages list box and click the Add Function button. ClassWizard will automatically add the OnInitDialog function to the CHelloDlg class.

5. Click OK to close ClassWizard.

The CHelloDlg::OnInitDialog function doesn't really need to initialize any variables, so you can display a message box instead. Edit OnInitDialog so that it looks like the function in Listing 4.1.

TYPE: Listing 4.1. The CHelloDlg::OnInitDialog function.

BOOL CHelloDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    AfxMessageBox( "WM_INITDIALOG received" );
    return TRUE;
}

Adding a Menu Choice for the New Dialog Box

To add a menu item to the menu used by HelloSDI follow the steps in this section. Don't worry too much about what's going on here; you'll learn more about menus in Hour 10.

Menus are stored in your project as resources. To display the current menu resources, select the ResourceView tab in the project workspace window. Expand the resource tree to show the different resource types defined for the current project; one of the folders is labeled Menu.

Open the Menu folder to display the single menu named IDR_MAINFRAME. Open the menu resource by double-clicking the menu resource icon. The menu is displayed in the resource editor ready for editing. Clicking any top-level menu item displays the pop-up menu associated with that item, as shown in Figure 4.4.

Figure 4.4.
Using the Developer Studio resource editor to edit a menu resource.

The last item of every menu is an empty box. This box is used to add new menu items to the menu resource. All menu items are initially added to the end of a menu resource and then moved to their proper position. To add a new menu item, follow these steps:

1. Double-click the empty box on the File menu to display the Menu Properties dialog box.

2. To add a menu item, provide a menu ID and caption for the new menu item. For this example, enter ID_FILE_HELLO as the menu ID and &Hello as the menu caption.

3. Click anywhere outside the properties dialog box to return to the editor.

After adding a menu item, the next step is to add a message-handling function to handle the new menu item. To add a message-handling function for the ID_FILE_HELLO menu item, follow these steps:

1. Open ClassWizard by pressing Ctrl+W or by right-clicking in a source code window and selecting ClassWizard from the menu.

2. Select the tab labeled Message Maps and select from the Class Name combo box the class that will handle the message--in this case, CMainFrame.

3. Select the object that is generating the message from the Object ID list box--in this case, ID_FILE_HELLO. Two message-handling functions are displayed in the Messages list box.

4. Select the COMMAND message from the Messages list box and click the Add Function button. Accept the default name suggested by ClassWizard for the function name: OnFileHello.

5. Click OK to close ClassWizard.

Edit the CMainFrame::OnFileHello function so that it looks like the function provided in Listing 4.2.

TYPE: Listing 4.2. The message-handling function for the Hello menu item.

void CMainFrame::OnFileHello()
{
    CHelloDlg   dlgHello;

    if( dlgHello.DoModal() == IDOK )
        AfxMessageBox( "OK button pressed" );
    else // IDCANCEL
        AfxMessageBox( "Cancel button pressed" );
}

Add an #include statement in MainFrm.cpp that includes the class definition for CHelloDlg, found in HelloDlg.h, by adding the following line just above the include statement for MainFrm.h:

#include "HelloDlg.h"

Compile and run the HelloSDI project. When the DoModal member function is called, the IDD_HELLO dialog box is displayed. The function call does not return until you close the dialog box by pressing one of the dialog box's buttons. If you press OK, the return value is IDOK. If you press Cancel, the return value is IDCANCEL.

Creating Dialog Box-Based Projects

New Term: A dialog box-based project uses a dialog box as the main window of a simple program. For example, many of the utilities found in the Windows 95 Control Panel are dialog box-based.

A dialog box-based program has a menu that is accessed through the system menu at the upper-left corner of the dialog box's caption bar. A dialog box-based project is often used to build very small programs that interact with the user through a single dialog box. The program can be much smaller and easier to program because the number of classes created by AppWizard is reduced by about half.


Time Saver: If your program must have sophisticated menus, it should not be dialog box based.

A user can easily operate a dialog box-based program. There is only one dialog box window, no menu, and all the available controls usually are initially visible. There are no hidden dialog boxes or menu items, and the user can usually see exactly which operations should be carried out.

AppWizard Support for Dialog Box-Based Projects

You can create a dialog box-based program using AppWizard, just like the SDI program you built earlier in this hour. Building a dialog box-based project is one of the initial options offered by AppWizard.

Because a dialog box-based project is much simpler than an SDI or MDI project, fewer steps are required when using AppWizard. Only four wizard pages are presented by AppWizard when building a dialog box-based project, versus the six pages required for an SDI or MDI project.

To create a dialog box-based project using AppWizard, follow these steps:

1. Open MFC AppWizard by creating a new project workspace, as you have in previous hours. For the purpose of building an example for this hour, use the name HelloDialog.

2. When the opening screen for AppWizard appears, select a dialog box-based project as the project type.

3. Accept the default project settings suggested by AppWizard and press the Finish button. You can also browse through the Wizard pages and change the default settings. AppWizard creates the dialog box-based project for you, just as it did earlier in the hour for the HelloSDI project.

Exploring the HelloDialog AppWizard Project

After you create the HelloDialog project, take some time to explore the project workspace. Much of the project workspace looks just as it does for an SDI project. There are four tabs for the different project workspace views, and several files and resources have been created for you.

There are several differences between a dialog-based project and an SDI or MDI project:

Using the Dialog Box Editor

Open the dialog box editor by double-clicking the IDD_HELLODIALOG_DIALOG icon. The IDD_HELLODIALOG_DIALOG dialog box is displayed in the dialog box editor, along with a dockable control toolbar or palette. The dialog box will already contain a static text control. Modify the static text control so that it reads Hello Dialog Project, as shown in Figure 4.5.

Figure 4.5.
The main dialog box for the HelloDialog project.

Build and run the HelloDialog project. Because it is much smaller, the HelloDialog project will compile and launch faster than an SDI or MDI project. For that reason many of the examples in this book that deal with controls will use dialog box-based projects.

Summary

This hour began with an introduction to object-oriented design. In this hour, you also learned about dialog boxes and how they are used in programs written for Windows. This hour also covered the support provided by Developer Studio, including ClassWizard, the MFC class library, and the dialog box editor.

Q&A

Q When I display a modal dialog box, no other part of the user interface can be used; does my application also stop functioning while the dialog box is displayed?

A A modal dialog box prevents the user from accessing other parts of your application; it does not prevent Windows from sending events to your message-handling procedures. Your application will continue to work normally while displaying a modal dialog box.

Q Why are C++ classes always split into two files? Wouldn't it be easier to have only a single file that defines the class as is done with Java?

A A key part of most languages that support object-oriented programming is the idea that the description of a class should be kept separate from its implementation. This fits in with the notion of information hiding, where unnecessary details are hidden whenever possible. In a well-designed C++ class, the implementation is considered a detail that the consumer doesn't need to be concerned with.

In Java, the class is always defined inside the class declaration, and they are never separated. This simplifies the work required for the compiler and runtime system. However, it also forces you to deal with implementation details when reading the class declaration.

If you prefer to define a class inside the class declaration, C++ supports that coding style; just include the function body after its declaration:
class CFoo
{
    int m_nBar;
public:
    CFoo(){
        m_nBar = 0;
    }
    void SetBar(int newVal){
        m_nBar = newVal;
    }
    int GetBar() const{
        return m_nBar;
    }
};

Workshop

The Workshop is designed to help you anticipate possible questions, review what you've learned, and begin thinking ahead to putting your knowledge into practice. The answers to the quiz are in Appendix B, "Quiz Answers."

Quiz

1. What is the difference between a modal and modeless dialog box?

2. What message is sent to a dialog box for initialization purposes?

3. What is the file extension used for C++ class declaration files?

4. What is the file extension used for C++ class implementation files?

5. What message box style is provided by default when using AfxMessageBox?

6. What message box style should be used when reporting an error to a user?

7. What MFC class is used to manage dialog boxes?

8. What member function is called to pop up a modal dialog box?

9. If the user presses the Yes button in a message box, what return value is provided to AfxMessageBox?

10. If the user presses the No button in a message box, what return value is provided to AfxMessageBox?

Exercises

1. Change the HelloSDI example so that the message box displayed for WM_INITIDIALOG uses the information icon.

2. Add a second static text label to the HelloDialog project's main dialog box that displays your name.


Previous chapterNext chapterContents


Macmillan Computer Publishing USA

© Copyright, Macmillan Computer Publishing. All rights reserved.