Netscape 4.x Preferences Dialog


When designing complex dialog boxes, one uses a property sheet whose functionality is encapsulated by MFC class CPropertySheet. However, there are several cases where alternative approach (dialog box similar to Netscape 4.x Preferences dialog box) is more flexible and user friendly.

  • When there are a lot of property pages in which case it is difficult to navigate thru the pages.
  • When there are several different sets of property pages whose visibility depends on the state of the application.
  • When there is a need for nested property pages.
Of course, there is always a possibility to derive a class from CPropertySheet and adapt it for the task at hand. However, this requires in depth knowledge of MFC implementation and also browsing the MFC source code which is not a trivial thing to do.

Basically, tree control contains a list names where each name is associated with a property page. This list may be (1) a simple list with no root, (2) list with a root which indicates the purpose of the visible set of property pages and (3) a list where one or more items contain one or more child items. When the user selects an item in a list, application automatically makes a property page associated with this item visible while all the other pages are invisible. It is also possible to replace the contents of the tree control with different lists according to the state of the application (for example, different list should be displayed for application configuration).


Implementation of this dialog is split into several steps:

Step 1:

Design a dialog box. Put whatever you need on it. Also place a tree control and a picture control which is actually a placeholder for property pages. Let's assume that the ID of the tree control is IDC_TREE and the ID of the picture control is IDC_PLACEHOLDER. Picture control should be invisible.

Step 2:

Design a separate dialog for each of the property pages. Put whatever controls you need on each dialog. Each dialog shoould have the following properties:
  • No titlebar
  • Style Child
  • Disabled
  • No border
  • Invisible
Using class wizard, create a class for each property page dialog. Base class must be CDialog. Each property page must override virtual functions CDialog::OnCancel() and CDialog::OnOK() since their default implementation will close the dialog.

Step 3:

Create the following structure which describes all the data associated with a property page.
struct TItem {
  int OptionId;        // Unique identification of this page
  LPCTSTR Name;        // Property page name displayed in a tree control
  int DialogID;        // Resource ID of the property page dialog
  void *Handle;        // HTREEITEM
  void *Parent;        // HTREEITEM
  CDialog *Dialog;     // Pointer to property page dialog
  BOOL Created;        // Is the dialog create or not
  long HelpID;         // Help ID for a property page
Within your source file, create a constant array of these structures and initialize it.
static TItem Options[] = {
    { 1, "General settings",    IDD_PROPPAGE1, NULL, NULL, NULL, FALSE, HELP_GENERAL },
    { 2, "Login settings",      IDD_PROPPAGE2, NULL, NULL, NULL, FALSE, HELP_LOGIN },
    { 3, "Connection settings", IDD_PROPPAGE3, NULL, NULL, NULL, FALSE, HELP_CONNECTION },
    { 4, "About",               IDD_PROPPAGE4, NULL, NULL, NULL, FALSE, HELP_ABOUT },
You need also to implement the following function:
TItem *TMainDialog::insertOption(HTREEITEM hroot, int option, BOOL select)
    TItem *ptr = &(Options[option]);
    HTREEITEM handle;
    handle = GetDlgItem(IDC_TREE)->InsertItem(ptr->Name, hroot);
    ptr->Handle = (void *)handle;
    ptr->Parent = (void *)hroot;
    if (select)
    CDialog *dialog = createDialog(ptr->OptionId,ptr->DialogID);
    CRect rect;
    dialog->SetWindowPos(NULL, rect.left,, 0, 0, 
    ptr->Dialog = dialog;
    ptr->Created = TRUE;
    return ptr;
}// TPage1... are classes associated with property pages.
CDialog *TMainDialog::createDialog(int optionId, int dialogId)
    CDialog *dialog = NULL;
    switch (optionId) {
    case 1: dialog = new TPage1; break;
    case 2: dialog = new TPage2; break;
    case 3: dialog = new TPage3; break;
    case 4: dialog = new TPage4; break;
    ASSERT(dialog != NULL);
    return dialog;
These two functions are responsible for property page creation. Notice that pointer to TItem structure is associated with an item in a tree control.

Step 4:

You need to fill the tree control and display the initial property page. This is done in OnOnitDialog() handler of the main dialog.
hroot = GetDlgItem(IDC_TREE)->InsertItem("Configuration");
insertOption(hroot,1,TRUE);    // Make first page visible
After this code, the tree control is filled, property pages are created and the first one is visible.

Step 5:

When the user selects another item in a tree control, you need to deactivate the currently visible property page and activate a new one (the one associated with the selected tree item). In order to perform this, following two functions are needed:
void TMainDialog::activateOption(TItem *item)
    ASSERT(item != NULL);
    Option = item;    // see below
    CDialog *dialog = Option->Dialog;
    ASSERT(dialog != NULL);

void TMainDialog::deactivateOption(TItem *item)
    ASSERT(item != NULL);
    CDialog *dialog = item->Dialog;
    ASSERT(dialog != NULL);
Option is a global variable of type TItem* which contains the currently selected item. In deactivateOption, visible property page is hidden. In activateOption, new property page is shown and updated (redrawn). Pointer to the new item structure is saved to global Option variable. These two functions are used in combination from the tree control handler triggered when the selection is changed (wither by the mouse or the keyboard). The following code handles the property page changes:
HTREEITEM handle = GetDlgItem(IDC_TREE)->GetSelectedItem();
if (handle != NULL) {
    TItem *item = (TItem*)GetDlgItem(IDC_TREE)->GetItemData(handle);
    if (item && (item != Option)) {

That's all. In a real world implementation, minor additions to the presented code are welcomed:

  • Create a base class for all property pages and add handlers executed when the page becomes active/inactive.
  • Add help for each page - trivial task since currently active page is accessable via Option variable and it contains a help ID for the page.
  • Presented code will create all the property pages and then only modify the visible flag for each page. It is possible to create/destroy pages when they are activated/deactivated. Which solution is appropriate depends on the application.


This is a very flexible solution for complex dialog boxes. It offers complete control of the creation/destruction of all the pages and allows dynamic modification of available property pages (not presented here). Since the basis is a plain dialog, it is possible to organize it anyway you like. The latest version of this article can be downloaded from my home page:


  • Please attach the demo code

    Posted by Legacy on 02/27/2003 12:00am

    Originally posted by: Juli

    It'll realy help if you'll send me the demo code.
    Thanks a lot.

  • Ooops, most probably I re-invented the wheel:-)

    Posted by Legacy on 07/29/2002 12:00am

    Originally posted by: Christopher Frank


    Sorry man.

    Was searching for the article I have contributed a few weeks ago and found it, but also found yours which does have absolutely the same content (but was first).

    Seems that the codeguru guys don't know exactly what is on the server anymore:-)

    Just wanted to tell that I don't want to compete neither have stolen your idea.

    Anyhow, I like the idea (but I like my implementation more than yours of course;-)

    Tot ziens

  • Child dialog is not Tab Stop

    Posted by Legacy on 01/09/2002 12:00am

    Originally posted by: Gary


    I'm using this technique to implement my own wizard-style dialog. However, it seems you can't TAB to the fields in the child dialogs. Pressing Tab only switches between the controls on the main dialog...

    Am I missing something?


  • pls send the entire code

    Posted by Legacy on 05/31/2001 12:00am

    Originally posted by: Radha

    Pls give me the entire source code.IF u give to me u make a big help to us.pls give me reply.
    thank u

  • Please, give the entire project.

    Posted by Legacy on 07/26/1999 12:00am

    Originally posted by: David Betz

    Please, give the entire project.

  • Dialog as control

    Posted by Legacy on 07/14/1999 12:00am

    Originally posted by: Yorik

    you can simple add to property dialogs style 'control'
    and you will don't need override virtual functions OnOK () and OnCancel ().

  • What the McFuck?

    Posted by Legacy on 05/04/1999 12:00am

    Originally posted by: Pejare LaFonte

    Where is the Botto demo source?

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Enterprises are increasingly looking to platform as a service (PaaS) to lower their costs and speed their time to market for new applications. Developing, deploying, and managing applications in the cloud eliminates the time and expense of managing a physical infrastructure to support them. PaaS offerings must deliver additional long-term benefits, such as a lower total cost of ownership (TCO), rapid scalability, and ease of integration, all while providing robust security and availability. This report …

  • Anthony Christie, the Chief Marketing Officer for Level Communications, is responsible for customer experience, worldwide marketing and product management. In this informative asset, he shares his insights into why a private network connection to cloud-bases applications is the right decision for your enterprise. Download now to find out more.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date