Click here to Skip to main content
Click here to Skip to main content

CTreePropSheet - A Netscape/Visual Studio .NET like Preferences Dialog

, 6 Mar 2003
Rate this:
Please Sign up or sign in to vote.
This framework introduces a property sheet, based on the original Windows property sheet (derived from CPropertySheet) which uses a tree control to browse the pages instead of a tab control
<!-- Add the rest of your HTML here -->

Content

  1. Introduction
    1. What's This?
    2. Why another One?
    3. Features
  2. Using CTreePropSheet
  3. Customizing CTreePropSheet
    1. Basics
    2. Advanced
      1. Page Frame and Caption
      2. Page Tree
      3. Empty Page Messages
  4. Reference
  5. Requirements
  6. Unicode Support
  7. Implementation Details
  8. Revision History

Windows 2000 screenshot Windows XP - Luna - screenshot Windows XP - Aqua - screenshot

Introduction

Using the normal property sheet provided by Windows is hard for the user, especially if the sheet contains a lot of pages. In this case, most sheets would provide a multi tab-rows and each time you click on a tab, that's not in the bottom-most row, the order of the rows will change. In other cases the sheet may provide only a single line of tabs, you can scroll through using tiny arrow buttons. Both solutions are not very comfortable to the user.

What's This?

This is where CTreePropSheet comes in: Instead of using tabs, this property sheet provides a tree control, that allows the user to select a page of the sheet. This also allows the developer to group several pages. A group will be displayed to the user as a tree item with some childs (the pages of the group).

This concept is already in use by several products for setting up the preferences. The most famous may be Netscape/Mozilla and Visual Studio .NET.

Why another One?

There are already classes, which are implementing dialogs, like the one described above (i.e. see SAPrefs - Netscape-like Preferences Dialog). But the CTreePropSheet is a special implementation: Instead of implementing a new preferences dialog up from the scratch, CTreePropSheet is based on the original Windows property sheet, which brings up several advantages:

  • Based on well tested codes
  • We get all the features of the original property sheet for free
  • Adding pages by their HPROPSHEETPAGE-handles, which is usefull for applications providing a plug-in-mechanism.
  • And the best: Its derived from the class CPropertySheet and using CPropertyPage-objects as pages, so that you can use your common code with only minimal changes.

Features

Because CTreePropSheet is based on the original property sheet, you get all the features, which are available with this common dialog, including:

  • Automatic resizing regarding the largest page
  • Support for 'OK'-, 'Cancel'-, 'Apply'- and 'Help'-Buttons
  • Page icons

Additionally CTreePropSheet introduces the following features:

  • Grouping pages into logical categories
  • Default text for root pages of a group
  • Default icons for root pages and child pages
  • Some helper functions to make setting icons for pages easier
  • Possibilities for customizing the look and feel
  • Full Windows XP theme support (looks good on themed and non-themed systems)

Using CTreePropSheet

This section won't describe all the basic stuff, because you will find this in the description of CPropertySheet in the MFC-documentation. This section will only describe the advanced features. This is also a tutorial like description of the functionality. A full reference is also available.

Using CTreePropSheet is in the first step identically to using the MFC-class CPropertySheet:

  1. Create some CPropertyPage (or derived classes) objects and modify there names, to group them together (see below).
  2. Create a CTreePropSheet object.
  3. Add the CPropertyPage objects to the CTreePropSheet object using the CTreePropSheet::AddPage() method.
  4. Modify the style of the property sheet using the methods described in the customization section.
  5. Call CTreePropSheet::DoModal() to display the property sheet as a modal dialog or CTreePropSheet::Create() to get a non-modal sheet.

If you only want to modify an existing application, so that it uses the CTreePropSheet class instead of the CPropertySheetClass, then simply follow these steps:

  1. Replace all occurences of CPropertySheet by CTreePropSheet.
  2. Change the names of the pages, to group them together (see below).

That's it!

To group pages into categories, you simply have to change the names of the property pages (the window title). The title should not only contain the name of the page now, rather it should specify the path of the page in the CTreePropSheet's page tree. The string "::" is used as path separator here. In example the sample application (see screenshot at the top of this page) has five pages which are named:

  1. Server::Outgoing
  2. Server::Incoming
  3. Message Format::View
  4. Message Format::Composition
  5. Appearance

The root items "Server" and "Message Format" and the related pages are generated automatically by the CTreePropSheet class, if you do not add pages with those paths explicitly. You can set the text, that should be displayed for those implicit root pages by using the CTreePropSheet::SetEmptyPageText() method.

To get pages, which contain the string "::" in there visible name, you simply have to prefix the double colon with a backslash ("\\::").

Customizing CTreePropSheet

This section gives a short overview of the possibilities, to change the look & feel of the CTreePropSheet.

Basics

The following methods are providing possibilities for simply modifying the look and feel of your CTreePropSheet. You will find a full description of each method in the reference.

SetTreeViewMode()
Changes the following settings (only before the creation of the window):
  • Switch between classic tab- and tree-mode
  • Enable/disable the page caption in tree-mode
  • Enable/disable page icons in the page tree in tree-mode
SetTreeWidth()
Sets the width of the tree control. Default is 150 pixels.
SetEmptyPageText()
Specifies the text to display on empty pages. Empty pages are pages which are created implicitly for root items in the tree.
SetEmptyTextFormat()
Specifies the flags to use with DrawText() to draw the text on empty pages (mainly alignment specific stuff).
SetTreeDefaultImages()
Specifies images, to use for pages and empty pages, which do not have explicitly defined images. Only of interest, if images are enabled.
GetPageTreeControl()
Provides direct access to the tree control, after the dialog has been created (i.e. in OnInitDialog()) that allows you to change the tree control's styles.
SetPageIcon() and DestroyPageIcon()
Static helpers, for defining icons for a page and destroying them, when they are no longer needed.

Advanced

The CTreePropSheet class also provides several advanced customization mechanisms, which are provided by overriding virtual methods.

Page Frame and Caption

You can see in the screen shots, that CTreePropSheet already comes with support for Windows XP themes, which is mainly important for the background and frame of the property pages: On non-themed systems (like Windows 2000) or when themes are deactivated, property pages are normaly painted in another way, than the sheet background. This requires the sheet to draw a frame around the page. This frame is normally provided by the tab control, but because we are not using a tab control, we have to draw the frame by ourselves, if one is needed.

This frame is drawn by an object of a CPropPageFrame derived class, which is created in CTreePropSheet::CreatePageFrame(). The default implementation of this method creates a CPropPageFrameDefault object, which detects wheter theming is enabled or not and performs the appropriate drawing, using the Windows XP theme library if necessary. This object is also responsible for drawing the page caption, if this feature is enabled (SetTreeViewMode()).

You can provide your own drawing mechanisms for frame and caption, by overriding the CreatePageFrame() method in a derived class of CTreePropSheet and create an object of your own CPropPageFrame-derived class.

Page Tree

Most part of modifications to the page tree can be done by using the GetPageTreeControl() method, to get a pointer to the CTreeCtrl and modify its style. If you would like to inject your own tree control, you can override the virtual CreatePageTreeObject() method in your derived class and create an object of your own class instead of the default CTreeCtrl.

Empty Page Messages

If you would like to customize the empty page messages, generated by the sheet, you can override the virtual GenerateEmptyPageMessage()-method.

Reference

You will find a reference of the complete CTreePropSheet-framework in the header file of the source code. You can generate HTML, HtmlHelp or LaTeX-documentation (and accordingly PDF documentation) from the source files using the help extraction tool doxygen.

Requirements

This should run on Windows 95 or later and on Windows NT 4.0 or later, though I only have tested it on Windows 98, Windows 2000 and Windows XP.

If you detect problems on one or more of the listed platforms, please let me know.

For compilation you will need Visual C++ 6.0 or 7.0 and the May 2002 Platform SDK. (If you don't have this SDK installed, you can undefine the XPSUPPORT macro in the file PropPageFrameDefault.cpp (comment line 30) and it should also work.)

Unicode Support

Though I haven't tested it, there is no reason, why this should not work with Unicode.

Implementation Details

There is no big deal about the implementation. The most interesting part is done in the WM_INITDIALOG-handler (OnInitDialog). The method hides the tab control, resizes the sheet horizontally to get space for the page tree, moves all existing items to the right of the sheet and creates the tree control at the left then.

The rest of the implementation is straight forward. Simply take a look into the code. If you have questions, please post them to the comments section of this article.

Revision History

2003/02/26
  • Initial Revision
2003/02/27
  • Fix for MFC7 (thanks to Rainer Wollgarten)
  • Fix for problems with centering the window correclty, after it has been resizted in OnInitDialog() under some circumstances (thanks to Stewart Tootill).
  • Fixed a little typo.
2003/03/03
  • [Strg]+[Tab] and [Strg]+[Shift]+[Tab] shortcuts for stepping through the pages now works as expected. Some changes to the text.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Sven Wiegand
Web Developer
Germany Germany
Sven Wiegand (1976), IT professional living in Berlin (Germany), develops open source software in his free time. His most successfull project is the LaTeX IDE TeXnicCenter which is distributed under the terms of the GNU-GPL and has more than 100,000 users all about the world.
 
"The picture shows me with my racing bike on the top of the Roque de los Muchachos (2426m) - the highest point of the canarian island La Palma."

Comments and Discussions

 
BugExtra OnKillActive call PinmemberTriggle30-May-14 7:06 
QuestionUnable to add same page twice Pinmemberfelixfan81919-Feb-14 1:11 
GeneralAvailable in c#? Pinmemberjhorstkamp4-Jun-11 8:41 
QuestionWrong Icons Pinmemberdiablo2743217-Oct-10 20:26 
AnswerRe: Wrong Icons Pinmemberdiablo2743217-Oct-10 21:12 
General24/32 bit icons/bitmaps Pinmemberflector10-Feb-10 10:12 
QuestionCan someone tell me which license governs the CTreePropSheet code? Pinmemberkrista mccredie10-Aug-09 9:58 
GeneralSheet goes off the screen Pinmembercolinbr12-Jun-09 7:26 
QuestionBug in dll ? PinmemberCeli Roberto26-Feb-09 0:26 
GeneralGetActivePage seems not to work PinmemberMember 384433118-Feb-09 13:27 
QuestionProblems of pages from different dll Pinmemberlostangels18-Aug-08 6:13 
QuestionHow to change TreeItem and/or Icon dynamically? PinmemberPeggy Van Lierde28-Apr-08 7:43 
GeneralWhen we place custom control in the dialog page is not displaying PinmembercodeSreenivas22-Apr-08 6:04 
QuestionHow to change pages dynamically? Pinmemberbranogoga14-Jan-08 9:07 
QuestionLicense PinmemberMember 323216811-Dec-07 3:11 
GeneralOut of Memory error PinmemberSteve Kowald19-Jul-07 14:11 
GeneralRe: Out of Memory error PinmemberSunny R5-Nov-07 10:36 
GeneralRe: Out of Memory error Pinmemberskowald2-Jan-08 17:06 
Sunny,
 
I never did resolve this. It fails in call to ::PropertySheet().
 
From MSDN: If you attempt to add more than 99 pages to a property sheet, this function will fail,
but with no indication of the cause of the error: PropertySheet returns a value of -1, but GetLastError
returns 0.
 
http://msdn2.microsoft.com/en-us/library/bb760811.aspx
 
I decided to go another route instead of creating multiple instances of the same modeless dialog, I just create
once instance of each type that I need and then just switch between them and set the data based on the node currently selected in the tree.
 
Steve
Questionwhy do not goto OnInitDialog of child page? Pinmemberthanhthuyvn_vtajkhskjakjd29-May-07 0:34 
AnswerRe: why do not goto OnInitDialog of child page? Pinmemberhroenick19-Feb-09 3:58 
NewsFix : How to select child item when selected item has no page. Pinmemberkilojuliet27-Apr-07 12:48 
GeneralRe: Fix : How to select child item when selected item has no page. Pinmemberkenshin_x19-Jul-07 16:13 
GeneralRe: Fix : How to select child item when selected item has no page. PinmvpRajesh R Subramanian15-May-08 19:33 
Questionhow can I change the page's titles dynamically ? PinmemberciroE21-Apr-07 1:14 
AnswerRe: how can I change the page's titles dynamically ? PinmemberKenny Zhao29-Sep-07 0:02 
GeneralCan't select pages using tree view Pinmembergaryrfleming21-Feb-07 14:20 
GeneralRe: Can't select pages using tree view Pinmembergaryrfleming22-Feb-07 5:21 
QuestionHow do I get pages attached to tree items Pinmemberrickcymru21-Feb-07 12:49 
AnswerRe: How do I get pages attached to tree items Pinmembergaryrfleming21-Feb-07 13:42 
GeneralCtrl+# hack [modified] Pinmembercopernican2-Feb-07 10:16 
GeneralCtrl+F1 - No help topic is associated... Pinmembercopernican17-Nov-06 13:05 
AnswerRe: Ctrl+F1 - No help topic is associated... PinmemberTarekat16-Apr-07 6:33 
GeneralRe: Ctrl+F1 - No help topic is associated... PinmemberTarekat16-Apr-07 6:43 
GeneralRe: Ctrl+F1 - No help topic is associated... Pinmembercopernican21-May-07 10:51 
QuestionHow to get rid of the Context Help button when right-click the title PinmemberSuper Garrison27-Oct-06 11:11 
AnswerRe: How to get rid of the Context Help button when right-click the title PinmemberSteve Kowald28-Oct-06 2:38 
GeneralRe: How to get rid of the Context Help button when right-click the title PinmemberSuper Garrison1-Nov-06 8:07 
GeneralRe: How to get rid of the Context Help button when right-click the title PinmemberSteve Kowald8-Nov-06 8:54 
AnswerRe: How to get rid of the Context Help button when right-click the title Pinmembercopernican31-Oct-06 8:11 
GeneralCTreePropSheet as Child problem Pinmemberymmace18-Aug-06 4:06 
GeneralRe: CTreePropSheet as Child problem PinmemberRupella171-Sep-06 3:13 
GeneralRe: CTreePropSheet as Child problem Pinmemberymmace5-Sep-06 16:51 
GeneralRe: CTreePropSheet as Child problem PinmemberBatman90026-Sep-06 16:47 
GeneralChange Apply Button to other name Pinmemberyeawsing5-Jul-06 0:07 
AnswerRe: Change Apply Button to other name Pinmembernarkotic_ro17-Dec-08 3:17 
QuestionWhere handled &quot;Automatic Resizing&quot;? PinmemberBehzad Ebrahimi2-Apr-06 7:29 
Questionhow to dynamicly change one page's name ? Pinmemberbanbanyy9-Mar-06 2:02 
GeneralProbably a silly question... Pinmembercopernican10-Feb-06 11:32 
GeneralExpanding groups as default PinmemberSupermagle18-Jan-06 4:58 
GeneralRe: Expanding groups as default Pinmemberoooleykin16-May-06 19:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411019.1 | Last Updated 7 Mar 2003
Article Copyright 2003 by Sven Wiegand
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid