Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

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

4.97/5 (164 votes)
1 Jan 2008CPOL22 min read 2   10.1K  
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.
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:

screenshotCheckboxes 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:

screenshot

screenshotSmart 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:

screenshot

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

screenshotHTML - I wanted to include XHtmlDraw functionality, including support for web links and APP: links.
screenshotEnhanced 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.
screenshotLoading 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:

screenshot

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:

screenshot

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:

    screenshot
    Image has been reduced in size.

    To refresh list, just click button again.

  3. The Find button displays Find dialog:

    screenshot

    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:

    screenshot

    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:

    screenshot

  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:

FunctionApplies ToDescription
COLORREF GetBkColor()tree controlGet current background color for tree
BOOL GetItemBold(HTREEITEM hItem)itemGet item bold state (TRUE = item is bold)
COLORREF GetItemTextBkColor(HTREEITEM hItem)itemGet item background color for text
COLORREF GetItemTextColor(HTREEITEM hItem)itemGet item text color
LOGFONT * GetLogfont()tree controlGet pointer to current LOGFONT
COLORREF GetTextColor()tree controlGet current text color for tree
BOOL GetUseLogfont()tree controlGet current state of LOGFONT (TRUE = use specified LOGFONT
COLORREF SetBkColor(COLORREF rgb)tree controlSet tree background color
BOOL SetItemBold(HTREEITEM hItem, BOOL bBold)itemSet bold state for item
COLORREF SetItemTextBkColor(HTREEITEM hItem, COLORREF rgb)itemSet background color for item text
COLORREF SetItemTextColor(HTREEITEM hItem, COLORREF rgb)itemSet text color for item
CXHtmlTree& SetLogfont(LOGFONT * pLogFont)tree controlSet new LOGFONT for tree
COLORREF SetTextColor(COLORREF rgb)tree controlSet text color for tree
CXHtmlTree& SetUseLogfont(BOOL bFlag)tree controlSet 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
ColdHot
NormalDisabledNormalDisabled
Unchecked0001010110011101
Checked0010011010101110
Tri-state0011011110111111

Here are functions implemented to support XHtmlTree checkboxes:

FunctionDescription
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:

KeyDescription
Down and Up Arrow KeysMoves selection to next/previous item; no expand
Right Arrow KeyExpands the current selected item (if it is collapsed), selects the first child item
Left Arrow KeyCollapses the current selected item (if it is expanded), selects the parent item
Page DownMoves selection to last item in tree window; pages items as necessary
Page UpMoves selection to first item in tree window; pages items as necessary
Ctrl+Page DownScrolls to last item in tree window; pages items as necessary; selection is not changed
Ctrl+Page UpScrolls to first item in tree window; pages items as necessary; selection is not changed
BackspaceMoves selection to parent item
EndMoves selection to last item; no expand
HomeMoves selection to first item; no expand
Ctrl+EndScrolls to last; selection is not changed, no expand
Ctrl+HomeScrolls to first; selection is not changed, no expand
Asterisk (*) on numeric keypadExpands all items under the selected item
Plus Sign (+) on numeric keypadExpands the selected item
Minus Sign (-) on numeric keypadCollapses the selected item

Tree Navigation and Management

Here are functions implemented to support XHtmlTree navigation:

FunctionDescription
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:

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:

screenshot

Here is HTML used for this tooltip:

<h2>Golden Retriever</h2>
<br><hr color=lightsteelblue><br>
<table>
<tr>
<td><bmp idres=133 cx=110 cy=92 mask></td>
<td> </td>
<td width=180>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.</td>
</tr>
</table>

This is all standard HTML, except for the <bmp idres=133 cx=110 cy=92 mask>, 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):

C++
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:

screenshot

Notification Messages

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

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:

MessageDescriptionlParam
WM_XHTMLTREE_CHECKBOX_CLICKEDSent when a checkbox is clickedNew checkbox state (TRUE = checked)
WM_XHTMLTREE_DISPLAY_TOOLTIPSent when a tooltip is about to be displayedPointer to tooltip control (CToolTipCtrl or CPPToolTip)
WM_XHTMLTREE_INIT_TOOLTIPSent when tooltip control is being initializedPointer to tooltip control (CToolTipCtrl or CPPToolTip)
WM_XHTMLTREE_ITEM_EXPANDEDSent when an item has been expanded or collapsedNew 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:
    #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:

    CursorDemo ImageDescription
    No dropscreenshotUsed to indicate a no-drop zone; either an area outside the tree control, or an item that is not an allowed drop target.
    Drop MovescreenshotUsed to indicate the dragged item will be moved when left mouse button is released.
    Drop CopyscreenshotUsed 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:

    screenshotThe user can use Ctrl key to toggle between copy and move, before or during drag.
    screenshotThe application can control whether Ctrl key is recognized by setting/resetting XHTMLTREE_DO_CTRL_KEY drag operations flag.
    screenshotThe 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:

    screenshotWM_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).
    screenshotWM_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).
    screenshotWM_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).

    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:

screenshot

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

screenshot

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:

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 ModuleNoneXHTMLHTMLXHTMLTOOLTIPSXHTMLXML
CeXDib.cpp

Image 33

Image 34

Image 35

Image 36

CeXDib.h

Image 37

Image 38

Image 39

Image 40

CreateCheckboxImageList.cpp

Image 41

Image 42

Image 43

Image 44

CreateCheckboxImageList.h

Image 45

Image 46

Image 47

Image 48

PPDrawManager.cpp

Image 49

Image 50

Image 51

Image 52

PPDrawManager.h

Image 53

Image 54

Image 55

Image 56

PPHtmlDrawer.cpp

Image 57

Image 58

Image 59

Image 60

PPHtmlDrawer.h

Image 61

Image 62

Image 63

Image 64

PPTooltip.cpp

Image 65

Image 66

Image 67

Image 68

PPTooltip.h

Image 69

Image 70

Image 71

Image 72

VisualStylesXP.cpp

Image 73

Image 74

Image 75

Image 76

VisualStylesXP.h

Image 77

Image 78

Image 79

Image 80

XHtmlDraw.cpp

Image 81

Image 82

Image 83

Image 84

XHtmlDraw.h

Image 85

Image 86

Image 87

Image 88

XHtmlDrawLink.cpp

Image 89

Image 90

Image 91

Image 92

XHtmlDrawLink.h

Image 93

Image 94

Image 95

Image 96

XHtmlTree.cpp

Image 97

Image 98

Image 99

Image 100

XHtmlTree.h

Image 101

Image 102

Image 103

Image 104

XmlDocument.cpp

Image 105

Image 106

Image 107

Image 108

XmlDocument.h

Image 109

Image 110

Image 111

Image 112

XNamedColors.cpp

Image 113

Image 114

Image 115

Image 116

XNamedColors.h

Image 117

Image 118

Image 119

Image 120

XString.cpp

Image 121

Image 122

Image 123

Image 124

XString.h

Image 125

Image 126

Image 127

Image 128

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: screenshot
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:

FunctionDescription
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.

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)