Property Sheets

You've already seen property sheets in Visual C++ and in many other modern Windows-based programs. A property sheet is a nice UI element that allows you to cram lots of categorized information into a small dialog. The user selects pages by clicking on their tabs. Windows offers a tab control that you can insert in a dialog, but it's more likely that you'll want to put dialogs inside the tab control. The MFC library supports this, and the result is called a property sheet. The individual dialogs are called property pages.

Building a Property Sheet

Follow these general steps to build a property sheet using the Visual C++ tools:

  1. Use the resource editor to create a series of dialog templates that are all approximately the same size. The captions are the strings that you want to display on the tabs.

  2. Use ClassWizard to generate a class for each template. Select CPropertyPage as the base class. Add data members for the controls.

  3. Use ClassWizard to generate a single class derived from CPropertySheet.

  4. To the sheet class, add one data member for each page class.

  5. In the sheet class constructor, call the AddPage member function for each page, specifying the address of the embedded page object.

  6. In your application, construct an object of the derived CPropertySheet class, and then call DoModal. You must specify a caption in the constructor call, but you can change the caption later by calling CPropertySheet::SetTitle.

  7. Take care of programming for the Apply button.

Property Sheet Data Exchange

The framework puts three buttons on a property sheet. (See, for example, Figure 13-5.) Be aware that the framework calls the Dialog Data Exchange (DDX) code for a property page each time the user switches to and from that page. As you would expect, the framework calls the DDX code for a page when the user clicks OK, thus updating that page's data members. From these statements, you can conclude that all data members for all pages are updated when the user clicks OK to exit the sheet. All this with no C++ programming on your part!

With a normal modal dialog, if the user clicks the Cancel button, the changes are discarded and the dialog class data members remain unchanged. With a property sheet, however, the data members are updated if the user changes one page and then moves to another, even if the user exits by clicking the Cancel button.

What does the Apply button do? Nothing at all if you don't write some code. It won't even be enabled. To enable it for a given page, you must set the page's modified flag by calling SetModified(TRUE) when you detect that the user has made changes on the page.

If you've enabled the Apply button, you can write a handler function for it in your page class by overriding the virtual CPropertyPage::OnApply function. Don't try to understand property page message processing in the context of normal modal dialogs; it's quite different. The framework gets a WM_NOTIFY message for all button clicks. It calls the DDX code for the page if the OK or Apply button was clicked. It then calls the virtual OnApply functions for all the pages, and it resets the modified flag, which disables the Apply button. Don't forget that the DDX code has already been called to update the data members in all pages, so you need to override OnApply in only one page class.

What you put in your OnApply function is your business, but one option is to send a user-defined message to the object that created the property sheet. The message handler can get the property page data members and process them. Meanwhile, the property sheet stays on the screen.