CQuadStateTree
派生自 CTreeCtrl 的控件,
引言
我需要一个具有标准CTreeCtrl
所不具备的多个功能的树形控件。
- 具有不确定状态的复选框。当树形控件的子项不全处于相同状态时,该项的复选框应显示不确定状态。
- 将父树项的复选框状态设置为选中或取消选中,应自动将所有其子树项的状态设置为相同状态。
- 将子树项的复选框状态设置为选中或取消选中,应自动将其父树项的状态设置为相应状态。
- 并非树形控件中的所有项都需要复选框。有时,树的根节点仅需作为标签占位符。
- 通知。如果树形控件的父窗口在树项复选框状态更改时收到详细的通知消息,那将是非常好的。
- 能够阻止复选框状态的更改。当父窗口收到通知(见上文)时,应有可能阻止复选框状态的更改。
本文档介绍的CQuadStateTree
类实现了所有这些需求,再加上一些额外的功能。
背景
您可能会问,为什么是 Quad State(四态)?这是因为树形控件中的每个复选框可以有四种状态。当然,有基本的选中和未选中,以及熟悉的“不确定”状态。但我增加了一种第四种状态,即“none
”(无)。您可能会说“none
”不是一种状态,但实际上是。当树形控件中的其他项都有复选框时,如何指定某一个树项不应有复选框?
当然,为了使“none
”状态有意义,必须对其施加基本限制。限制是:为了使树项具有“none
”状态,其所有父项(沿树向上直到根节点)也必须处于“none
”状态。无法选择父项但无法选择子项是没有意义的。
Using the Code
在您自己的项目中开始使用此代码的第一步是将QuadStateTree.h和QuadStateTree.cpp文件添加到您的项目中。然后,在任何需要访问CQuadStateTree
类的文件中,只需#include QuadStateTree.h
。
由于CQuadStateTree
是从CTreeCtrl
派生的,因此您可以使用此类的使用方式与使用CTreeCtrl
完全相同,但存在以下API例外:
CQuadStateTree 数据类型
CQuadStateTree
使用以下自定义数据类型。
TVCS_CHECKSTATE
TVCS_CHECKSTATE
enum
定义了四种可能的复选框状态。
语法
enum TVCS_CHECKSTATE
{
TVCS_NONE = -1,
TVCS_UNCHECKED = 0,
TVCS_CHECKED = 1,
TVCS_INDETERMINATE = 2
};
成员
TVCS_NONE | 该树项没有与之关联的复选框。 |
TVCS_UNCHECKED | 该树项的复选框中没有勾选标记。 |
TVCS_CHECKED | 该树项的复选框中有一个勾选标记。 |
TVCS_INDETERMINATE | 该树项有子项,并且子项是选中和未选中状态的混合。 |
NMTVNCHECK
NMTVNCHECK
结构包含有关树项复选框状态更改的信息。
语法
typedef struct tagTVNCHECK
{
NMHDR hdr;
HTREEITEM hTreeItem;
LPARAM lParam;
TVCS_CHECKSTATE OldCheckState;
TVCS_CHECKSTATE NewCheckState;
HTREEITEM TriggerItem;
} NMTVNCHECK, *LPNMTVNCHECK;
成员
hdr | NMHDR 结构,包含有关 TVN_CHECK 通知消息的信息。 |
hTreeItem | 要从中检索复选框状态的树项的句柄。 |
lParam | 与hTreeItem 关联的应用程序特定数据。 |
OldCheckState | hTreeItem 的旧复选框状态。 |
NewCheckState | hTreeItem 的新复选框状态。 |
TriggerItem | 由用户切换或在调用SetCheck() 时指定的树项的句柄。 |
CQuadStateTree 通知消息
TVN_CHECK 通知代码
TVN_CHECK
通知作为 WM_NOTIFY 消息发送到父窗口,以通知父窗口复选框即将更改状态。
语法
TVN_CHECK
pNMTvnCheck = (LPNMTVNCHECK) lParam
参数
pNMTvnCheck | 指向 NMTVNCHECK 结构的指针。 |
返回值
如果NMTVNCHECK
结构中的hTreeItem
和TriggerItem
成员指向同一树项,则返回非零值将阻止树项复选框更改状态。
在所有其他情况下,将忽略返回值。
ON_TVN_CHECK 消息映射宏
使用ON_TVN_CHECK
宏来定义TVN_CHECK
通知处理函数。
语法
ON_TVN_CHECK(<nID>, <pFunction>)
参数
nID | 树形控件的标识号 |
pFunction | 当发送TVN_CHECK 通知时要调用的成员函数的指针。 |
备注
pFunction
必须使用以下原型声明:
afx_msg void memberFxn( NMHDR * pNMHDR, LRESULT * pResult );
其中斜体参数是:
pNMHDR
指向NMHDR
结构的指针,可以将其强制转换为 LPNMTVNCHECK 结构指针。
pResult
指向您在返回前设置的结果代码的指针。
CQuadStateTree 成员函数
CQuadStateTree::CQuadStateTree
用于构造CQuadStateTree
对象的类构造函数。
语法
CQuadStateTree();
CQuadStateTree::~CQuadStateTree
删除CQuadStateTree
对象时调用的类析构函数。
语法
virtual ~CQuadStateTree();
CQuadStateTree::GetCheck
语法
TVCS_CHECKSTATE GetCheck(
HTREEITEM hTreeItem) const;
参数
hTreeItem | 要从中检索复选框状态的树项的句柄。 |
返回值
返回一个 TVCS_CHECKSTATE enum
,指示复选框的当前状态。
备注
此函数与 CTreeCtrl::GetCheck 相同。唯一区别在于返回值是作为 TVCS_CHECKSTATE enum
返回,而不是BOOL
。
CQuadStateTree::SetCheck
语法
BOOL SetCheck (
HTREEITEM hTreeItem,
TVCS_CHECKSTATE NewCheckState = TVCS_CHECKED);
参数
hTreeItem | 要接收复选框状态更改的树项的句柄。 |
NewCheckState | 新的复选框状态。默认情况下,复选框状态设置为TVCS_CHECKED 。 |
返回值
成功则返回非零值;否则返回零。
备注
SetCheck()
因以下原因返回零:
NewCheckState
为TVCS_INDETERMINATE
。TVCS_INDETERMINATE
状态仅在树项的子项状态不同时由控件设置。无法通过SetCheck()
设置TVCS_INDETERMINATE
。NewCheckState
为TVCS_NONE
。将复选框设置为TVCS_NONE
状态的唯一方法是,hTreeItem
的所有父树项都已设置为TVCS_NONE
。要设置TVCS_NONE
状态,您必须从树的根节点开始,向下进行。
CQuadStateTree::Create
调用此函数以创建控件(子窗口)并将其与CQuadStateTree
对象关联。
语法
virtual BOOL Create(
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
UINT nID);
参数
dwStyle | 指定树视图控件的样式。应用窗口样式,如 CreateWindow 中所述,以及平台 SDK中所述的任何 树视图控件样式的组合。 |
rect | 对RECT 结构的引用,该结构描述了要创建的窗口的大小和位置,以pParentWnd 的客户区坐标表示。 |
pParentWnd | 指向作为控件父窗口的窗口的指针。 |
nID | 控件的子窗口 ID。 |
CQuadStateTree::CreateEx
调用此函数以创建控件(子窗口)并将其与CQuadStateTree
对象关联。
语法
virtual BOOL CreateEx(
DWORD dwExStyle,
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
UINT nID);
参数
dwExStyle | 指定要创建控件的扩展样式。有关 扩展 Windows 样式的列表,请参阅平台 SDK中 CreateWindowEx 的dwExStyle 参数。 |
dwStyle | 指定树视图控件的样式。应用窗口样式,如 CreateWindow 中所述,以及平台 SDK中所述的任何 树视图控件样式的组合。 |
rect | 对RECT 结构的引用,该结构描述了要创建的窗口的大小和位置,以pParentWnd 的客户区坐标表示。 |
pParentWnd | 指向作为控件父窗口的窗口的指针。 |
nID | 控件的子窗口 ID。 |
备注
我尚未探索 树视图扩展样式,因此我不知道它们将如何影响此控件。
从CQuadStateTree派生
CQuadStateTree
必须处理多个不同的消息才能正常工作。如果您从CQuadStateTree
派生自己的控件,并且在派生类中处理相同的消息,请务必从您的消息处理函数调用CQuadStateTree
消息处理函数。
此处列出了CQuadStateTree
处理的消息以及处理它们的函数的名称:
NM_CLICK | CQuadStateTree::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult) |
NM_TVSTATEIMAGECHANGING | CQuadStateTree::OnNMTvStateImageChanging(NMHDR *pNMHDR, LRESULT *pResult) |
TVN_KEYDOWN | CQuadStateTree::OnTvnKeydown(NMHDR *pNMHDR, LRESULT *pResult) |
TVN_ITEMCHANGED | CQuadStateTree::OnTvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult) |
TVM_SETITEM | CQuadStateTree::OnTvmSetitem(WPARAM wp, LPARAM lp) |
历史
- 2014年11月28日 - 首次发布