分类: C/C++
2008-08-26 23:08:07
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.
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.
There are already classes, which are implementing dialogs, like the one described above (i.e. see ). 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:
HPROPSHEETPAGE
-handles, which is usefull for applications providing a plug-in-mechanism.
CPropertySheet
and using CPropertyPage
-objects as pages, so that you can use your common code with only minimal changes. Because CTreePropSheet
is based on the original property sheet, you get all the features, which are available with this common dialog, including:
Additionally CTreePropSheet
introduces the following features:
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 is also available.
Using CTreePropSheet
is in the first step identically to using the MFC-class CPropertySheet
:
CPropertyPage
(or derived classes) objects and modify there names, to group them together (see below).
CTreePropSheet
object.
CPropertyPage
objects to the CTreePropSheet
object using the CTreePropSheet::AddPage()
method.
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:
CPropertySheet
by CTreePropSheet
.
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:
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 ("\\::").
This section gives a short overview of the possibilities, to change the look & feel of the CTreePropSheet
.
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 .
SetTreeViewMode()
SetTreeWidth()
SetEmptyPageText()
SetEmptyTextFormat()
DrawText()
to draw the text on empty pages (mainly alignment specific stuff).
SetTreeDefaultImages()
GetPageTreeControl()
OnInitDialog()
) that allows you to change the tree control's styles.
SetPageIcon()
and DestroyPageIcon()
The CTreePropSheet
class also provides several advanced customization mechanisms, which are provided by overriding virtual methods.
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.
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
.
If you would like to customize the empty page messages, generated by the sheet, you can override the virtual GenerateEmptyPageMessage()
-method.
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 .
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.)
Though I haven't tested it, there is no reason, why this should not work with Unicode.
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.
2003/02/26 |
|
2003/02/27 |
|
2003/03/03 |
|