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:
The Modal Dialog and Windows Common Controls
Almost every Windows-based program uses a dialog window to interact with the user. The dialog might be a simple OK message box, or it might be a complex data entry form. Calling this powerful element a dialog "box" is an injustice. A dialog is truly a window that receives messages, that can be moved and closed, and that can even accept drawing instructions in its client area. The two kinds of dialogs are modal and modeless.
Modal vs Modeless Dialogs
The CDialog base class supports both modal and modeless dialogs. With a modal dialog, such as the Open File dialog, the user cannot work elsewhere in the same application more correctly, in the same user interface thread until the dialog is closed. With a modeless dialog, the user can work in another window in the application while the dialog remains on the screen. Microsoft Word's Find and Replace dialog is a good example of a modeless dialog; you can edit your document while the dialog is open. Your choice of a modal or a modeless dialog depends on the application. Modal dialogs are much easier to program, which might influence your decision.
Resources and Controls
So now you know a dialog is just a window. What makes the dialog different from the CView windows you've seen already? For one thing, a dialog window is almost always tied to a Windows resource that identifies the dialog's elements and specifies their layout. Because you can use the dialog editor that is one of the resource editors to create and edit a dialog resource, you can quickly and efficiently produce dialogs in a visual manner.
A dialog contains a number of elements called controls. Dialog controls include edit controls (aka text boxes), buttons, list boxes, combo boxes, static text (aka labels), tree views, progress indicators, sliders, and so forth. Windows manages these controls using special grouping and tabbing logic and that relieves you of a major programming burden. The dialog controls can be referenced either by a CWnd pointer (because they are really windows) or by an index number (with an associated #define constant) assigned in the resource. A control sends a message to its parent dialog in response to a user action such as typing text or clicking a button.
The MFC Library and ClassWizard work together to enhance the dialog logic that Windows provides. ClassWizard generates a class derived from CDialog and then lets you associate dialog class data members with dialog controls. You can specify editing parameters such as maximum text length and numeric high and low limits. ClassWizard generates statements that call the MFC data exchange and data validation functions to move information back and forth between the screen and the data members.
Programming a Modal Dialog
Modal dialogs are the most frequently used dialogs. A user action (a menu choice, for example) brings up a dialog on the screen, the user enters data in the dialog, and then the user closes the dialog. Here's a summary of the steps to add a modal dialog to an existing project:
Use the dialog editor to create a dialog resource that contains various controls. The dialog editor updates the project's resource script (RC) file to include your new dialog resource, and it updates the project's resource.h file with corresponding #define constants.
Use ClassWizard to create a dialog class that is derived from CDialog and attached to the resource created in step 1. ClassWizard adds the associated code and header file to the Microsoft Visual C++ project.
When ClassWizard generates your derived dialog class, it generates a constructor that invokes a CDialog modal constructor, which takes a resource ID as a parameter. Your generated dialog header file contains a class enumerator constant IDD that is set to the dialog resource ID. In the CPP file, the constructor implementation looks something like this:
CMyDialog::CMyDialog(CWnd* pParent /*=NULL*/) : CDialog(CMyDialog::IDD, pParent)
// initialization code here
The use of enum IDD decouples the CPP file from the resource IDs that are defined in the project's resource.h file.
Use ClassWizard to add data members, exchange functions, and validation functions to the dialog class.
Use ClassWizard to add message handlers for the dialog's buttons and other event-generating controls.
Write the code for special control initialization (in OnInitDialog()) and for the message handlers. Be sure the CDialog virtual member function OnOK() is called when the user closes the dialog unless the user cancels the dialog). The OnOK() is called by default.
Write the code in your view class to activate the dialog. This code consists of a call to your dialog class's constructor followed by a call to the DoModal() dialog class member function. DoModal() returns only when the user exits the dialog window.
Now we'll proceed with a real example, one step at a time.
The MYMFC7 Project Example
Let's not mess around with wimpy little dialogs. We'll build a monster dialog that contains almost every kind of control. The job will be easy because Visual C++'s dialog editor is there to help us. The finished product is shown in the following Figure.
Figure 1: The finished dialog of the MYMFC7 project.
As you can see, the dialog supports a human resources application. These kinds of business programs are fairly boring, so the challenge is to produce something that could not have been done with 80-column punched cards. The program is brightened a little by the use of scroll bar controls for "Loyalty" and "Reliability." Here is a classic example of direct action and visual representation of data! Later on, ActiveX controls could add more interest.
Building the Dialog Resource
Here are the steps for building the dialog resource:
Run AppWizard to generate a project called MYMFC7. Choose New from Visual C++'s File menu, and then click the Projects tab and select MFC AppWizard (exe). Accept all the defaults but two: select Single Document and de-select Printing And Print Preview. The options and the default class names are shown here.
Figure 2: MYMFC7 project summary.
As usual, AppWizard sets the new project as the current project.
Create a new dialog resource with ID IDD_DIALOG1 (the default given ID). Choose Resource from Visual C++'s Insert menu. The Insert Resource dialog appears. Click on Dialog, and then click New. Visual C++ creates a new dialog resource, as shown here.
Figure 3: Creating a new dialog resource through the Insert menu.
Figure 4: Inserting new dialog resource.
Figure 5: Dialog resource editor.
The dialog editor assigns the resource ID IDD_DIALOG1 to the new dialog. Notice that the dialog editor inserts OK and Cancel buttons for the new dialog.
Resize the dialog and assign a MyDialog caption. Enlarge the dialog box to about 5-by-7 inches.
When you right-click on the new dialog and choose Properties from the pop-up menu, the Dialog Properties dialog appears. Type in the caption for the new dialog as shown in the screen below.
Figure 6: Dialog’s properties.
The state of the pushpin button in the upper-left corner determines whether the Dialog Properties dialog stays on top of other windows. When the pushpin is "pushed," the dialog stays on top of other windows.
Figure 7: The pushpin button, making the Dialog Properties staying on top.
Click the Toggle Grid button (on the Dialog toolbar) to reveal the grid and to help align controls.
Figure 8: The dialog grid, helping the controls alignment on the dialog.
Figure 9: Dialog with grid.
You can test your dialog during the design stage by clicking the Test switch in the Dialog toolbar.
Figure 10: The dialog Test switch, testing your dialog during the design process.
Similar buttons and other utilities can also be accessed through the Layout menu.
Figure 11: Accessing dialog’s editing utilities through Layout menu.
Set the dialog style. Click on the Styles tab at the top of the Dialog Properties dialog, and then set the style properties as shown in the following illustration.
Figure 12: Setting the dialog style.
Set additional dialog styles. Click on the More Styles tab at the top of the Dialog Properties dialog, and then set the style properties as shown here.
Figure 13: Setting additional dialog styles.
Add the dialog's controls. Use the control palette to add each control. If the control palette is not visible, right-click any toolbar and choose Controls from the list. Drag controls from the control palette (shown below) to the new dialog and then position and size the controls, as shown in Figure 1. Here are the control palette's controls.
Figure 14: Available controls from Visual C++ control palette.
The dialog editor displays the position and size of each control in the status bar. The position units are special "dialog units," or DLUs, not device units. A horizontal DLU is the average width of the dialog font divided by 4. A vertical DLU is the average height of the font divided by 8. The dialog font is normally 8-point MS Sans Serif.
Here's a brief description of the dialog's controls, use drag and drop for the controls:
The static text control for the Name field. A static text control simply paints characters on the screen. No user interaction occurs at runtime. You can type the text after you position the bounding rectangle, and you can resize the rectangle as needed. This is the only static text control you'll see listed in text, but you should also create the other static text controls as shown earlier in Figure 6-1. Follow the same procedure for the other static text controls in the dialog. All static text controls have the same ID, but that doesn't matter because the program doesn't need to access any of them.
Figure 15: Setting The static text control.
A static text control (such as Name or Skill) has an ampersand (&) embedded in the text for its caption. At runtime, the ampersand will appear as an underscore under the character that follows. This keyboard accelerator or short cut key, enables the user to jump to selected controls by holding down the Alt key (or Ctrl or Shift) and pressing the key corresponding to the underlined character. The related control must immediately follow the static text in the tabbing order. Thus, Alt-N jumps to the Name edit control and Alt-K jumps to the Skill combo box. Needless to say, designated jump characters should be unique within the dialog. The Skill control uses Alt-K because the SSN control uses Alt-S. Unfortunately the keyboard accelerator not works in this example because we need extra step to make it function and will be shown in another Module. The extra step is setting the key through the Accelerator resource as shown below.
Figure 16: Assigning the keyboard accelerator through the ResourceView.
The Name edit control. An edit control is the primary means of entering text in a dialog. Right-click the control, and then choose Properties. Change this control's ID from IDC_EDIT1 to IDC_NAME. Accept the defaults for the rest of the properties. Notice that the default sets Auto HScroll, which means that the text scrolls horizontally when the box is filled.
The SSN (social security number) edit control. As far as the dialog editor is concerned, the SSN control is exactly the same as the Name edit control. Simply change its ID to IDC_SSN. Later you will use ClassWizard to make this a numeric field.
Figure 17: Modifying the SSN edit control properties.
The Bio (biography) edit control. This is a multiline edit control. Change its ID to IDC_BIO, and then set its properties as shown here.
Figure 18: Modifying the Bio (biography) edit control properties.
The Category group box. This control serves only to group two radio buttons visually. Type in the caption Category. The default ID is sufficient.
The Hourly and Salary radio buttons. Position these radio buttons inside the Category group box. Set the Hourly button's ID to IDC_CAT and set the other properties as shown here.
Figure 19: Modifying the radio button properties.
Figure 20: Modifying the second radio button properties.
Be sure that both buttons have the Auto property (the default) on the Styles tab set and that only the Hourly button has the Group property set. When these properties are set correctly, Windows ensures that only one of the two buttons can be selected at a time. The Category group box has no effect on the buttons' operation.
The Insurance group box. This control holds three check boxes. Type in the caption Insurance.
Later, when you set the dialog's tab order, you'll ensure that the Insurance group box follows the last radio button of the Category group. Set the Insurance control's Group property now in order to "terminate" the previous group. If you fail to do this, it isn't a serious problem, but you'll get several warning messages when you run the program through the debugger.
Figure 21: Modifying the Insurance group box properties.
The Life, Disability, and Medical check boxes. Place these controls inside the Insurance group box. Accept the default properties, but change the IDs to IDC_LIFE, IDC_DIS, and IDC_MED. Unlike radio buttons, check boxes are independent; the user can set any combination.
Figure 22: Modifying the Life, Disability, and Medical check boxes properties.
The Skill combo box. This is the first of three types of combo boxes. Change the ID to IDC_SKILL, and then click on the Styles tab and set the Type option to Simple. Click on the Data tab, and add three skills (terminating each line with Ctrl-Enter) in the Enter Listbox Items box.
Figure 23: Modifying the Skill combo box properties.
Figure 24: Adding the listbox item.
This is a combo box of type Simple. The user can type anything in the top edit control; use the mouse to select an item from the attached list box, or use the Up or Down direction key to select an item from the attached list box.
The Educ (education) combo box. Change the ID to IDC_EDUC; otherwise, accept the defaults. Add the three education levels in the Data page, as shown in Figure 25. In this Dropdown combo box, the user can type anything in the edit box, click on the arrow, and then select an item from the drop-down list box or use the Up or Down direction key to select an item from the attached list box.
Figure 25: Modifying the Educ (education) combo box.
Continue on next module...part 2
Further reading and digging:
MSDN MFC 9.0 class library online documentation - latest version.
DCOM at MSDN.
COM+ at MSDN.
COM at MSDN.