65.9K
CodeProject 正在变化。 阅读更多。
Home

XHtmlTree - 支持HTML、XML、智能复选框以及拖放功能的树形控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (160投票s)

2007年8月9日

CPOL

23分钟阅读

viewsIcon

488550

downloadIcon

10155

XHtmlTree 是一个基于 CTreeCtrl 的 MFC 控件,支持 HTML 文本、网页链接、APP: 链接、XML 加载/保存、智能复选框以及拖放功能。

screenshot
2007年8月获奖
月度竞赛

引言

每个人都熟悉树形控件:每次打开 Windows 资源管理器时,都会看到文件系统层次结构以树形显示。另一种树形控件被一些程序(如安装程序)用于允许您选择要安装的选项。当特定子树的所有选项都被选中时,您会看到一个带有勾号的复选框 (screenshot);当子树中没有选项被选中时,子树根旁边的复选框会显示一个未选中的复选框 (screenshot);当子树中只有部分选项被选中时,您会看到所谓的三态复选框 (screenshot)。

令人惊讶的是,MFC 的 CTreeCtrl 中并没有直接支持三态复选框。最接近的方法是为您的树创建一个三态图像列表。虽然这可行,但它无法提供 XP 主题复选框的完整视觉效果,例如鼠标悬停时的热状态外观 (screenshot)。

当我研究树形控件以及如何添加三态复选框时,我了解到树形控件(类似于列表控件)可以通过自定义绘制机制,通过许多有用的功能和漂亮的 UI 效果进行增强。这促使我迈出了下一步:为树形项添加 HTML 支持。由于我刚刚完成了我的 XHtmlDraw 文章,所以很容易看出这是如何实现的。

不久我就草拟出了我的新树形控件的需求

screenshot 支持主题的复选框 - 我希望在复选框切换时向父级发送通知消息,并获得完整的主题支持;这意味着支持悬停(热)状态,复选框的绘制应与主题化的 XP 复选框完全相同。当然,在 Vista 上,复选框应该具有 Vista 外观。

screenshot

screenshot 智能复选框 - 这是我开始使用(但并非发明)的一个术语,用于描述选中父项时也会选中该项的所有子项,反之,取消选中子项时,如果其他子项仍被选中,则父项会显示三态复选框。以下是其工作原理的快速演示。

screenshot

当然,智能复选框是可选的——您可以拥有复选框而无需使用智能复选框。

screenshot HTML - 我想包含 XHtmlDraw 功能,包括对网页链接和 APP: 链接的支持。
screenshot 增强的树形导航和状态 - 阅读 Zafir Anjum 的文章 给我带来了改进树形控件编程接口的想法,我还想实现更好的管理功能,例如确定有多少项被选中,一个项有多少子项等等,并在项展开时向父级发送通知消息。
screenshot 使用 XML 加载和保存树数据 - 随着 XML 在更多应用程序中被采用,这是一个常见的需求。

XHtmlTree 功能

首先,让我向您展示演示应用程序:

screenshot

此对话框允许您选择树的数据源。它可以是文本文件或 XML 文件(文件以资源形式存储,详情请参阅我的XResFile 文章)。每种文件类型都有两种选择——一种是完整列表,第二种是每个主节点包含十个项目的部分列表,以便于调试。

点击按钮后,您将看到

screenshot

以下是主要功能

  1. 选项复选框允许以各种树范围内的选项显示树——即,它们影响所有项目。
  2. 显示已选中按钮显示一个无模式对话框,其中显示当前已选中项目的列表。

    screenshot
    图像已缩小。

    要刷新列表,只需再次单击按钮。

  3. 查找”按钮显示“查找对话框

    screenshot

    此对话框使用内置的 CXHtmlTree::FindItem() 函数来搜索项目文本。对话框上的一个选项允许您标记所有匹配的项目,您可以使用“显示已选中”对话框进行观察。

  4. 颜色”按钮显示“颜色对话框

    screenshot

    请注意,背景颜色将设置为整个树形控件的背景(通过 SetBkColor())。但是,单个项目可以通过使用 SetItemTextBkColor() 或使用 HTML 来独立设置其背景。

    screenshot

  5. 这些是拖放滚动滚动速度的指示器。
  6. 这三个按钮允许您切换所有项目的勾选状态、展开所有项目和折叠所有项目。
  7. 树形控件显示一个已勾选的项目。请注意,其父项(Collies)显示为三态勾选框,表示其子项之一(但不是全部)已勾选。其父项(Herding Dogs)也具有三态勾选框。
  8. 编辑框包含项目文本,您可以修改它,然后使用更新按钮将新文本写入树项目。
  9. 树信息”显示整个树的信息。
  10. 项目信息”显示有关项目的信息 - 无论是当前选定的项目,还是刚刚展开的项目。
  11. 树形面包屑导航通过使用 GetItemPath() 函数和 XBreadCrumbBar 显示。当您点击活动面包屑时,该树节点将被选中。
  12. 当从控件接收到通知消息(TVN_SELCHANGEDWM_XHTMLTREE_CHECKBOX_CLICKEDWM_XHTMLTREE_ITEM_EXPANDED)时,“日志”会显示信息。您可以使用复选框启用或禁用日志。

实现说明

HTML

要查看支持的 HTML 标签的完整列表,包括如何使用网页链接和 APP: 链接,请参阅我的 XHtmlDraw 文章。

颜色和文本属性

以下函数支持项目和树的颜色以及文本属性

函数 适用范围 描述
COLORREF GetBkColor() 树形控件 获取树的当前背景颜色
BOOL GetItemBold(HTREEITEM hItem) 获取项的粗体状态(TRUE = 项是粗体)
COLORREF GetItemTextBkColor(HTREEITEM hItem) 获取项目的文本背景颜色
COLORREF GetItemTextColor(HTREEITEM hItem) 获取项目文本颜色
LOGFONT * GetLogfont() 树形控件 获取指向当前 LOGFONT 的指针
COLORREF GetTextColor() 树形控件 获取树的当前文本颜色
BOOL GetUseLogfont() 树形控件 获取 LOGFONT 的当前状态 (TRUE = 使用指定的 LOGFONT)
COLORREF SetBkColor(COLORREF rgb) 树形控件 设置树的背景颜色
BOOL SetItemBold(HTREEITEM hItem, BOOL bBold) 设置项目的粗体状态
COLORREF SetItemTextBkColor(HTREEITEM hItem, COLORREF rgb) 设置项目文本的背景颜色
COLORREF SetItemTextColor(HTREEITEM hItem, COLORREF rgb) 设置项目的文本颜色
CXHtmlTree& SetLogfont(LOGFONT * pLogFont) 树形控件 为树设置新的 LOGFONT
COLORREF SetTextColor(COLORREF rgb) 树形控件 设置树的文本颜色
CXHtmlTree& SetUseLogfont(BOOL bFlag) 树形控件 设置标志以指示是否应使用 LOGFONT 结构(TRUE = 使用 LOGFONT)

复选框

您可以独立于启用智能复选框(使用 SetSmartCheckBox())启用树的复选框(使用 SetHasCheckBoxes())。当复选框启用时,将为各种复选框状态创建内部状态图像列表。此创建是在 CreateCheckboxImageList() 中执行的(参见 CreateCheckboxImageList.cpp)。对于每种可能的状态,都会(使用 David Zhao 优秀的 CVisualStylesXP 类)为冷状态和热状态创建位图。显然,这意味着模态处理,但由于我可以使用 CTreeCtrl::SetItemState(),因此跟踪项目状态并不太复杂。此外,我设计了图像列表,使常见的状态转换变得简单。在下表中,您可以看到从“冷”状态到“热”状态涉及与 8 进行 OR 运算,从“正常”状态到“禁用”状态涉及与 4 进行 OR 运算。

XHtmlTree 复选框状态
正常 禁用 正常 禁用
未选中 0001 0101 1001 1101
Checked 0010 0110 1010 1110
三态 0011 0111 1011 1111

以下是为支持 XHtmlTree 复选框而实现的函数

函数 描述
void CheckAll(BOOL bCheck) 将所有项目的复选框设置为 bCheck 状态
BOOL GetCheck(HTREEITEM hItem) 如果项目被选中,则返回 TRUE。如果项目未被选中或处于三态,则返回 FALSE。
int GetCheckedCount() 返回树中已选中项目的总数
int GetChildrenCheckedCount(HTREEITEM hItem) 返回子项的选中数量
HTREEITEM GetFirstCheckedItem() 返回第一个选中的项目,如果没有则返回 NULL
BOOL GetHasCheckBoxes() 如果树有复选框,则返回 TRUE
HTREEITEM GetNextCheckedItem(HTREEITEM hItem) 返回下一个被选中的项目,如果没有则返回 NULL
HTREEITEM GetPrevCheckedItem(HTREEITEM hItem) 返回上一个选中的项目,如果没有则返回 NULL
BOOL GetSelectFollowsCheck() 如果选中项目也会导致其被选中,则返回 TRUE
BOOL GetSmartCheckBox() 如果智能复选框已启用,则返回 TRUE
BOOL IsChecked(HTREEITEM hItem) 如果项目被选中,则返回 TRUE。如果项目未被选中或处于三态,则返回 FALSE。
CXHtmlTree& SetCheck(HTREEITEM hItem, BOOL fCheck = TRUE) 将项目选中状态设置为 fCheck
CXHtmlTree& SetCheckChildren(HTREEITEM hItem, BOOL fCheck) 将子项的选中状态设置为 fCheck
CXHtmlTree& SetHasCheckBoxes(BOOL bHasCheckBoxes) 如果 bHasCheckBoxes 为 TRUE,则为树启用复选框
CXHtmlTree& SetSelectFollowsCheck(BOOL bFlag) 如果 bFlag 为 TRUE,选中一个项目也会导致它被选中
CXHtmlTree& SetSmartCheckBox(BOOL bFlag) 如果 bFlag 为 TRUE,则启用智能复选框

键盘快捷键

XHtmlTree 支持标准 Windows 键盘导航技术

描述
向下和向上箭头键 将选择移动到下一/上一项;不展开
右箭头键 展开当前选定的项(如果它已折叠),选择第一个子项
左箭头键 折叠当前选定的项(如果它已展开),选择父项
Page Down 将选择移动到树窗口中的最后一项;根据需要翻页
Page Up 将选择移动到树窗口中的第一项;根据需要翻页
Ctrl+Page Down 滚动到树窗口中的最后一项;根据需要翻页;选择不改变
Ctrl+Page Up 滚动到树窗口中的第一项;根据需要翻页;选择不改变
退格键 将选择移动到父项
End 将选择移动到最后一项;不展开
Home 将选择移动到第一项;不展开
Ctrl+End 滚动到末尾;选择不变,不展开
Ctrl+Home 滚动到开头;选择不变,不展开
数字键盘上的星号(*) 展开选中项下的所有项
数字键盘上的加号 (+) 展开选中的项目
数字键盘上的减号 (-) 折叠选中的项目

树形导航和管理

以下是为支持 XHtmlTree 导航而实现的函数

函数 描述
HTREEITEM GetLastItem(HTREEITEM hItem) 检索树中的最后一项
HTREEITEM GetNextCheckedItem(HTREEITEM hItem) 检索下一个已勾选的项
HTREEITEM GetNextItem(HTREEITEM hItem) 检索树中的下一项。这会像树完全展开时视觉上显示的那样,从上到下遍历树。
HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) 检索与 hItem 具有指定关系(由 nCode 参数指示)的项目
HTREEITEM GetPrevCheckedItem(HTREEITEM hItem) 检索上一个已勾选的项
HTREEITEM GetPrevItem(HTREEITEM hItem) 检索树中的上一项。这会像树完全展开时视觉上显示的那样,从上到下遍历树。

初始化树

用一条语句初始化 XHtmlTree 很简单

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

工具提示

XHtmlTree 通过 CToolTipCtrl 支持标准工具提示,也支持 HTML 工具提示,这些工具提示由 Eugene Pustovoyt 优秀的 CPPToolTip 类显示。以下是 HTML 工具提示如何使用的示例

screenshot

以下是此工具提示使用的 HTML

<h2>金毛寻回犬</h2>
<br><hr color=lightsteelblue><br>
<table>
<tr>
<td><bmp idres=133 cx=110 cy=92 mask></td>
<td> </td>
<td width=180>金毛寻回犬是一种受欢迎的犬种,最初是为了在狩猎中捡回猎物而培育的。由于其天性友善且易于训练,因此它是最常见的家庭犬之一。</td>
</tr>
</table>

这都是标准 HTML,除了 <bmp idres=133 cx=110 cy=92 mask>,它指定要从资源 ID 133 读取位图。

好的,那么 HTML 是从哪里来的呢,因为它显然不是项目文本?XHtmlTree 提供了一个新的 SetItemNote() 函数,它将可选的注释文本附加到项目。注释文本(如果存在)将代替项目文本用于工具提示。对于标准工具提示和 HTML 工具提示都是如此。但是,请记住,标准工具提示有 80 个字符的硬限制。

要启用 HTML 工具提示,请确保 XHtmlTree.h 中的这一行未被注释掉:#define XHTMLTOOLTIPS

如果您包含 HTML 工具提示,则必须在项目中包含额外的文件 - 详情请参阅下面的“如何使用”部分。

关于工具提示的最后一点:您可以选择在工具提示即将显示时动态更改它。一条通知消息(WM_XHTMLTREE_DISPLAY_TOOLTIP - 参见下面的“通知消息”)让您有机会在工具提示显示前使用 SetItemNote()。举个例子,在 XHtmlTreeTestDlg.cpp 中,您将看到以下代码(此处已精简)

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
}

在演示应用程序中,您将看到

screenshot

通知消息

对于所有通知消息,wParam 参数是指向 XHTMLTREEMSGDATA 结构的指针

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

lParam 参数取决于具体消息。以下消息发送给 XHtmlTree 父级

Message 描述 lParam
WM_XHTMLTREE_CHECKBOX_CLICKED 点击复选框时发送 新的复选框状态(TRUE = 选中)
WM_XHTMLTREE_DISPLAY_TOOLTIP 当工具提示即将显示时发送 指向工具提示控件的指针(CToolTipCtrlCPPToolTip
WM_XHTMLTREE_INIT_TOOLTIP 当工具提示控件正在初始化时发送 指向工具提示控件的指针(CToolTipCtrlCPPToolTip
WM_XHTMLTREE_ITEM_EXPANDED 当项目被展开或折叠时发送 新项目状态(TRUE = 已展开)

拖放

从版本 1.4 开始,XHtmlTree 支持拖放。以下拖放功能和操作已实现

  1. 有一个新的编译时符号来启用拖放代码的包含
        #define XHTMLDRAGDROP
    定义(或不定义)此符号也会正确设置 TVS_DISABLEDRAGDROP 样式。
  2. 拖放是使用 CTreeCtrl::SetInsertMark() API 实现的。例如,Firefox 书签就是使用这种方式。当一个项目被拖动时,您会看到一条实心细条——称为插入标记——显示在树中的项目之间。插入标记表示如果项目被放置,它将插入到树中的位置。
  3. 根据设计,传统的 OLE 样式拖动图像动画尚未实现,目前也没有计划这样做。
  4. 除了显示插入标记之外,您还可以选择通过 SetDropCursors() 函数显示三个自定义光标:禁止放置光标放置移动光标放置复制光标。演示应用程序包含每个示例

    光标 演示图片 描述
    禁止放置 screenshot 用于指示禁止放置区域;可以是树形控件外部的区域,或者是不允许作为放置目标的项。
    放置移动 screenshot 用于指示在释放鼠标左键时,拖动的项目将被移动。
    放置复制 screenshot 用于指示在释放鼠标左键时,拖动的项目将被复制。

  5. 放置复制放置移动 - 有几种方法可以控制拖动的项目是复制还是移动

    screenshot 用户可以在拖动之前或拖动期间使用 Ctrl 键在复制和移动之间切换。
    screenshot 应用程序可以通过设置/重置 XHTMLTREE_DO_CTRL_KEY 拖动操作标志来控制是否识别 Ctrl 键
    screenshot 应用程序可以通过设置/重置 XHTMLTREE_DO_COPY_DRAG 拖动操作标志来更改 Ctrl 键的默认行为。

  6. 应用程序可以通过处理以下通知消息来控制拖动的每个阶段

    screenshot WM_XHTMLTREE_BEGIN_DRAG - 此消息在拖动开始时发送,包括被拖动的项目和 XHTMLTREE_DO_COPY_DRAG 标志位的状态。请注意,在演示应用程序中,尝试拖动“灵缇犬组”中的“长犬”将被拒绝(参见演示日志)。
    screenshot WM_XHTMLTREE_END_DRAG - 此消息在拖动终止时发送,无论是通过放置还是其他用户操作(例如按 ESC 键,右键单击鼠标,将项目放回自身,或放置到树形控件外部)。如果拖动因放置到有效的树形项(自身除外)而终止,此消息将包含建议的放置目标。如果拖动因任何其他原因终止,则将值 0 作为 lParam 参数发送。请注意,在演示应用程序中,放置到“灵缇犬组”中的“长犬”将被拒绝(参见演示日志)。
    screenshot WM_XHTMLTREE_DROP_HOVER - 当光标悬停在树形项目上时发送此消息,并包含可能成为放置目标的树形项目。请注意,在演示应用程序中,悬停在“灵缇犬组”中的“长犬”上将显示“禁止放置”光标。

    对于所有上述消息,一个指向 XHTMLTREEDRAGMSGDATA 结构的指针作为 lParam 参数发送(在 WM_XHTMLTREE_END_DRAG 消息的情况下可能为 NULL)。

    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
    };

    应用程序可以通过 FALSE(表示建议的操作可以继续)或 TRUE(表示不允许建议的操作)来响应这些消息。当响应 WM_XHTMLTREE_BEGIN_DRAGWM_XHTMLTREE_END_DRAG 消息时,返回代码 TRUE 将终止拖动。当响应 WM_XHTMLTREE_DROP_HOVER 消息时,返回代码 TRUE 将导致显示禁止放置光标。

    由于在没有消息处理程序的情况下,默认返回代码为 0 或 FALSE,因此无需实现任何这些消息的处理程序即可启用拖放功能。

  7. 默认情况下,在拖动过程中,当光标接近控件顶部或底部时,树将自动滚动。树以三种不同的速度滚动,具体取决于光标与边缘的距离。此外,应用程序可以选择两种整体速度设置之一 - 正常或快速 - 并且还可以完全禁用拖动滚动。拖动滚动由拖动操作标志 XHTMLTREE_DO_SCROLL_NORMALXHTMLTREE_DO_SCROLL_FAST 控制。如果这两个标志位都为 0,则不会发生滚动。
  8. 默认情况下,在拖动过程中,当光标悬停在节点上时,树将自动展开该节点。此行为可以通过拖动操作标志位 XHTMLTREE_DO_AUTO_EXPAND 禁用。
  9. 通过结合使用 SetInsertMark() API 和自动展开,用户可以在任何现有节点之后放置项目(或分支)。然而,这两个机制不允许“放置到下面”,即放置导致子项的创建。为了适应这一点,用户可以在拖动之前或拖动期间使用 Shift 键。按住 Shift 键会使放置变为“放置到下面”:插入标记被移除,取而代之的是放置目标(建议的新父项)被高亮显示。此行为可以通过拖动操作标志位 XHTMLTREE_DO_SHIFT_KEY 禁用。
  10. 涉及禁用或只读项目的拖动操作不会被 XHtmlTree 明确禁止。如果您想阻止拖动禁用或只读项目,您应该为 WM_XHTMLTREE_BEGIN_DRAG 消息设置处理程序。请参阅 XHtmlTreeTestDlg.cpp 获取示例。
  11. 存在一个已知问题:当按住 Ctrl 键时,ESC 键无法终止拖动。

分隔符

screenshot
从版本 1.6 开始,XHtmlTree 支持项目分隔符。分隔符只是视觉指示符,旨在区分或分隔树形项目。在以下屏幕截图中,三只“澳大利亚”犬被两个分隔符包围

screenshot

要亲自尝试分隔符,您可以使用演示应用程序中的右键菜单。

screenshot

以下分隔符功能和操作已实现

  1. 函数 InsertSeparator() 在指定项目之后插入一个分隔符。分隔符的数量没有限制。
  2. 函数 IsSeparator() 允许您测试树形项目是否为分隔符。
  3. 您可以使用 SetItemTextColor() 更改单个分隔符的颜色,或者可以使用 SetSeparatorColor() 更改所有分隔符的颜色。默认分隔符颜色是 GetSysColor(COLOR_GRAYTEXT) 返回的颜色。
  4. 分隔符可以像任何其他树形项目一样被选中。
  5. 分隔符可以像任何其他树形项目一样被拖动。
  6. 分隔符不能有文本。
  7. 分隔符不能有子项。尝试将项目放置在分隔符上将始终导致项目插入到分隔符之后(不允许“放置到下方”)。但是,允许将分隔符放置在非分隔符项目下方。
  8. 分隔符不能通过 TVN_BEGINLABELEDIT 编辑。
  9. 分隔符包含在子项计数中,但对智能复选框没有影响。
  10. 您可以使用属性 separator=1 指定从 XML 文件加载分隔符。

如何使用

要将 XHtmlTree 集成到您自己的应用程序中,您首先需要将以下文件添加到您的项目

  • 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

标有 的文件必须在 Visual Studio 中设置为不使用预编译头文件

如果您想使用 HTML 工具提示,那么您还必须包含以下文件

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

最后,如果您想包含 XML 函数,则必须包含这两个文件

  • XmlDocument.cpp
  • XmlDocument.h

然后声明 CTreeCtrl 对象的变量,并将其类型更改为 CXHtmlTree

    CXHtmlTree    m_Tree;

现在您就可以在您的项目中使用 CXHtmlTree 了。

XHtmlTree 编译时选项

有三个编译时选项控制 XHtmlTree 包含哪些功能。这些选项可以通过编辑 XHtmlTree.h、将其作为 #define 语句包含(例如,在 stdafx.h 中),或者通过 IDE 定义它们(在 VS2005 中,转到项目 | 属性 | 配置属性 | C/C++ | 预处理器 | 预处理器定义;确保对所有配置都执行此操作)。

  • XHTMLHTML - 定义后,此选项将启用在树形项中使用 HTML。
  • XHTMLTOOLTIPS - 定义后,此选项将启用 HTML 工具提示的使用。
  • XHTMLXML - 定义后,此选项将启用 XML 数据的加载/保存。
  • XHTMLDRAGDROP - 定义后,此选项将启用拖放功能。

下表显示了每个编译时选项需要包含的源模块(包括未选择任何选项的情况,这在 MinDialog 演示中使用了)

XHtmlTree 编译时选项
源模块 XHTMLHTML XHTMLTOOLTIPS XHTMLXML
CeXDib.cpp

CeXDib.h

CreateCheckboxImageList.cpp

CreateCheckboxImageList.h

PPDrawManager.cpp

PPDrawManager.h

PPHtmlDrawer.cpp

PPHtmlDrawer.h

PPTooltip.cpp

PPTooltip.h

VisualStylesXP.cpp

VisualStylesXP.h

XHtmlDraw.cpp

XHtmlDraw.h

XHtmlDrawLink.cpp

XHtmlDrawLink.h

XHtmlTree.cpp

XHtmlTree.h

XmlDocument.cpp

XmlDocument.h

XNamedColors.cpp

XNamedColors.h

XString.cpp

XString.h

标有 的文件必须在 Visual Studio 中设置为不使用预编译头文件

拖放(XHTMLDRAGDROP)所需的文件与“”下列出的文件相同。

使用 XML

您可以按照您当前的方式加载树,或者(如果您在 XHtmlTree.h 中定义了 XHTMLXML)您可以使用 LoadXmlFromXXXX 函数 - 请参阅 XHtmlTreeTestDlg.cpp 获取示例。XHtmlTree 使用的 XML 解析器极其简单,不执行任何严格的错误检查。在 dogs.xml 中此精简的 XML 片段中,请注意 HTML 标签必须用字符实体进行转义 screenshot
点击放大。

以下是 LoadXmlFromXXXX 函数期望的属性名称

  • name - 这是将插入到树中的项目文本。它可以包含 HTML 格式。
  • checked - 为项目指定初始选中状态(如果为“1”)或未选中状态(“0”)。默认为未选中。
  • enabled - 为项目指定初始启用状态(如果为“1”)或未启用状态(“0”)。默认为启用。
  • separator - 指定项目是分隔符(如果为“1”)或不是分隔符(“0”)。默认为不是分隔符。
  • image - 将图像列表中的图像与项目关联。使用 SetImageList() 设置图像列表。
  • text-color - 项目的文本颜色;覆盖全局树文本颜色。
  • text-background-color - 项目的文本背景颜色;覆盖全局树文本背景颜色。
  • note-width - 此项目的工具提示宽度。默认值为 0 表示将使用启发式方法确定适当的宽度。
  • note - 此文本将代替标准工具提示文本显示。如果已定义 XHTMLTOOLTIPS(参见 XHtmlTree.h),则此文本可以包含 HTML 标签。

您可以从资源、文件或内存缓冲区加载 XML,也可以将 XML 保存到文件。

以下是为支持 XML 而实现的函数

函数 描述
BOOL ConvertBuffer(const BYTE * inbuf, DWORD inlen, BYTE ** outbuf, DWORD& outlen, ConvertAction eConvertAction = NoConvertAction) 将 XML 缓冲区转换为 Unicode/从 Unicode 转换
CString GetXmlText(HTREEITEM hItem, LPCTSTR lpszElem) 检索项目的 XML
BOOL LoadXmlFromBuffer(const BYTE * pBuf, DWORD len, ConvertAction eConvertAction) 从内存缓冲区加载 XML
BOOL LoadXmlFromFile(LPCTSTR lpszFile, ConvertAction eConvertAction) 从文件加载 XML
BOOL LoadXmlFromResource(HINSTANCE hInstance, LPCTSTR lpszResId, LPCTSTR lpszResType, ConvertAction eConvertAction) 从资源加载 XML
BOOL SaveXml(HTREEITEM hItem, LPCTSTR lpszFileName, BOOL bSaveAsUTF16) 将 XML 保存到文件

参考文献

以下是我在这篇文章中提到的链接。我还包含了我在 CodeProject 上的文章链接,我在演示应用程序中使用了它们。

修订历史

版本 1.6 - 2007 年 12 月 19 日

  • 添加了对分隔符的支持。
  • 修复了多根节点错误 - 拖放根节点总是创建子节点而不是根节点。
  • 在演示应用程序中添加了多根节点示例

版本 1.5 - 2007 年 11 月 7 日

  • 修复了 XML 输入错误(如果没有图像列表则崩溃);由 Berni Slootbeek 报告。
  • 更新至 XHtmlDraw v1.2。

版本 1.4 - 2007 年 11 月 4 日

  • 添加了对 拖放 的支持,由 David McMinn 建议。感谢您的帮助,David!

版本 1.3 - 2007 年 10 月 16 日

  • 添加了“最小对话框”的演示项目。此项目展示了如何使用带智能复选框的 XHtmlTree,但没有 HTML、XML 或 HTML 工具提示。这使得可执行文件大小减少了约 130KB。

版本 1.2 - 2007 年 10 月 14 日

  • 调整了显示性能。
  • 演示应用程序的少量修改。
  • 在演示应用程序中添加了 WM_CONTEXTMENU 的处理程序。
  • 添加了 CXHtmlTree::EnableBranch(HTREEITEM hItem, BOOL bEnabled)
  • 修复了使用空格键选中项目的问题,由 David McMinn 报告。
  • 修复了就地编辑框不关闭的问题,由 David McMinn 报告。
  • 使用 David McMinn 提供的代码修复了几个就地编辑问题。

版本 1.1 - 2007 年 10 月 10 日

  • 添加了 MDI 应用程序的演示项目。
  • 消除了桌面图标闪烁的问题,由 Greg Cadmes 报告。
  • 修复了系统颜色定义版本问题,由 Graham Shanks 报告。
  • 修复了 CVisualStylesXP::UseVisualStyles() 的编译问题,由 Graham Shanks 报告。
  • 智能复选框现在默认为关闭 (FALSE);由 Graham Shanks 建议。
  • 添加了对禁用树的颜色支持,由 Graham Shanks 建议。
  • 修复了 CheckAll() 处理多个根节点的问题,由 Rolando E. Cruz-Marshall 报告。
  • 修复了 SetCheck() 的问题,由 Graham Shanks 报告。
  • 添加了 Get/SetReadOnly() 函数,由 Graham Shanks 建议。SetReadOnly() 函数可在活动(读/写)和非活动(只读)之间切换所有复选框,并允许/阻止就地编辑。设置为只读时,没有自动的视觉指示表明树是只读的。您可以使用 SetBkColor() 函数设置只读树的背景,以指示只读状态。还在演示应用程序中添加了设置只读状态的选项。
  • 将西施犬添加到狗列表中,由 bolivar123 建议。

版本 1.0 - 2007 年 8 月 9 日

  • 首次公开发布

用法

本软件发布到公共领域。您可以以任何您喜欢的方式使用它,但不得出售此源代码。如果您修改或扩展它,请考虑在此处发布新代码供大家分享。本软件“按原样”提供,不提供任何明示或暗示的保证。对于本软件可能造成的任何损害或业务损失,我不承担任何责任。

© . All rights reserved.