digitalmars.com                      
Last update Sun Mar 4 12:07:01 2018

14. Lesson 5: Add a Dialog Box with ClassExpress

In Lesson 4, you learned how to use ClassExpress to add handlers for Windows messages. The application from that lesson is still skeletal. Its interface is complete, and it receives the Windows messages it needs to act upon, but every user action ultimately results in a call to a stub function. After completing Lesson 4, the next step is writing code that supplies functionality.

This lesson shows you how to use some additional, powerful features of Digital Mars C++. To accomplish this, a body of code that supplies some substantial functionality has been added to the application you built in Lesson 4. In between the end of Lesson 4 and the start of this lesson, only the Source window has been used to create or change C++ files in the project. That is, none of the new code has been automatically generated; it has all been manually entered.

Start this lesson with the project samples\tutorial\lesson5\start\tmlread.prj, located in the directory where you installed Digital Mars C++. The first task you will perform is to build that project. Once you have done so, you will have a fully functional TML Reader.

In the remainder of the lesson, you will implement a Preferences dialog box. In addition to supplying C++ code for the start of this lesson, we have also already used ResourceStudio to create a dialog resource that defines the Preferences dialog box. However, this dialog box is not yet connected to the application. It lies dormant within tmlread.rc. You will perform all the tasks necessary to animate it and make it fully functional.

Specifically, you'll use ResourceStudio to:

Within ClassExpress, you'll: Finally, within the IDDE, you will: After completing this lesson, you will have: The next section walks you through building and running the TML Reader. It also discusses how the Reader displays files and how to create a Preferences dialog box which lets the user configure how the files are displayed.

Building and Exploring the TML Reader

This section acquaints you with the major features of the TML Reader. After building the Reader, you will use it to read sample files that contain TML formatting strings.

Before building the Reader, you must first copy the file viewhdrs.h from the tutorial\tmlread directory to the tutorial\lesson5\backup directories. Various TMLRead modules include this header file, and cannot be compiled without it.

Building the Reader

Follow the first four steps to build the TML Reader.
  1. If you are not already in the IDDE, launch it.
  2. Open the project tmlread.prj in the directory samples\tutorial\lesson5\start located beneath the directory where you installed Digital Mars C++.
  3. Choose Build from the Project menu.
  4. Choose Execute Program from the Project menu to run the program. The IDDE minimizes, and TMLRead is launched. No file is yet displayed.

Exploring the capabilities of the Reader

Now use the Reader to browse two sample files that illustrate the kinds of formatting that the Reader can display.
  1. Choose Open from TMLRead's File menu.
  2. In the File Open dialog box, select the file sample.tml in the samples\tutorial\lesson5\start directory, then click OK. TMLRead reads, parses, and displays the file.
  3. Scroll within the document using the arrow keys and the Page Up and Page Down keys. Code within CTMLReadView::OnKeyDown causes the scrolling to occur.
  4. Now scroll by using the vertical scroll bar. In this case, code within CTMLReadView::OnVScroll is responsible for the scrolling.
  5. Drag either the left or right border of the window to resize it. Notice that the ends of lines are automatically adjusted so that paragraphs wrap properly, filling almost all of the window's width. The handler CTMLReadView::OnSize causes rewrapping to occur.
  6. If you are not now displaying the beginning of the file, press the Home key. The heading "Contents" announces the table of contents of this document, presented as a hierarchical bulleted list of the major sections of sample.tml. Each line in the table of contents is underlined and displayed in green. These properties of the text indicate that it is a hyperlink. Place the cursor over any hyperlink; the cursor changes to a hand with an extended index finger, a visual cue that you can meaningfully click on the text. Move the cursor so that it is not over a hyperlink; the cursor reverts to the default cursor. This behavior is provided by CTMLReadView::OnSetCursor after a necessary initialization by CTMLReadView::PreCreateWindow.
  7. Click on the last hyperlink in the Contents section, named "Hyperlinks," with the left mouse button. This displays the last section of the file. The method CTMLReadView::OnLButtonDown handles the mouse click by determining whether or not it occurred on a hyperlink; if a hyperlink is clicked, the jump occurs.
  8. At the end of the last paragraph, there is the following hyperlink phrase: "here is a link to another sample document." Click on this phrase. The file complex.tml is read and displayed. Again, CTMLReadView::OnLButtonDown causes the jump to occur.
  9. Choose Previous File from TMLRead's File menu to return to sample.tml.
  10. Examine each section of sample.tml by clicking each hyperlink in the document's contents at the top of the file. This will give you a good sense of the features of TML, the subset of HTML (HyperText Markup Language) recognized by the Reader.
  11. Choose Print Preview from TMLRead's File menu to see a WYSIWYG display of how sample.tml would look if it were printed on the current default printer. The presence and functionality of the buttons at the top of the Print Preview window has been supplied almost entirely by MFC. When you finish looking at the Print Preview display, click Close to return to the main view of the Reader.
  12. Choose Exit from TMLRead's File menu. This closes the Reader and returns you to the IDDE.

Turning aspects of the Reader's display into preferences

A few numerical quantities that help determine how TMLRead displays documents are at present hard-coded. These numbers are stored as int data members of CTMLReadView and are described in the following table:
nParVSpace
Vertical space between paragraphs
nMargin
Amount of horizontal space between the document and the edges of the window
nIndent
Amount by which items in a list are offset from the left margin
The CTMLReadView constructor calls CTMLReadView::SetDefaultPrefs to initialize these data members with default values provided by the following enum constants (defined in the class declaration):
	eDftParVSpace = 12
	eDftMargin = 10 
	eDftIndent = 40 
The Preferences dialog box lets the user alter these values, as shown in Figure 14-1.

[Figure 14-1 The Preferences dialog box]

Of course, the user should be allowed to configure many other aspects of the Reader's display, such as colors and fonts. However, implementing this simple Preferences dialog box gives you the fundamental skills needed to realize more ambitious designs using the Digital Mars C++ tools.

Before you connect the Reader's data with the controls of the Preferences dialog box, you need to first outfit the user interface with a way to call the dialog box. In the next section, therefore, you'll use ResourceStudio to add a menu item to TMLRead.

Using ResourceStudio to Add a Menu Item

To add a Preferences item to the View menu of TMLRead, launch ResourceStudio from within the IDDE so that it loads tmlread.rc. To do this, follow these steps:
  1. Open the Project window if it is not already open.
  2. Double-click on tmlread.rc in the Project window. When asked if you want to use ResourceStudio to edit this file, click Yes.

    The Browser window of ResourceStudio opens, as shown in Figure 14-2.

    [Figure 14-2 The Browser window of ResourceStudio]

  3. Select the item named Menu in the upper-left pane. The lower-left pane now displays the ID of the TMLRead menu, IDR_MAINFRAME.
  4. Double-click on IDR_MAINFRAME in the lower-left pane. The pane on the right now contains a representation of the TMLRead menu, shown in Figure 14-3.

    The Property Sheet and the Test menu window also open; they are described in Chapter 12, "Lesson 3: Customize the Interface."

    [Figure 14-3 ResourceStudio displaying the TMLRead menu]

  5. In the right pane, click on the item MENUITEM Status Bar to select it. This item is the last one belonging to the POPUP View item. When a new menu item is added, it will appear beneath this one.
  6. Choose New Item from the Menu menu in the Browser window. This inserts a new item whose text is Item, and creates a new ID for it. The Property Sheet, shown in Figure 14-4, shows these settings.

    [Figure 14-4 The Property Sheet after adding a new item]

  7. Click on the Property Sheet to make it active.
  8. Click on the General tab near the top of the window to ensure that the General page is displayed.
  9. In the ID textbox, type ID_VIEW_PREFS to change the ID name.
  10. In the text textbox, type &Preferences....
  11. Click on the Connect tab.
  12. On this page, type the string Customize the appearance of the view. This prompt will appear in the status bar whenever the Preferences item is selected.
  13. Save your work by choosing Save from the Browser window's File menu.
  14. Close the Browser window, close the ResourceStudio Shell window (and with it, the Property Sheet), and return to the IDDE.
You have now created the desired menu item. However, TMLRead does not yet contain a command handler for ID_VIEW_PREFS. In the next section, you will add one using ClassExpress, in which the bulk of the remaining work will take place.

Two command handlers must be added- one for ID_VIEW_PREFS, the other for the Default button of the Preferences dialog box. Thus, a class must be created that represents the Preferences dialog box in the same way that CAboutDlg represents the About dialog box. The handler for the Default button will be a method for this new class. In the next section, you use ClassExpress to add the CPrefDialog class.

Using ClassExpress to Create a New Dialog Class

Follow these steps to create a class that corresponds to the Preferences dialog box:
  1. Launch ClassExpress by choosing ClassExpress from the IDDE's Tools menu.
  2. Click the Add Class button. The Add Class dialog box opens, as shown in Figure 14-5. ClassExpress detects that a new dialog box has been added to the project, and assumes that you want to create a corresponding class.

    It initializes the selections in the Class Type and Dialog ID drop-down lists to reflect this assumption: Class Type is set to Dialog, and Dialog ID to IDD_PREFDIALOG.

    [Figure 14-5 The Add Class dialog box]

    The focus is in the New Class Name editbox. ClassExpress has suggested the name CTestDialog and has selected the substring Test so that you can change it just by typing. It has also suggested TestDial.cpp as the name of the implementation file.

  3. Type Pref to change the name of the dialog class to CPrefDialog. Notice that ClassExpress accordingly changes the suggested name of the implementation file to PrefDial.cpp.
  4. Click OK in the Add Class dialog box to accept the settings. ClassExpress confirms the operation with a message box.
  5. Click OK to close this message box. This returns you to the ClassExpress window, which displays the Message Maps page, as shown in Figure 14-6.

    [Figure 14-6 ClassExpress displaying the Message Maps page]

Using ClassExpress to Add Methods

In this section, you'll add two methods that respond to user actions. One opens the Preferences dialog box when the Preferences menu item is chosen, and updates the Reader's display if the OK button is clicked in the dialog box. The other method handles the clicking of the Default button in the Preferences dialog box. You will see later why it is unnecessary to add handlers for the OK and Cancel buttons.

First you'll add a method that handles the command generated when Preferences is chosen from the View menu. This method also is responsible for updating the application to reflect any changed preferences. Then, you'll add a method that responds to a click on the Default button of the Preferences dialog box.

The procedure in each case is similar to the one that you used in Lesson 4. The results of your actions also will be similar: ClassExpress adds these methods to class declarations, add entries to Message Maps, and create stub functions for the methods. When you return to the IDDE, you will only need to write the code for these two methods.

Creating a handler for the Preferences command

You will use ClassExpress to bind the ID_VIEW_PREFS command ID to a new method that creates and initializes an object of class CPrefDialog, and then uses this object to display the dialog box. When the user closes the dialog box, this method determines whether the user clicked OK or Cancel. If OK was clicked, application data must be updated, and the view must be redrawn.

This method needs access to data members of CTMLReadView in order to initialize the dialog box and to update those data members if the user clicks OK. Because of these requirements, the method is added to the class CTMLReadView.

  1. Select the class CTMLReadView in the Class combobox on the Message Maps page.
  2. In the Control IDs in the Class listbox, select ID_VIEW_PREFS, the ID of the command issued when the Preferences item in the View menu is chosen. The listbox on the right, Windows Messages, now contains the two items, COMMAND and UPDATE_COMMAND_UI.
  3. Double-click on COMMAND in the Windows Messages listbox. The Method Name dialog box opens, asking you for a name for the method that is called when Preferences is chosen. ClassExpress suggests the name OnViewPrefs for this method.
  4. Click OK in the Method Name dialog to accept the name OnViewPrefs.
ClassExpress adds this method to the declaration of class CTMLReadView in the header file for the class. It also updates the class implementation file by adding an entry to the class's Message Map, and by adding a stub function CTMLReadView::OnViewPrefs.

Creating a handler for the Default button of the Preferences dialog box

You will now add a method to CPrefDialog for handling clicks on the Default button in the Preferences dialog box. This method must update the values displayed in the controls of the dialog box with the same default values used to initialize the CTMLReadView data members nParVSpace, nMargin, and nIndent. Because the default values are public enum constants, this method requires no access privileges to CTMLReadView.

Follow these steps to add this method:

  1. Select the class CPrefDialog in the Class combobox on the Message Maps page.
  2. In the Control IDs in Class listbox, select ID_PREFS_DEFAULT, the ID of the Default button. The listbox on the right, Windows Messages, now contains the two items BN_CLICKED and BN_DOUBLECLICKED.

    Note: These so-called messages are actually notifications that the button sends to its parent, the Preferences dialog box, via WM_COMMAND messages. BN_xxx stands for Button Notification. The BN_xxx identifiers are defined in windows.h.

  3. In the Windows Messages listbox, double-click on BN_CLICKED, the notification sent when the Default button is clicked. The Method Name dialog box opens, suggesting OnClickedPrefsDefault for the method name.
  4. Change this name to OnDefault.
  5. Click OK in the Method Name dialog box to return to the ClassExpress main window.
As it did when you added CTMLReadView::OnViewPrefs, ClassExpress adds a prototype for OnDefault to the declaration of the class CPrefDialog in the class's header file. It also updates the class implementation file by adding an entry to the class's Message Map. It also adds a stub function CPrefDialog::OnDefault.

Once you are back in the IDDE, you must write code to implement these two handlers. To have the handlers to perform their intended tasks, you must first make it possible to transfer data into and out of the controls of the Preferences dialog box. MFC and ClassExpress make it surprisingly easy not only to transfer data to and from a dialog box, but also to validate data that the user has entered into a dialog's controls. Adding these capabilities is addressed in the next section, the last one in which you use ClassExpress.

Adding Dialog Data Exchange and Validation

Windows programs written in C traditionally exchange data with dialog boxes by fetching data from each control in a manner particular to the control type (edit control, radio button, check box, and so on) and particular to the intended type of the data (string, integer, long integer, and so on). Then, the extracted data is usually stored in static storage. Also, there are rarely any general-purpose facilities from Windows API for validating data that the user enters in a dialog box- placing another burden on the programmer.

MFC and ClassExpress add order, simplicity and elegance to this situation. To use the MFC model of dialog box data exchange and validation, you must first add data members to the dialog class. (This replaces the ad hoc collection of static data favored by the traditional approach.) You use ClassExpress to associate data members with controls in the dialog box. MFC then automates the transfer of data between the dialog's controls and the dialog class data members. When adding a data member with ClassExpress, you also specify its type and the validation criteria in the associated control. MFC uses this information to perform its automatic data validation.

In the next step, you'll add data members to the CPrefDialog class using the Data Transfer page of ClassExpress. After you complete this task, there is a review of the changes that ClassExpress has made to the CPrefDialog source files, and an explanation of how MFC accomplishes data exchange and validation.

Throughout this section, you'll work with the CPrefDialog class on the Data Transfer page of ClassExpress. Perform the following steps to set up ClassExpress for this part of the lesson:

  1. In the upper-left listbox, select the second item, Data Transfer. ClassExpress opens the Data Transfer page in the larger pane on the right, as shown in Figure 14-7.

    [Figure 14-7 ClassExpress displaying the Data Transfer page]

  2. Be sure that CPrefDialog is selected in the Class Name combobox at the top of the Data Transfer page.

Adding data members to CPrefDialog

To add data members, to CPref Dialog, carry out the following steps:
  1. Click on the Add Variable button. The Add Member Variable dialog box opens, as shown in Figure 14-8.

    [Figure 14-8 The Add Member Variable dialog box]

  2. Select IDC_PARVSPACE from the Control ID combobox.
  3. Change the Member Variable Name to nParVSpace. (For simplicity, you can name the member variables of CPrefDialog the same as the members of CTMLReadView to which they correspond.)
  4. For the DDX Type option, select Value.

    In fact, the Control Name combobox does not contain symbolic indentifiers for the three edit controls in the Preferences dialog box. Rather, you see only the integer resource ids of these controls. Select 3001, the resource id of the Paragraph Spacing edit control.

  5. In the Variable Type combobox, select int. Two new textboxes, Minimum Value and Maximum Value, appear at the bottom of the dialog box, as shown in Figure 14-9.

    [Figure 14-9 Add Member Variable with Variable Type set to int]

  6. Type 0 in the Minimum Value field.
  7. Type 100 in the Maximum Value field.
  8. Click OK in the Add Member Variable dialog box. The Data Transfer page now reflects this additional data member and its validation criteria in the Control ID and Variables list, as shown in Figure 14-10.

    [Figure 14-10 The Data Transfer page after adding nParVSpace]

  9. Follow the procedure described in steps 3 through 10 of the previous task to add an int variable named nMargin associated with the control IDC_MARGIN. Set its minimum and maximum values to 0 and 50, respectively.

    In fact, the Control Name combobox does not contain symbolic identifiers for the three edit controls in the Preferences dialog box. Rather, you see only the integer resource ids of these controls. Therefore, add a data member corresponding to the control 3004, the resource id of the Margin edit control.

  10. Then, follow steps 3 through 10 to add a final int variable, nIndent, associated with the control IDC_INDENT. Sets its minimum and maximum values to 0 and 120, respectively.

    In fact, the Control Name combobox does not contain symbolic identifiers for the three edit controls in the Preferences dialog box. Rather, you see only the integer resource ids of these controls. Therefore, add a data member corresponding to the control 3005, the resource id of the Indent edit control.

To return to the IDDE, click the Close button. The IDDE's Project window now lists the source file prefdial.cpp.

Seeing the changes in the CPrefDialog source files

As a result of adding data members to CPrefDialog, ClassExpress makes various changes to the header and implementation files of the class CPrefDialog including:

Changes to the class definition

ClassExpress added the following lines to the declaration of CPrefDialog in prefdial.h:
	// Dialog Data
	    //{{ AFX_DATA(CPrefDialog) 
	    enum { IDD = IDD_PREFDIALOG };
	    int nParVSpace; 
	    int nMargin;
	    int nIndent; 
	    //}} AFX_DATA 

	// Implementation
	protected: 
	    virtual void DoDataExchange(CDataExchange* pDX); // DDX/ DDV support 
The comments help ClassExpress find where subsequently added data members should be declared. (The variables that ClassExpress adds are public.) The enum constant IDD is used by the CPrefDialog constructor as an argument to the constructor of its base class, CDialog.

Changes to the constructor

ClassExpress changes the CPrefDialog constructor so that it appears as follows:
	CPrefDialog::CPrefDialog(CWnd* pParent /*= NULL*/)
	   : CDialog(CPrefDialog::IDD, pParent) 
	{
	    //{{ AFX_DATA_INIT(CPrefDialog)
	    nParVSpace = 0; 
	    nMargin = 0;
	    nIndent = 0; 
	    //}} AFX_DATA_INIT
	} 
The AFX_DATA_INIT comments are used by ClassExpress to delimit the location within the constructor where data members participating in data exchange and validation should be initialized. All the data members that you added are set to 0. Therefore, before it displays the Preferences dialog box, the handler CTMLReadView::OnViewPrefs first sets these CPrefDialog data members to the values of the CTMLReadView data members to which they correspond.

Changes to the DoDataExchange function

The protected member function DoDataExchange is the workhorse that transfers data between the added data members and the controls of the Preferences dialog box. It also validates the values entered into the controls when the user clicks OK. (The acronym DDX stands for Dialog Data eXchange; DDV stands for Dialog Data Validation.) ClassExpress also writes the DoDataExchange function, using the information you gave it when you added each variable. The implementation of the function, in PrefDial.cpp, looks like this:
	void CPrefDialog::DoDataExchange(CDataExchange* pDX) 
	{
	    CDialog::DoDataExchange(pDX); 
	    //{{ AFX_DATA_MAP(CPrefDialog)
	    DDX_Text(pDX, IDC_PARVSPACE, nParVSpace); 
	    DDV_MinMaxInt(pDX, nParVSpace, 0, 100);
	    DDX_Text(pDX, IDC_MARGIN, nMargin); 
	    DDV_MinMaxInt(pDX, nMargin, 0, 50);
	    DDX_Text(pDX, IDC_INDENT, nIndent); 
	    DDV_MinMaxInt(pDX, nIndent, 0, 120);
	    //}} AFX_DATA_MAP 
	} 
Again, the AFX_DATA_MAP comments serve only as delimiters used by ClassExpress when adding data members.

The overloaded DDX_xxx and DDV_xxx functions are declared in the MFC include file afxdd_.h. These functions all take a pointer, pDX, to a CDataExchange object. This object contains two public data members that enable the functions.

The CDataExchange data member m_bSaveAndValidate informs the functions of the direction of the transfer. If m_bSaveAndValidate is TRUE, then the transfer is from the controls to the data members; if this data member is FALSE, the transfer is from the data members to the controls. The DDX_xxx functions perform the appropriate transfer in each case. If m_bSaveAndValidate is TRUE, each DDV_xxx validation function checks whether the data meets the validation criteria it implements. If the data fails to meet the criteria, the validation function opens a message box informing the user, and sets the focus to the control containing the invalid value. If m_bSaveAndValidate is FALSE, the validation functions do nothing.

The CDataExchange data member m_pDlgWnd is a pointer to the CWnd whose data is being transferred and validated. The presence of this data member saves DoDataExchange from having to pass the this pointer to every DDX_xxx and DDV_xxx function.

Note: Because DoDataExchange is a CWnd member function and m_pDlgWnd is a CWnd*, DDX and DDV can be used with any window, and not just with those derived from CDialog.

DoDataExchange is called by the UpdateData function whenever data exchange must take place. You never call it directly. In particular, DoDataExchange is called when a window or dialog box is first opened to initialize its controls. It is also called by the CDialog member function OnOK when a user clicks on a button in the dialog box with an ID of IDOK. Thus in the Preferences dialog box, the inherited handler for the OK button already performs data transfer and validation, so you do not need to supply an override. Similarly, the CDialog member function OnCancel simply terminates a dialog box- behavior completely suitable for the Preferences dialog box.

With these concepts in mind, you can clearly see the purpose and effect of the handlers that you supply in the next task.

Writing Code for the New Handlers

Now, the only task left is to provide implementations of the handlers CTMLReadView::OnViewPrefs and CPrefDialog::OnDefault. Both handlers are straightforward.

Implementing CTMLReadView::OnViewPrefs

Carry out these steps to create the handler:
  1. In the Project window, double-click on tmlrdvw.cpp. This opens a Source window in which you can edit the file tmlrdvw.cpp.
  2. Find the group of #include statements toward the top of the file. Add this line after the last #include statement:
    	#include "prefdial.h" 
    
  3. Find the function CTMLReadView::OnViewPrefs. (It is at the bottom of the file.)
  4. Edit the function by entering the following code. (You may omit the lengthy comments.)
    	void CTMLReadView::OnViewPrefs()
    	{   
    	    CPrefDialog dlgPref; 
    
    	    // Initialize dlgPref data members with
    	    // current values from CTMLReadView 
    	    //
    	    dlgPref.nParVSpace = nParVSpace; 
    	    dlgPref.nMargin = nMargin;
    	    dlgPref. nIndent = nIndent; 
    
    	    // Display the dialog modally.
    	    // If user clicks OK, DoDataExchange 
    	    // will be called to validate data in
    	    // the controls. If the controls hold valid 
    	    // values, their contents will be
    	    // transferred to the CPrefDialog data 
    	    // members. In that case, we must transfer
    	    // the values to the corresponding 
    	    // CTMLReadView data members.
    	    // 
    	    if (dlgPref. DoModal() == IDOK)
    	    {   
    		// Transfer the data to our view class
    		// 
    		nParVSpace = dlgPref.nParVSpace;
    		nMargin = dlgPref.nMargin; 
    		nIndent = dlgPref.nIndent; 
    
    		// Make sure that the view is redrawn
    		// to reflect the new preferences 
    		//
    		bWordsWrapped = FALSE; 
    		OnUpdate(NULL, 0L, NULL);
    	    } 
    	}
    
  5. Save your work by choosing Save from the File menu of the Source window.
  6. Close the Source window by clicking on the close box in the upper-left corner of the window (on the caption bar).

Implementing CPrefDialog::OnDefault

This handler is even simpler. To create it, perform these steps:
  1. In the Project window, double click on prefdial.cpp. This opens a Source window in which you can edit the file prefdial.cpp.
  2. Find the group of #include statements, toward the top of the file. Add this statement to the end of the group:
    	#include "viewhdrs.h" 
    
  3. Find the function CPrefDialog::OnDefault. (It is at the bottom of the file.)
  4. Edit the function by entering the following code. (You may omit the lengthy comments.)
    	void CPrefDialog::OnDefault()
    	{   
    	    // Set data members to default values
    	    // 
    	    nParVSpace = CTMLReadView::eDftParVSpace;
    	    nMargin = CTMLReadView::eDftMargin; 
    	    nIndent = CTMLReadView::eDftIndent; 
    
    	    // Transfer these values to the controls. 
    	    // UpdateData calls DoDataExchange to effect 
    	    // the transfer. The argument determines the 
    	    // direction of the transfer: 
    	    // TRUE causes values to move from the 
    	    // controls to the data members; 
    	    // FALSE, used here, transfers the values of 
    	    // the data members to the controls. 
    	    // UpdateData uses its argument to set the 
    	    // m_bSaveAndValidate data member of the 
    	    // CDataExchange object whose address 
    	    // it passes to DoDataExchange. 
    	    // 
    	    UpdateData(FALSE); 
    	}
    
  5. Save your work by choosing Save from the File menu of the Source window.
You have now completed all the tasks necessary for the Preferences dialog box to be fully functional. To conclude this lesson, you will rebuild TMLRead and test the dialog box.

Rebuild and Test TMLRead

To verify that your work has achieved the desired goal, rebuild and run the Reader, making it a point to use the new features. To do this, follow these steps:
  1. Choose Build from the Project menu to incorporate the changes you have made into the executable file tmlread.exe.
  2. Choose Execute Program from the Project menu to run the Reader.
  3. Choose Open from the File menu of TMLRead. Again, load the file sample.tml.
  4. Choose Preferences from the View menu of TMLRead.
  5. Enter 25 into all three edit controls.
  6. Click on the Default button to verify that the CPrefDialog data members are set to default values by CPrefDialog::OnDefault.
  7. Click Cancel. You should see no change in the display of sample.tml.
  8. Again, choose Preferences from the View menu of TMLRead.
  9. Change the values to 150, 40, and 10, respectively.
  10. Click OK. Observe the message box informing you of invalid data.
  11. Click OK to close the message box. The focus returns to the editbox containing 150.
  12. Continue experimenting with the Preferences dialog box, eventually clicking OK when valid data is entered in the controls. After you have confirmed that the dialog box is performing as you want, exit the program by choosing Exit from the Reader's File menu. This returns you to the IDDE.

Summary

In this lesson, you learned: This concludes the tutorial section. These lessons have been an instructive introduction to the capabilities of Digital Mars C++. By this point, you will have acquired the techniques and knowledge you need to apply the features of Digital Mars C++ to your own projects.
Home | Compiler & Tools | Runtime Library | STL | Search | Download | Forums | Prev | Next