XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop

By Hans Dietrich

XHtmlTree is an MFC control based on CTreeCtrl, with support for HTML text, web links, APP: links, XML load/save, Smart Checkboxes, and Drag & Drop.

  • Download demo project - 501.13 KB
screenshot
Winner August 2007
Monthly Competition

Introduction

Everyone is familiar with tree controls: every time you open Windows Explorer, you see file system hierarchy as a tree. Another kind of tree is used by some programs, such as installers, to allow you to select options to install. When all options of a particular subtree are selected, you will see checkbox with a check mark (screenshot); when no options in a subtree are selected, the checkbox next to the subtree root displays an unchecked checkbox (screenshot); and when only some of the options in a subtree are selected, you will see what is known as tri-state checkbox (screenshot).

Surprisingly, there is no direct support for tri-state checkboxes in MFC's CTreeCtrl. The closest you can get is to create a tri-state image list for your tree. While this will work, it does not give you the complete visual effect of XP themed checkboxes, such as hot-state appearance (screenshot) when the mouse is hovering.

While I was researching tree controls and how to add tri-state checkboxes, I came to understand that the tree control - like the list control - can be enhanced with many useful features and nice UI effects by mechanism of custom draw. This led me to take next step: adding HTML support to tree items. It was easy to see how this would be possible, since I had just completed my XHtmlDraw article.

Before long I sketched out requirements of my new tree control:

screenshot Checkboxes with theme support - I wanted notification messages sent to parent when checkbox was toggled, and full theme support; this means hover (hot) support, with checkboxes drawn exactly like themed XP checkboxes. Of course, on Vista, checkboxes should have Vista appearance:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第1张图片

screenshot Smart Checkboxes - this is a term I started using (but did not invent) to describe how checking parent item will also checkmark the children of that item - and, conversely, unchecking a child item will display parent with tri-state checkbox, if any other children are still checkmarked. Here is quick demo of how it works:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第2张图片

Of course, Smart Checkboxes are optional - you can have checkboxes without using Smart Checkboxes.

screenshot HTML - I wanted to include XHtmlDraw functionality, including support for web links and APP: links.
screenshot Enhanced tree navigation and status - reading Zafir Anjum's articles gave me ideas for improving the programmatic interface of the tree control, and I also wanted to implement better management features, like determining how many items are checked, how many children an item has, etc., and sending notification message to parent when item is expanded.
screenshot Loading and saving tree data using XML - this is a common requirement as XML is adopted in more applications.

XHtmlTree Features

To begin with, let me show you the demo app:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第3张图片

This dialog allows you to choose source of data for tree. It can be text file or XML file (files are stored as resources, see my XResFile article for details). There are two choices for each file type - one is complete list, the second is partial list with ten items in each main node, to make debugging easy.

When you click on button, here is what you see:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第4张图片

Here are main features:

  1. The Options checkboxes allow to display tree with various options that are tree-wide in scope - i.e., they affect all items.
  2. The Show Checked button displays modeless dialog that shows list of currently checked items:

    XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第5张图片
    Image has been reduced in size.

    To refresh list, just click button again.

  3. The Find button displays Find dialog:

    XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第6张图片

    This dialog uses built-in CXHtmlTree::FindItem() function to search for item text. An option on dialog lets you checkmark all matching items, which you can observe using Show Checked dialog.

  4. The Colors button displays Colors dialog:

    XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第7张图片

    Note that background color will be set as background of the entire tree control (via SetBkColor()). However, individual items can have their backgrounds set independently of this, either by using SetItemTextBkColor(), or by using HTML:

    XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第8张图片

  5. These are indicators of scrolling speed for drag & drop scrolling.
  6. These are three buttons that allow you to toggle checkmark of all items, expand all items, and collapse all items.
  7. The tree control shows one item checkmarked. Note that its parent (Collies) is shown with tri-state checkmark, indicating one of its children - but not all - is checked. Its parent (Herding Dogs) also has tri-state checkmark.
  8. The edit box contains item text, which you can modify, and then use Update button to write new text to tree item.
  9. The Tree Info displays information about entire tree.
  10. The Item Info displays information about an item - either the currently selected item, or item that was just expanded.
  11. Tree breadcrumb trail is displayed by using GetItemPath() function and XBreadCrumbBar. When you click on active breadcrumb, that tree node will be selected.
  12. The Log displays information when notification messages (TVN_SELCHANGED, WM_XHTMLTREE_CHECKBOX_CLICKED, and WM_XHTMLTREE_ITEM_EXPANDED) are received from control. You can enable or disable the Log with checkbox.

Implementation Notes

HTML

To see full list of supported HTML tags, including how to use web links and APP: links, please refer to my XHtmlDraw article.

Colors and Text Attributes

The following functions support item and tree colors and text attributes:

Function Applies To Description
COLORREF GetBkColor() tree control Get current background color for tree
BOOL GetItemBold(HTREEITEM hItem) item Get item bold state (TRUE = item is bold)
COLORREF GetItemTextBkColor(HTREEITEM hItem) item Get item background color for text
COLORREF GetItemTextColor(HTREEITEM hItem) item Get item text color
LOGFONT * GetLogfont() tree control Get pointer to current LOGFONT
COLORREF GetTextColor() tree control Get current text color for tree
BOOL GetUseLogfont() tree control Get current state of LOGFONT (TRUE = use specified LOGFONT
COLORREF SetBkColor(COLORREF rgb) tree control Set tree background color
BOOL SetItemBold(HTREEITEM hItem, BOOL bBold) item Set bold state for item
COLORREF SetItemTextBkColor(HTREEITEM hItem, COLORREF rgb) item Set background color for item text
COLORREF SetItemTextColor(HTREEITEM hItem, COLORREF rgb) item Set text color for item
CXHtmlTree& SetLogfont(LOGFONT * pLogFont) tree control Set new LOGFONT for tree
COLORREF SetTextColor(COLORREF rgb) tree control Set text color for tree
CXHtmlTree& SetUseLogfont(BOOL bFlag) tree control Set flag to indicate whether LOGFONT struct should be used (TRUE = use LOGFONT)

Checkboxes

You can enable checkboxes for tree (using SetHasCheckBoxes()) independently of enabling Smart Checkboxes (using SetSmartCheckBox()). When checkboxes are enabled, an internal state image list is created for various checkbox states. This creation is performed in CreateCheckboxImageList() (see CreateCheckboxImageList.cpp). For each possible state, a bitmap is created (using David Zhao's excellent CVisualStylesXP class), for both cold and hot states. Obviously this implies modal processing, but since I can use CTreeCtrl::SetItemState(), keeping track of item state is not too complicated. Furthermore, I have designed image list so that common state transitions are simple. In following table, you can see that going from "cold" state to "hot" state involves OR'ing with 8, and going from "normal" state to "disabled" state involves OR'ing with 4.

XHtmlTree Checkbox States

Cold Hot
Normal Disabled Normal Disabled
Unchecked 0001 0101 1001 1101
Checked 0010 0110 1010 1110
Tri-state 0011 0111 1011 1111

Here are functions implemented to support XHtmlTree checkboxes:

Function Description
void CheckAll(BOOL bCheck) Sets the checkbox for all items to the bCheck state
BOOL GetCheck(HTREEITEM hItem) Returns TRUE if item is checked. Returns FALSE if item is not checked, or is in tri-state.
int GetCheckedCount() Returns total count of checked items in tree
int GetChildrenCheckedCount(HTREEITEM hItem) Returns checked count for children
HTREEITEM GetFirstCheckedItem() Returns first checked item, or NULL
BOOL GetHasCheckBoxes() Returns TRUE if tree has checkboxes
HTREEITEM GetNextCheckedItem(HTREEITEM hItem) Returns next checked item, or NULL
HTREEITEM GetPrevCheckedItem(HTREEITEM hItem) Returns previous checked item, or NULL
BOOL GetSelectFollowsCheck() Returns TRUE if checking an item will also cause it to be selected
BOOL GetSmartCheckBox() Return TRUE if Smart Checkboxes are enabled
BOOL IsChecked(HTREEITEM hItem) Returns TRUE if item is checked. Returns FALSE if item is not checked, or is in tri-state.
CXHtmlTree& SetCheck(HTREEITEM hItem, BOOL fCheck = TRUE) Sets item checked state to fCheck
CXHtmlTree& SetCheckChildren(HTREEITEM hItem, BOOL fCheck) Sets checked state of children to fCheck
CXHtmlTree& SetHasCheckBoxes(BOOL bHasCheckBoxes) Enable checkboxes for tree if bHasCheckBoxes is TRUE
CXHtmlTree& SetSelectFollowsCheck(BOOL bFlag) If bFlag is TRUE, checking an item will also cause it to be selected
CXHtmlTree& SetSmartCheckBox(BOOL bFlag) Enable Smart Checkboxes if bFlag is TRUE

Keyboard Shortcuts

XHtmlTree supports standard Windows keyboard navigation techniques:

Key Description
Down and Up Arrow Keys Moves selection to next/previous item; no expand
Right Arrow Key Expands the current selected item (if it is collapsed), selects the first child item
Left Arrow Key Collapses the current selected item (if it is expanded), selects the parent item
Page Down Moves selection to last item in tree window; pages items as necessary
Page Up Moves selection to first item in tree window; pages items as necessary
Ctrl+Page Down Scrolls to last item in tree window; pages items as necessary; selection is not changed
Ctrl+Page Up Scrolls to first item in tree window; pages items as necessary; selection is not changed
Backspace Moves selection to parent item
End Moves selection to last item; no expand
Home Moves selection to first item; no expand
Ctrl+End Scrolls to last; selection is not changed, no expand
Ctrl+Home Scrolls to first; selection is not changed, no expand
Asterisk (*) on numeric keypad Expands all items under the selected item
Plus Sign (+) on numeric keypad Expands the selected item
Minus Sign (-) on numeric keypad Collapses the selected item

Tree Navigation and Management

Here are functions implemented to support XHtmlTree navigation:

Function Description
HTREEITEM GetLastItem(HTREEITEM hItem) Retrieve the last item in the tree
HTREEITEM GetNextCheckedItem(HTREEITEM hItem) Retrieve the next item that is checked
HTREEITEM GetNextItem(HTREEITEM hItem) Retrieve the next item in the tree. This traverses the tree top-to-bottom, just like the tree appears visually when it is fully expanded.
HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) Retrieve the item that has the specified relationship, indicated by the nCode parameter, to hItem
HTREEITEM GetPrevCheckedItem(HTREEITEM hItem) Retrieve the previous item that is checked
HTREEITEM GetPrevItem(HTREEITEM hItem) Retrieve the previous item in the tree. This traverses the tree top-to-bottom, just like the tree appears visually when it is fully expanded.

Initializing the Tree

It is easy to initialize XHtmlTree in one statement:

minus.gif Collapse
    m_Tree.Initialize(m_bCheckBoxes, TRUE)
.SetSmartCheckBox(m_bSmartCheckBoxes)
.SetHtml(m_bHtml)
.SetStripHtml(m_bStripHtml)
.SetImages(m_bImages);

Tooltips

XHtmlTree supports standard tooltips via CToolTipCtrl, and also supports HTML tooltips, displayed with Eugene Pustovoyt's excellent CPPToolTip class. Here is example of how HTML tooltips can be used:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第9张图片

Here is HTML used for this tooltip:

Golden Retriever












The Golden Retriever is a popular breed of dog, originally developed to retrieve game during hunting. It is one of the most common family dogs as it is naturally very friendly and amenable to training.

This is all standard HTML, except for the , which specifies bitmap to be read from resource id 133.

OK, so where is HTML coming from, since it is obviously not the item text? XHtmlTree provides a new SetItemNote() function, which attaches optional note text to an item. The note text (when it exists) is used instead of item text for tooltips. This is true for both standard tooltips and HTML tooltips. However, keep in mind that standard tooltips have hard limit of 80 characters.

To enable HTML tooltips, make sure this line in XHtmlTree.h is not commented out: #define XHTMLTOOLTIPS

If you include HTML tooltips, you must include additional files in your project - see How To Use section below for details.

One final point about tooltips: you have option of dynamically changing a tooltip when it is about to be displayed. A notification message (WM_XHTMLTREE_DISPLAY_TOOLTIP - see Notification Messages below) gives you chance to use SetItemNote() right before tooltip is displayed. To give example, in XHtmlTreeTestDlg.cpp, you will see this code (condensed here):

minus.gif Collapse
LRESULT CXHtmlTreeTestDlg::OnDisplayTreeToolTip(WPARAM wParam, LPARAM)
{
XHTMLTREEMSGDATA *pData = (XHTMLTREEMSGDATA *)wParam;
HTREEITEM hItem = pData->hItem;
CString strText = m_Tree.GetItemText(hItem);

// check if this is 'Galgo Español (Spanish Greyhound)'
if (_tcsncmp(strText, _T("Galgo"), 5) == 0)
{
// set new note for this item --
// zero tip width will use default width
m_Tree.SetItemNote(hItem,
_T("This is alternate text. ")
_T("For standard tooltip, it is limited to 80 characters."),
0);
}

return 0; // return 0 to allow tooltip to be displayed,
// 1 to prevent display
}

In the demo app, this is what you will see:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第10张图片

Notification Messages

For all notification messages, the wParam parameter is pointer to XHTMLTREEMSGDATA struct:

minus.gif Collapse
struct XHTMLTREEMSGDATA
{
HWND hCtrl; // hwnd of XHtmlTree
UINT nCtrlId; // id of XHtmlTree
HTREEITEM hItem; // current item
};

The lParam parameter depends on specific message. The following messages are sent to XHtmlTree parent:

Message Description lParam
WM_XHTMLTREE_CHECKBOX_CLICKED Sent when a checkbox is clicked New checkbox state (TRUE = checked)
WM_XHTMLTREE_DISPLAY_TOOLTIP Sent when a tooltip is about to be displayed Pointer to tooltip control (CToolTipCtrl or CPPToolTip)
WM_XHTMLTREE_INIT_TOOLTIP Sent when tooltip control is being initialized Pointer to tooltip control (CToolTipCtrl or CPPToolTip)
WM_XHTMLTREE_ITEM_EXPANDED Sent when an item has been expanded or collapsed New item state (TRUE = expanded)

Drag & Drop

Starting with version 1.4, XHtmlTree supports drag & drop. The following drag & drop facilities and operations are implemented:

  1. There is new compile-time symbol to enable inclusion of drag & drop code:
    minus.gif Collapse
        #define XHTMLDRAGDROP
    Defining (or not defining) this symbol also takes care of setting TVS_DISABLEDRAGDROP style correctly.
  2. Drag & drop is implemented using CTreeCtrl::SetInsertMark() API. This is what is used, for example, for FireFox bookmarks. As an item is being dragged, what you will see is a solid thin bar - called the insert mark - that is displayed between items in the tree. The insert mark indicates where item will be inserted into the tree if it is dropped.
  3. By design, traditional OLE-style drag image animation has not been implemented, and there are no current plans to do so.
  4. In addition to display of insert mark, you have option of displaying (via SetDropCursors() function) three custom cursors: the no-drop cursor, the drop move cursor, and the drop copy cursor. The demo app includes examples of each:

    Cursor Demo Image Description
    No drop screenshot Used to indicate a no-drop zone; either an area outside the tree control, or an item that is not an allowed drop target.
    Drop Move screenshot Used to indicate the dragged item will be moved when left mouse button is released.
    Drop Copy screenshot Used to indicate the dragged item will be copied when left mouse button is released.
  5. Drop Copy vs. Drop Move - There are several ways to control whether dragged item will be copied or moved:

    screenshot The user can use Ctrl key to toggle between copy and move, before or during drag.
    screenshot The application can control whether Ctrl key is recognized by setting/resetting XHTMLTREE_DO_CTRL_KEY drag operations flag.
    screenshot The application can change default behavior of Ctrl key by setting/resetting XHTMLTREE_DO_COPY_DRAG drag operations flag.
  6. The application can control each stage of a drag by handling following notification messages:

    screenshot WM_XHTMLTREE_BEGIN_DRAG - This message is sent when a drag is initiated, and includes the dragged item and the state of the XHTMLTREE_DO_COPY_DRAG flag bit. Note that in demo app, attempting to drag Longdog in Sight Hounds group will be rejected (see demo Log).
    screenshot WM_XHTMLTREE_END_DRAG - This message is sent when a drag is terminated, either by a drop or by other user action (such as hitting the ESC key, right-clicking the mouse, dropping an item back onto itself, or dropping outside tree control). If the drag ends because of a drop on a valid tree item (other than itself), this message will include the proposed drop target. If the drop terminates for any other reason, a value of 0 will be sent as lParam parameter. Note that in demo app, dropping on Longdog in Sight Hounds group will be rejected (see demo Log).
    screenshot WM_XHTMLTREE_DROP_HOVER - This message is sent when the cursor is over a tree item, and includes the tree item that could be a drop target, Note that in demo app, hovering over Longdog in Sight Hounds group will display a "no-drop" cursor.

    For all above messages, a pointer to XHTMLTREEDRAGMSGDATA struct is sent as lParam parameter (this might be NULL in the case of WM_XHTMLTREE_END_DRAG message).

    minus.gif Collapse
    struct XHTMLTREEDRAGMSGDATA
    {
    HTREEITEM hItem; // item being dragged
    HTREEITEM hNewParent; // proposed new parent
    HTREEITEM hAfter; // drop target - item being dragged will
    // either sequentially follow this item,
    // or hAfter specifies the relationship
    // (TVI_FIRST, TVI_LAST, etc.) the
    // dragged item will have with hNewParent.
    // Note that TVI_xxxx constants are all
    // defined as 0xFFFFnnnn, with the 16
    // high-order bits set.
    BOOL bCopyDrag; // TRUE = dropped item will be copied;
    // FALSE = dropped item will be moved
    };

    The application may respond to these messages with either FALSE (indicating that proposed action may continue), or TRUE, indicating that proposed action is not permitted. When sent in response to WM_XHTMLTREE_BEGIN_DRAG and WM_XHTMLTREE_END_DRAG messages, a return code of TRUE will terminate drag. When sent in response to WM_XHTMLTREE_DROP_HOVER message, a return code of TRUE will cause the no-drop cursor to be displayed.

    Since the default return code - in the absence of a message handler - is 0 or FALSE, it is not necessary to implement handlers for any of these messages in order to enable drag & drop.

  7. By default, during a drag the tree will auto-scroll when cursor approaches top or bottom of control. The tree scrolls at three different speeds, depending on how close the cursor is to the edge. In addition, the application can select one of two overall speed settings - normal or fast - and can also completely disable drag scrolling. Drag scrolling is controlled by drag operations flags XHTMLTREE_DO_SCROLL_NORMAL and XHTMLTREE_DO_SCROLL_FAST. If both of these flag bits are 0, no scrolling will occur.
  8. By default, during drag the tree will auto-expand a node when cursor hovers over it. This behavior may be disabled with drag operations flag bit XHTMLTREE_DO_AUTO_EXPAND.
  9. By using SetInsertMark() API in conjunction with auto-expand, the user may drop an item (or branch) after any existing node. However, these two mechanisms do not allow for drop-under, where the drop results in creation of a child item. To accommodate this, the user may use Shift key before or during drag. Holding down Shift key causes drop to become drop-under: the insert mark is removed, and instead the drop target (the proposed new parent) is highlighted. This behavior may be disabled with drag operations flag bit XHTMLTREE_DO_SHIFT_KEY.
  10. Drag operations involving disabled or read-only items are not explicitly disallowed by XHtmlTree. If you want to prevent dragging of disabled or read-only items, you should set up handler for WM_XHTMLTREE_BEGIN_DRAG message. See XHtmlTreeTestDlg.cpp for example.
  11. There is known problem that when Ctrl key is down, the ESC key will not terminate drag.

Separators

screenshot
Starting with version 1.6, XHtmlTree supports item separators. Separators are simply visual indicators that are meant to set apart or divide tree items. In the following screenshot, the three "Australian" dogs are enclosed in two separators:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第11张图片

To try out separators yourself, you can use right-click menu in demo app:

XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第12张图片

The following separator facilities and operations are implemented:

  1. The function InsertSeparator() inserts a separator after the specified item. There is no limit on the number of separators.
  2. The function IsSeparator() allows you to test whether a tree item is separator.
  3. You can change the color of individual separators by using SetItemTextColor(), or you can use SetSeparatorColor() to change the color of all separators. The default separator color is that returned by GetSysColor(COLOR_GRAYTEXT).
  4. Separators can be selected just like any other tree item.
  5. Separators can be dragged just like any other tree item.
  6. Separators cannot have text.
  7. Separators cannot have children. Attempting to drop an item on a separator will always cause item to be inserted after separator ("drop under" is not allowed). However, it is allowed to drop a separator under a non-separator item.
  8. Separators cannot be edited via TVN_BEGINLABELEDIT.
  9. Separators are included in count of children, but have no effect on Smart Checkboxes.
  10. You can specify separators to be loaded from XML file by using attribute separator=1.

How To Use

To integrate XHtmlTree into your own app, you first need to add following files to your project:

  • CreateCheckboxImageList.cpp
  • CreateCheckboxImageList.h
  • VisualStylesXP.cpp
  • VisualStylesXP.h
  • XHtmlDraw.cpp
  • XHtmlDraw.h
  • XHtmlDrawLink.cpp
  • XHtmlDrawLink.h
  • XHtmlTree.cpp
  • XHtmlTree.h
  • XNamedColors.cpp
  • XNamedColors.h
  • XString.cpp
  • XString.h

Files marked with must be set in Visual Studio to Not Using Precompiled headers.

If you want to use HTML tooltips, then you must also include these files:

  • CeXDib.cpp
  • CeXDib.h
  • PPDrawManager.cpp
  • PPDrawManager.h
  • PPHtmlDrawer.cpp
  • PPHtmlDrawer.h
  • PPTooltip.cpp
  • PPTooltip.h

And finally, if you want to include XML functions, then you must include these two files:

  • XmlDocument.cpp
  • XmlDocument.h

Then declare variable for CTreeCtrl object, and change its type to CXHtmlTree:

minus.gif Collapse
    CXHtmlTree    m_Tree;

Now you are ready to use CXHtmlTree in your project.

XHtmlTree Compile-time Options

There are three compile-time options that control what XHtmlTree features are included. These options may be selected by editing XHtmlTree.h, by including them as #define statements (for example, in stdafx.h), or by defining them via IDE (in VS2005, go to Project | Properties | Configuration Properties | C/C++ | Preprocessor | Preprocessor Definitions; be sure to do this for All Configurations).

  • XHTMLHTML - when defined, this option will enable use of HTML in tree items.
  • XHTMLTOOLTIPS - when defined, this option will enable use of HTML tooltips.
  • XHTMLXML - when defined, this option will enable loading/saving XML data.
  • XHTMLDRAGDROP - when defined, this option will enable drag & drop.

The following table shows what source modules need to be included for each compile-time option (including the case where no options are selected, which is what is used in MinDialog demo):

XHtmlTree Compile-time Options
Source Module None XHTMLHTML XHTMLTOOLTIPS XHTMLXML
CeXDib.cpp

blank1.png

blank1.png

check1.png

blank1.png

CeXDib.h

blank2.png

blank2.png

check2.png

blank2.png

CreateCheckboxImageList.cpp

check1.png

check1.png

check1.png

check1.png

CreateCheckboxImageList.h

check2.png

check2.png

check2.png

check2.png

PPDrawManager.cpp

blank1.png

blank1.png

check1.png

blank1.png

PPDrawManager.h

blank2.png

blank2.png

check2.png

blank2.png

PPHtmlDrawer.cpp

blank1.png

blank1.png

check1.png

blank1.png

PPHtmlDrawer.h

blank2.png

blank2.png

check2.png

blank2.png

PPTooltip.cpp

blank1.png

blank1.png

check1.png

blank1.png

PPTooltip.h

blank2.png

blank2.png

check2.png

blank2.png

VisualStylesXP.cpp

check1.png

check1.png

check1.png

check1.png

VisualStylesXP.h

check2.png

check2.png

check2.png

check2.png

XHtmlDraw.cpp

blank1.png

check1.png

blank1.png

blank1.png

XHtmlDraw.h

check2.png

check2.png

check2.png

check2.png

XHtmlDrawLink.cpp

blank1.png

check1.png

blank1.png

blank1.png

XHtmlDrawLink.h

blank2.png

check2.png

blank2.png

blank2.png

XHtmlTree.cpp

check1.png

check1.png

check1.png

check1.png

XHtmlTree.h

check2.png

check2.png

check2.png

check2.png

XmlDocument.cpp

blank1.png

blank1.png

blank1.png

check1.png

XmlDocument.h

blank2.png

blank2.png

blank2.png

check2.png

XNamedColors.cpp

check1.png

check1.png

check1.png

check1.png

XNamedColors.h

check2.png

check2.png

check2.png

check2.png

XString.cpp

check1.png

check1.png

check1.png

check1.png

XString.h

check2.png

check2.png

check2.png

check2.png

Files marked with must be set in Visual Studio to Not Using Precompiled headers.

The files needed for drag & drop (XHTMLDRAGDROP) are the same ones listed under None.

Using XML

You can load tree the way you are currently doing it, or - if you define XHTMLXML in XHtmlTree.h - you can use LoadXmlFromXXXX functions - see XHtmlTreeTestDlg.cpp for example. The XML parser used by XHtmlTree is extremely simple, and does not perform any strict error checking. In this condensed snippet of XML from dogs.xml, note that HTML tags must be escaped with character entities:
XHtmlTree - Tree control with support for HTML, XML, Smart Checkboxes, and Drag & Drop_第13张图片
Click to enlarge.

Here are attribute names expected by LoadXmlFromXXXX functions:

  • name - this is the item text that will be inserted in the tree. It can include HTML formatting.
  • checked - gives the item an initial checked state (if "1") or unchecked state ("0"). Default is unchecked.
  • enabled - gives the item an initial enabled state (if "1") or unchecked state ("0"). Default is enabled.
  • separator - specifies that item is separator (if "1") or not a separator ("0"). Default is not a separator.
  • image - associates image from image list with item. Use SetImageList() to set the image list.
  • text-color - text color of item; overrides the global tree text color.
  • text-background-color - text background color of item; overrides the global tree text background color.
  • note-width - tooltip width for this item. Default of 0 means that a heuristic will be used to determine appropriate width.
  • note - this text will be displayed instead of the standard tooltip text. This can include HTML tags, if XHTMLTOOLTIPS has been defined (see XHtmlTree.h).

You can load XML from a resource, a file, or a memory buffer, and you can save XML to a file.

Here are functions implemented to support XML:

Function Description
BOOL ConvertBuffer(const BYTE * inbuf, DWORD inlen, BYTE ** outbuf, DWORD& outlen, ConvertAction eConvertAction = NoConvertAction) Convert XML buffer to/from Unicode
CString GetXmlText(HTREEITEM hItem, LPCTSTR lpszElem) Retrieve the XML for item
BOOL LoadXmlFromBuffer(const BYTE * pBuf, DWORD len, ConvertAction eConvertAction) Loads XML from memory buffer
BOOL LoadXmlFromFile(LPCTSTR lpszFile, ConvertAction eConvertAction) Loads XML from file
BOOL LoadXmlFromResource(HINSTANCE hInstance, LPCTSTR lpszResId, LPCTSTR lpszResType, ConvertAction eConvertAction) Loads XML from resource
BOOL SaveXml(HTREEITEM hItem, LPCTSTR lpszFileName, BOOL bSaveAsUTF16) Saves XML to file

References

Here are links I have mentioned in this article. I have also included links to my articles on CodeProject, which I have used in demo app.

  • Tree Control Drag-and-Drop Operations from MSDN
  • Customizing a Control's Appearance Using Custom Draw from MSDN
  • Tree control articles by Zafir Anjum
  • CTreeComboBox: A Multiline Tree Combo Box that supports XML by John Melas. This article contains the CXmlDocument class that I use in XHtmlTree.
  • Add XP Visual Style Support to OWNERDRAW Controls by David Y. Zhao. I use this to create the checkbox bitmaps.
  • CPPToolTip by Eugene Pustovoyt. I use this class for the HTML tooltips.
  • XBreadCrumbBar - Draw breadcrumb trail with hyperlinks and HTML
  • XColourPicker - yet another colour picker control
  • XEditPrompt - CEdit-derived control with web-like prompt
  • XGlyphButton - a simple image button control
  • XHtmlDraw - Draw text with HTML tags and anchor links - I use this to draw tree items that contain HTML formatting.
  • XHyperLink - yet another hyperlink control
  • XListBox - Owner-draw CListBox with selectable text and background colors
  • XResFile - Files stored in resources: Part 1 - Text and Binary
  • XString - non-MFC non-STL string functions

Revision History

Version 1.6 - 2007 December 19

  • Added support for separators.
  • Fixed bug with multiple roots - dropping a root node always created child node instead of root node.
  • Added multiple-root sample to demo app.

Version 1.5 - 2007 November 7

  • Fixed bug with XML input (crash if no image list); reported by Berni Slootbeek.
  • Updated to XHtmlDraw v1.2.

Version 1.4 - 2007 November 4

  • Added support for drag & drop, suggested by David McMinn. Thanks for your help, David!

Version 1.3 - 2007 October 16

  • Added demo project for "minimum dialog". This project shows how to use XHtmlTree with Smart Checkboxes, but without HTML, XML, or HTML tooltips. This reduces size of executable by about 130Kb.

Version 1.2 - 2007 October 14

  • Tweaked display performance.
  • Minor changes to demo app.
  • Added handler for WM_CONTEXTMENU to demo app.
  • Added CXHtmlTree::EnableBranch(HTREEITEM hItem, BOOL bEnabled)
  • Fixed problem with using spacebar to check item, reported by David McMinn.
  • Fixed problem with in-place edit box not closing, reported by David McMinn.
  • Fixed several problems with in-place editing, using code supplied by David McMinn.

Version 1.1 - 2007 October 10

  • Added demo project for MDI app.
  • Eliminated flickering of desktop icons, reported by Greg Cadmes.
  • Fixed version problem with system color definitions, reported by Graham Shanks.
  • Fixed compile problem with CVisualStylesXP::UseVisualStyles(), reported by Graham Shanks.
  • Smart checkboxes now default to off (FALSE); suggested by Graham Shanks.
  • Added color support for disabled tree, suggested by Graham Shanks.
  • Fixed CheckAll() to handle multiple root nodes, reported by Rolando E. Cruz-Marshall.
  • Fixed problem with SetCheck(), reported by Graham Shanks.
  • Added Get/SetReadOnly() functions, suggested by Graham Shanks. The SetReadOnly() function toggles all checkboxes between active (read/write) and inactive (read-only), and also allows/prevents in-place editing. When set to read-only, there is no automatic visual indication that the tree is read-only. You can use the SetBkColor() function to set the background of read-only tree to indicate read-only state. Also added option to demo app to set read-only state.
  • Added Shih Tzu to dog list, suggested by bolivar123.

Version 1.0 - 2007 August 9

  • Initial public release

Usage

This software is released into the public domain. You are free to use it in any way you like, except that you may not sell this source code. If you modify it or extend it, please to consider posting new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hans Dietrich

%7BA29339B6-2EA0-4F01-BAE6-36FC66E688D7%7D.gif

Mvp
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.
Occupation: Software Developer (Senior)
Location: United States United States

From: http://www.codeproject.com/KB/tree/XHtmlTree.aspx

你可能感兴趣的:(C/C++)