Changing Contents of a Property Page with a ComboBox


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

I wanted to create a property page whose controls changed when the user changed the selection in a combo box located on the page. This property page is similar to the one in Microsoft Visual Studio on the Project...Settings...C/C++ tab. On that page when you change the selection in the Category combo box, all of the controls beneath the combo box change. For example,

My first reaction was to create a dialog in the resource editor with the controls stacked on top of each other and show/hide the various controls. This for obvious reasons is a maintenance nightmare. What I really wanted to do was create separate dialogs for each option in the combo box. Thanks to Mike Liss's CodeGuru article on modeless child dialogs not only did I learn how to do just that but also how to get the tab order to go from the controls on the property page to the embedded dialog's controls properly.

Instead of deriving the child dialogs from CDialog, I instead chose to derive them from CPropertyPage. My reason for doing this is so that the main property page could invoke the CPropertyPage methods in the child pages. For example, in OnKillActive the main page would invoke OnKillActive on the current child page to determine whether it was acceptable for the main page to no longer be the active page.

Step 1: Create the main property page in the resource editor

Open the resource editor and add a new dialog. Assign an appropriate ID and set the caption for the property sheet tab. Remove the OK and Cancel buttons. Drop static text on the page to describe the contents of the combo box. Now drop the combo box on the page. Bring up the properties for the combo box and set the ID to IDC_COMBOPAGE_COMBO. Switch to the Styles tab and change the Type to Drop List and remove the checkmark for Sort. For example,

Do NOT fill in any data for the combo box.

Now drop a Picture control on the page and position it as far left as possible. You do not need to resize the control. Bring up the properties for the picture and set the ID to IDC_DLG_AREA. Clear the Visible checkbox and make sure the Type is set to Frame. For example,

Your dialog/property page should look like the following:

Step 2: Create the child property pages

Follow these steps for each option that you wish to appear in the combo box. Insert a new dialog in the resource editor. Assign an appropriate ID and set the caption to the text that you wish to appear in the combo box. Drop whatever controls you wish onto your dialog. Bring up the Properties for the dialog and select the Styles tab. Make it a child dialog with a thin border on this page, such as:

Select the More Styles tab and check the Control checkbox, for example:

Create a class for the property page by bringing up the ClassWizard. Make sure the class is derived from CPropertyPage. Add a handler for WM_INITDIALOG if you wish to initialize the controls in your property page. If you want to validate the data in your property pages, write a handler for OnKillActive and return FALSE if the page is invalid.

Step 3: Add a new class to your project

After you have downloaded the source code, copy the CodePage.cpp and CodePage.h files to your project directory and add them to your project. Be sure to include the CodePage.h file from the source file that will add the page to a property sheet. Also include all of the header files for the property page classes to add to the combo page.

Step 4: Add the property pages to the page

In the source file that will use the combo page, you will need to create an instance of the combo page and all of the property pages to add to it. When creating an instance of CComboPage you need to specify the ID of the property page you created in step 1. Then you simply add the property pages to the combo page specifying the ID of each property page. For example,

void CComboWizardView::OnViewComboDialog() 
 CPropertySheet sheet;
 CFirstPage firstPage;
 CLastPage lastPage;

 CComboPage	comboPage( IDD_COMBOPAGE );
 COptionAPage pageA;
 COptionBPage pageB;
 COptionCPage pageC;

 // Add the pages to the combo page
 comboPage.AddPage( &pageA, pageA.IDD );
 comboPage.AddPage( &pageB, pageB.IDD );
 comboPage.AddPage( &pageC, pageC.IDD );

 // Add the property pages to the property sheet
 sheet.AddPage( &firstPage );
 sheet.AddPage( &comboPage );
 sheet.AddPage( &lastPage );

 // Set the title of the property sheet window
 sheet.SetTitle( "Property Sheet Containing a ComboPage" );

 // Uncomment the next line to display a wizard instead.
 //	sheet.SetWizardMode();


Step 5: Process the results

If you are using the combo property page to obtain a variety of information on a single topic, such as the C/C++ tab in Visual Studio, then you will want to obtain all of the information from each of the property pages. If you need to perform this step after the call to DoModal(), then use the local variables for each property page that were created with the property sheet. If you need to perform this step in the combo page code or if you are passing the combo page to another routine to do this, you can get each property page by calling CComboPage::GetPage and specifying the index of the page to retrieve.

If you are using the combo property page to have the user select and configure a single option, then you can use the CComboPage::GetSelectedPage to get the page the user selected through the combo box. This method returns a pointer to the page and the ID of the page. For example,

CPropertyPage* pPage = comboPage.GetSelectedPage( nID );

switch ( nID )
 case pageA.IDD:
  CString string;
  COptionAPage* pOptionAPage = (COptionAPage*) pPage;
  int nRadio = pOptionAPage->m_radio;
  string.Format("You selected option A and radio %d", 
                nRadio + 1 );
  ::AfxMessageBox( string );

 case pageB.IDD:
  ::AfxMessageBox( "You selected option B" );

 case pageC.IDD:
  ::AfxMessageBox( "You selected option C" );

Final Notes:

If you need to enable the Apply button when the data in your property page changes, calling SetModified will not work since the child property pages do not belong to the property sheet. Instead you will need to get the parent window, cast it to a property page, and then call SetModifed on the parent. For example,

void COptionAPage::OnChange() 
 CPropertyPage* pParent = (CPropertyPage*) GetParent();

You can still override the CPropertyPage methods in your derived classes. For example, OnOK will be called on every child page when the OK button is pressed. OnKillActive is called on the current page when the user changes the setting in the combo box and OnSetActive is called on the new page. UpdateData is called on any page before OnKillActive is called so you do not need to perform this step. Also when the main property page is no longer the active page, it will invoke OnKillActive on the current page. The OnWizardBack, OnWizardNext, and OnWizardFinish methods are the only other methods that are invoked only on the currently selected page.


Download demo project - 30 Kb
Download source - 4 Kb


  • dynamic dialog in a page

    Posted by Legacy on 06/11/2003 07:00am

    Originally posted by: Rafa

    Hello, I see this code and is very good, but I like to do another thing, I would like add a new page after DoModal metod  has beeb called, Is it possible to do this thing?
    The new page than I like add is into a dll.

    Thank you.

  • Using cpropertysheet as main view

    Posted by Legacy on 08/14/2002 07:00am

    Originally posted by: Warren Johnson

    I am working on a project where I need a porpertysheet as the main view in my MDI. Now i have that setup but when I try to add the combopage to it its ok but when i click on that tab it crashes. Do you have any suggestions as to what I should do? Thank you and keep up the excellent work.


  • Dynamically changing titles

    Posted by Legacy on 06/05/2002 07:00am

    Originally posted by: Jessica Olsen

    I want to be able to change the title that appears in the ComboBox dynamically and I am having trouble setting it.

    I have an array of structures that have names, types, and other variables. Depending on the type (there will be 5) I want to change the contents of the property page. I think that I can get that to work, but I cant get the name to appear in the combo box. The problem is that I will only have 5 possible pages because of the types, but I have the possiblity of 50 different elements with unique names that must be selected individually.

    What I have so far is:
    CMyPropertySheet propSheet;
    CComboPage* firstPage=new CComboPage(IDD_PROPPAGE1);
    CIntPg* IntPg=new CIntPg;//Will eventually be an array
    CIntPg* IntPg2=new CIntPg;

    IntPg->m_psp.dwFlags |= PSP_USETITLE
    IntPg->m_psp.pszTitle=_T("My Caption");



    All the IntPg->m_psp.pszTitle=_T("My Caption") stuff works if I have this as a regular property page, but once I add it to the ComboPage it always shows the regular caption instead of the one that I changed it to. Any help is appreciated.

  • Having trouble using this with a RichEdit 2.0 Control

    Posted by Legacy on 12/30/2001 08:00am

    Originally posted by: Steve Horowitz

    Have been able to implement fine (and thanks). However when I add a RichEdit 2.0 Control on one of the "sub" property pages based on the combo box I get an assertion on the AddString line from the OnInitDialog - take off the control and everything works again. By the way the string variable is blank for some reason when it asserts.

    // Add this page's caption to the combo box
    pPage->GetWindowText( string );
    pCombo->AddString( string );

    Also, another question. Is there a way to add more than just the combo box (IDC_COMBOPAGE_COMBO) to the main property page for stuff that may be common to each of the
    "sub" property pages so you don't have to repeat them on each one? When I did it, I could not override the OnInitDialog and therefore could not preload my controls with information.



  • Excellent job

    Posted by Legacy on 12/01/2001 08:00am

    Originally posted by: Herbert Griebel

    Thank you very much for the cool class. Could easly use it!
    Is there any simple method to prevent flickering when changing the page?

    Herbert Griebel

  • multiple dynamic property sheets

    Posted by Legacy on 07/17/2001 07:00am

    Originally posted by: Jess

    how would you make a dynamic page the child of another dynamic page? i am running into problems with the "SecondPage.AddPage(&Option2,Option2.IDD)" line, if I try to make the Option2 into a dynamic page, it will not allow it. It says that IDD is not a member of CComboPage. Is there an easier way to get around this problem?

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

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