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.
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.
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.
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:
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:
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.
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.
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.
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.
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.
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.
Return Value | Button Pressed |
IDABORT | Abort |
IDCANCEL | Cancel |
IDIGNORE | Ignore |
IDNO | No |
IDOK | OK |
IDRETRY | Retry |
IDYES | Yes |
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 to a program usually takes four steps:
Each of these steps is covered in the following sections.
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.
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.
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.
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:
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.
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.
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:
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:
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.
BOOL CHelloDlg::OnInitDialog() { CDialog::OnInitDialog(); AfxMessageBox( "WM_INITDIALOG received" ); return TRUE; }
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:
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:
Edit the CMainFrame::OnFileHello function so that it looks like the function provided in Listing 4.2.
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.
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.
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:
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:
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.
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.
class CFoo { int m_nBar; public: CFoo(){ m_nBar = 0; } void SetBar(int newVal){ m_nBar = newVal; } int GetBar() const{ return m_nBar; } };
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."
© Copyright, Macmillan Computer Publishing. All rights reserved.