Discussion: Dialog Boxes

Windows dialog boxes are used to interact with the user. They convey messages to the user and take user input through various kinds of controls. The Microsoft Foundation Class Library provides two dialog classes that you can use directly or derive your own dialog classes from. This section discusses the dialog classes used in the Phone Book program.

This discussion does not instruct you to add any code to your files.

Modal vs. Modeless Dialog Boxes

Class CModalDialog provides “modal” dialog boxes. These are dialog boxes that the user must respond to before he or she can continue work in the underlying application. They put the user in a “mode” that must be dealt with until the dialog box is dismissed, typically with OK or Cancel. It's not a good practice in general to put the user into a limiting mode, but modal dialog boxes are useful in situations that require the user to provide input before the program can continue.

Class CDialog provides “modeless” dialogs. When a modeless dialog box is on the screen, the user can treat it like any other application window. The user can continue working in the program, do something in the modeless dialog box, and return to the program without dismissing the dialog box. For many tasks, modeless dialog boxes are preferable to modal dialogs because they don't limit the user's freedom of action.

For more information about class CDialog, see Chapter 15 in this manual and the class description in the Class Libraries Reference.

The Dialog Classes

The Phone Book program uses two kinds of dialog boxes: standard Windows dialogs and custom-built dialogs based on the Foundation dialog classes.

Some of the dialog boxes used in the Phone Book program are standard Microsoft Windows dialogs. These are displayed and operated by calling a function from COMMDLG.DLL. The Open command in the File menu uses the GetOpenFileName function. The Save and Save As commands in the File menu use the GetSaveFileName function. The Print command in the File menu uses the PrintDlg function. The use of these functions is explained in “Standard Windows Dialog Boxes” on page 167.

Other dialog boxes used in the Phone Book program are based on class CModalDialog. You saw the About dialog in Hello, which constructs a dialog object directly from CModalDialog. That same dialog code is used for the About dialog box in the Phone Book program. The three Help dialogs in Phone Book also use CModalDialog objects. See the discussion of the OnHelp member function under “Add Message-Handlers for Help Menu Commands” on page 222 in Chapter 6.

Several other dialog boxes in the Phone Book program are constructed from classes derived from CModalDialog. This is because CModalDialog doesn't provide member functions to work with any controls you might define in your dialog box, except for the OK and Cancel buttons. Class CFindDialog defines a class of dialog box objects designed to get a single string of data from the user. Class CEditDialog defines a class of dialog box objects designed to get three pieces of data from the user. These classes add member functions to retrieve any data the user enters in the dialog boxes.

Class CFindDialog

CFindDialog is derived from CModalDialog to add a constructor, a member variable, and two member functions. Figure 5.2 shows what the CFindDialog dialog box typically looks like on the screen.

The member variable of a CFindDialog dialog object, m_szFindName, stores the data entered in the text box. The CFindDialog object's constructor simply invokes the constructor for its base class, CModalDialog. The constructor looks like this:

CFindDialog( CWnd* pParentWnd = NULL ) :

CModalDialog( "Find", pParentWnd )

{ };

CFindDialog inherits the DoModal member function from class CModalDialog. DoModal processes user interactions with the dialog until the user selects either OK or Cancel, then returns the result, either IDOK or IDCANCEL. You can use the function result to determine which button the user clicked.

If the user clicked the OK button, the CFindDialog dialog object's OnOK message-handler function is called. In the Phone Book program, the CFindDialog object's OnOK function overrides OnOK from class CModalDialog.

The CModalDialog version of OnOK simply ends the dialog box. The overriding CFindDialog extracts the information the user entered in the dialog box and stores it in the dialog object's m_szFindName member variable. It does so by calling the CString member function GetBuffer to allocate a text buffer and then calling the CDialog member function GetDlgItemText to retrieve the text entered by the user. After retrieving the text, OnOK calls the dialog object's EndDialog member function, inherited from CDialog, to terminate the modal dialog.

If the user clicked the Cancel button, the CFindDialog dialog object's OnCancel message-handler function is called. In the Phone Book program, CModalDialog's version of OnCancel provides default behavior that suits Phone Book's needs. OnCancel calls the dialog object's EndDialog member function, passing an argument of FALSE. This causes the dialog object's DoModal member to return FALSE.

After the user dismisses your dialog and the DoModal member function completes, you can use your own member functions to retrieve the values from the controls in the dialog box. For the CFindDialog object, you call the GetFindString member function to retrieve the string that the user entered in the dialog box. GetFindString returns the string as a CString object.

You build the controls in a dialog box by supplying a resource template in your resource script file. But you must also supply functions in your derived dialog class, such as GetFindString, to read the results of those controls. For more about the dialog resource template, see “The Dialog Resources” on page 166.

Class CEditDialog

Like CFindDialog, CEditDialog is derived from CModalDialog. The derived class adds member functions to handle dialog controls. These are built into the dialog box via a resource template. Figure 5.3 shows what the CEditDialog dialog box looks like on the screen.

CEditDialog has one member variable, m_pData, to store a pointer to a CPerson object. When you construct a CEditDialog object, you pass a pointer to a CPerson as one of the arguments to the constructor, which installs the CPerson in the dialog object's m_pData member. If the CPerson object passed in has data in its member variables, these are extracted by the CEditDialog object's OnInitDialog member function and displayed in the four text fields of the dialog box. If the CPerson object is empty, nothing is displayed. You pass a filled CPerson object when the dialog box is to be used for editing and an empty CPerson object when the dialog box is to be used for data entry.

When the dialog is dismissed, the user has either edited the data and clicked OK or has clicked Cancel. If OK, you can call the CEditDialog dialog object's GetData member to retrieve the person object and store it in your database.

How Dialog Objects Work

Modal dialog objects, like those in the Phone Book program, are derived from class CWnd through class CDialog. Some of the functionality of a CModalDialog object is inherited from these classes. But CModalDialog objects, and objects of classes derived from CModalDialog, operate differently from ordinary windows or “modeless” dialog boxes (constructed from class CDialog). For a distinction between modal and modeless dialog boxes, see “Modal vs. Modeless Dialog Boxes” on page 182.

A modal dialog operates when your code calls the dialog object's DoModal member function. DoModal remains in control until the user dismisses the dialog box by clicking OK, Cancel, or some similar button. The user cannot perform any operations outside the dialog box.

Because a dialog box is a window by inheritance, most Windows messages for the dialog box go through the standard window procedure provided by the Microsoft Foundation Classes for all windows. However, a few special messages, such as WM_SETFONT and WM_INITDIALOG, instead go through a standard dialog procedure. If a dialog object's dialog procedure receives a WM_INITDIALOG message, it calls the dialog object's OnInitDialog member function. CModalDialog objects inherit this function from class CDialog, but classes derived from CModalDialog can override it to provide special processing at the time of dialog initialization.

In the Phone Book program, one of the derived CModalDialog classes, CEditDialog, overrides CDialog's version of OnInitDialog to perform setup chores. Class CEditDialog uses its version of OnInitDialog to set the initial text that the user sees in the editable text fields of the dialog box and to set the initial selection in the dialog box to the last name field.

The Dialog Resources

When you construct a dialog object, you pass the name of a dialog resource template as an argument. Recall that when you construct an object of a derived class in C++, you append to your constructor call a call to the constructor for your base class. For example, in class CEditDialog, the constructor looks like this:

CEditDialog( CPerson* person, CWnd* pParentWnd = NULL ) :

CModalDialog( "EditPerson", pParentWnd )

{ m_pData = person; }

In the second line of this code, “EditPerson” is the dialog template name. Windows uses this name as its connection with the dialog template in the resource file, which it uses to display the dialog on the screen and to operate the dialog from the dialog object's DoModal member function.

The dialog resource template tells Windows what controls to put in the dialog box, where to put them, what to label them, what styles they have, and what their ID numbers are. This is where, for example, the OK button is defined as a “default push button” placed at coordinates 5, 32 in the dialog window with a height of 32 and a width of 14 units, with the WS_GROUP style and the ID number IDOK. Some ID numbers, such as IDOK, are declared in WINDOWS.H, while others, such as the ID for the editable text field for a person's last name, IDC_LASTNAME, are declared in your own RESOURCE.H file.

For more information about writing and using dialog resource templates, see the Windows SDK documentation.

Message Maps for Dialog Classes

If you look at the hierarchy diagram for the Microsoft Foundation Class Library provided with the Class Libraries Reference, you see that CModalDialog and its base class, CDialog, are derived from class CWnd. Thus dialog classes are specialized window classes, and they inherit the member variables and functions of class CWnd.

Because dialog classes, including the ones you derive, are window classes, they require message maps to connect Windows messages with the message-handler functions designed to process them. Classes CDialog and CModalDialog, like all window classes, have their own message maps.

If you provide special message-handler member functions in your derived dialog classes, you must also provide message maps with entries for these handlers.

However, classes CFindDialog and CEditDialog do not require you to write message maps. This is because you add no message-handler functions to the classes. Each of these classes does override some message-handler functions declared in CModalDialogOnOK in both classes and OnInitDialog as well in CEditDialog. These are overridden because you need to provide some special processing for these messages. The classes don't override CModalDialog's OnCancel member function because the default behavior is sufficient.

Because the classes add no new handlers, they need no new message map entries. Therefore, the message map supplied with CModalDialog does the job for them. To save data space in your program, don't supply the message map if you don't have any message handlers.

Standard Windows Dialog Boxes

Phone Book also uses some of the standard Windows dialog boxes. These are the familiar Windows dialog boxes for getting a filename to open or save to and the standard print dialog:

Standard Open dialog box

This dialog box lets the user switch directories and select files to open.

In Phone Book, the OnOpen member function of the main window class invokes this dialog box. See the discussion of OnOpen under “Discussion: File Menu Message-Handlers” on page 213 in Chapter 6.

Standard Save dialog box

This dialog box lets the user switch directories and save a file.

In Phone Book, the OnSave and OnSaveAs member functions of the main window class invoke this dialog box. See the discussion of OnSave and OnSaveAs under “Discussion: File Menu Message-Handlers” on page 213 in Chapter 6.

Standard Print dialog box

This dialog lets the user select printing options and print a file.

In Phone Book, the OnPrint member function of the main window class invokes this dialog box. See the discussion of OnPrint under “Discussion: File Menu Message-Handlers” on page 213 in Chapter 6.

Note:

You must include the file COMMDLG.H with an #include directive in your VIEW.CPP file. Because you're including a standard C file in a C++ program, place the #include directive in an “extern C” block. The file COMMDLG.DLL must also be in your PATH when you run the program. COMDLG.DLL is a Windows dynamic link library supplied with the Windows 3.1 SDK and with your Microsoft C/C++, Version 7.0 package. The declaration looks like this:

extern "C"

{

#include <commdlg.h>

}