MFC高级控件之树状视图控件(CTreeCtrl)

“树状视图控件”是一个显示项目层次列表的窗口,例如文档中的标题、索引中的条目或磁盘上的文件和目录。每个项目都由一个标签和一个可选的位图图像组成,每个项目都可以有一个与其相关联的子项目列表。通过单击项目,用户可以展开和折叠子项目的关联列表。CTreeCtrl类提供了Windows通用树状视图控件的功能

CTreeCtrl类的父类为CWnd。要使用CTreeCtrl类,需包含的头文件为afxcmn.h,即:#include

可用Create函数创建树状视图控件并与一个CTreeCtrl对象关联。CTreeCtrl类的Create函数原型如下:

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

返回值:
如果初始化成功则返回非零值;否则返回0。

参数:

dwStyle 指定tree view控件的风格。可以对这个控件使用tree view控件风格的任意组合。
rect 指定tree view控件的尺寸和位置。此参数可以是一个CRect对象或一个RECT结构。
pParentWnd 指定tree view控件的父窗口,通常是一个CDialog。它不能是NULL。
nID 指定tree view控件的ID。


说明:
构造一个CTreeCtrl要分两步。首先调用构造函数,然后调用Create来创建这个tree view控件并将它与该CTeeCtrl对象连接。
下面的风格可以应用到一个tree view控件:

· TVS_HASLINES tree view控件的子项与它们的父项之间用线连接。
· TVS_LINESATROOT tree view控件用线连接子项和根项。
· TVS_HASBUTTONS tree view在每一个父项的左边添加一个按钮。
· TVS_EDITLABELS tree view控件允许用户编辑tree view项的标签。
· TVS_SHOWSELALWAYS 当tree view失去焦点时,使被选择的项仍然保持被选择。
· TVS_DISABLEDRAGDROP 该tree view控件被禁止发送。
· TVN_BEGINDRAG 通知消息。
· TVS_NOTOOLTIPS tree view控件使用工具提示。
· TVS_SINGLEEXPAND 当使用这个风格时,改变在tree view中的选择将导致正被选择的项展开,而没有被选择的项收缩。如果用鼠标单击被选择的项,并且该项是关闭的,则该项就会展开。如果该被选择的项被单击时是打开的,则它就会收缩。

CTreeCtrl类还有以下成员函数:

属性

GetCount 获取与一个treeview控件相关联的tree项的数目
GetIndent 获取一个tree view项对它的父项的偏移(以像素表示)
SetIndent 设置一个tree view项对它的父项的偏移(以像素表示)
GetImageList 获取与一个tree view控件相关联的图像列表的句柄
SetImageList 设置与一个tree view控件相关联的图像列表的句柄
GetNextItem 获取与指定的关系匹配的下一个tree view项
ItemHasChildren 如果指定项有子项则返回非零值
GetChildItem 获取一个指定tree view项的子项
GetNextSiblingItem 获取指定tree view项的下一个兄弟项
GetPrevSiblingItem 获取指定tree view项的前一个兄弟项
GetParentItem 获取指定tree view项的父项
GetFirstVisibleItem 获取指定tree view项的第一个可视项
GetNextVisibleItem 获取指定tree view项的下一个可视项
GetPrevVisibleItem 获取指定tree view项的前一个可视项
GetSelectedItem 获取当前被选择的tree view项
GetDropHilightItem 获取一次拖放操作的目标
GetRootItem 获取指定tree view项的根
GetItem 获取一个指定tree view项的属性
SetItem 设置一个指定tree view项的属性
GetItemState 返回一个项的状态
SetItemState 设置一个项的状态
GetItemImage 获取与一个项相关联的图像
SetItemImage 设置与一个项相关联的图像
GetItemText 返回一个项的文本
SetItemText 设置一个项的文本
GetItemData 返回与一个项关联的32位的应用程序指定值
SetItemData 设置与一个项关联的32位的应用程序指定值
GetItemRect 获取一个tree view项的边界矩形
GetEditControl 获取用来编辑指定tree view项的编辑控件的句柄
GetVisibleCount 获取与一个tree view项关联的可视tree项的编号
GetToolTips 获取一个tree view控件使用的子ToolTip控件的的句柄
SetToolTips 设置一个tree view控件的子ToolTip控件的的句柄
GetBkColor 获取控件的当前背景颜色
SetBkColor 设置控件的背景颜色
GetItemHeight 获取tree view项的当前高度
SetItemHeight 设置tree view项的当前高度
GetTextColor 获取控件的当前文本颜色
SetTextColor 设置控件的文本颜色
SetInsertMark 设置一个tree view控件的插入标记
GetCheck 获取一个tree控件项的核选状态
SetCheck 设置一个tree控件项的核选状态
GetInsertMarkColor 获取tree view用来绘制插入标记的颜色
SetInsertMarkColor 设置tree view用来绘制插入标记的颜色


操作

InsertItem 在一个tree view控件中插入一个新项。
DeleteItem 从一个tree view控件中删除一个项
DeleteAllItems 从一个tree view控件中删除所有的项
Expand 展开或收缩指定tree view项的子项
Select 选择,在视中滚动,或重画一个指定的tree view项
SelectItem 选择一个指定的tree view项
SelectDropTarget 重画作为一次拖放操作的目标的tree项
SelectSetFirstVisible 选择一个指定的tree view项作为第一个可视项
EditLabel 现场编辑一个指定的tree view项
HitTest 返回与CtreeCtrl关联的光标的当前位置
CreateDragImage 为指定的tree view项创建一个拖动位图
SortChildren 排序一个给定父项的子项
EnsureVisible 确保一个tree view项在它的tree view控件中是可视的
SortChildrenCB 使用一个由应用程序定义的排序函数来排列一个给定父项的子项

下面以实例演示树状视图控件的创建,及其常用成员函数的使用。

1.创建一个MFC对话框项目CTreeTest,然后在对话框的头文件中声明一个CTreeCtrl变量m_TreeCtrl;,如下:

// CCTreeTestDlg 对话框
class CCTreeTestDlg : public CDialogEx
{
// 构造
public:
	CCTreeTestDlg(CWnd* pParent = nullptr);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_CTREETEST_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CTreeCtrl m_TreeCtrl;
};

2. 在OnInitDialog()中加入生成、显示树状视图的代码,如下:

BOOL CCTreeTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_TreeCtrl.Create(TVS_HASLINES, CRect(0, 0, 0, 0), this, 0x1005);
	m_TreeCtrl.MoveWindow(20,20,200,300);
	m_TreeCtrl.ShowWindow(SW_SHOW);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

添加的代码为:

 点击菜单“调试”“开始执行(不调试)”,结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第1张图片

 对话框中显示出一个白色矩形框,这就是通过代码创建的树状视图控件。当然我们也可以通过将工具箱中的树状视图控件拖到对话框中来创建,如下图:

MFC高级控件之树状视图控件(CTreeCtrl)_第2张图片

  点击菜单“调试”“开始执行(不调试)”,结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第3张图片

 多出了一个矩形白框,这个白框就是新添加的树状视图控件。

3. 插入内容 (从工具箱添加的CTreeCtrl控件需关联一个CTreeCtrl变量,再通代码实现),在OnInitDialog()中继续添加代码如下:

 插入该代码段的OnInitDialog()函数如下:

BOOL CCTreeTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_TreeCtrl.Create(TVS_HASLINES, CRect(0, 0, 0, 0), this, 0x1005);
	m_TreeCtrl.MoveWindow(20,20,200,300);
	m_TreeCtrl.ShowWindow(SW_SHOW);
	HTREEITEM Grades = m_TreeCtrl.InsertItem(_T("Grade"),0,0);
	HTREEITEM Grade1= m_TreeCtrl.InsertItem(_T("Grade 1"), 1, 1, Grades);
	HTREEITEM Grade2 = m_TreeCtrl.InsertItem(_T("Grade 2"), 1, 1, Grades);
	HTREEITEM Grade3 = m_TreeCtrl.InsertItem(_T("Grade 3"), 1, 1, Grades);
	m_TreeCtrl.Expand(Grades, TVE_EXPAND);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

执行程序(不调试),结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第4张图片

 Expand函数用于展开或收缩Tree View项的子,其原型如下:

BOOL Expand( HTREEETEM hItem, UINT nColor );

返回值:如果成功则返回非零值;否则返回0。

参数:

hItem 要被扩展的tree项的句柄。
nCode 用来指示要被进行的动作的标志。这个标志可以是下列值之一:
· TVE_COLLAPSE 收缩列表。
· TVE_COLLAPSERESET 收缩列表并删除子项。
· TVE_EXPAND 展开列表。
· TVE_TOGGLE 如果列表当前是展开的则收缩列表;反之则展开列表

注释掉含Expand函数的代码行,执行结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第5张图片

 说明在没有调用该函数时,子项是收缩的,如果不明白这点,可能会误以为添加子项失败。

继续添加如下代码:

MFC高级控件之树状视图控件(CTreeCtrl)_第6张图片

 插入该代码段的OnInitDialog()函数如下:

BOOL CCTreeTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_TreeCtrl.Create(TVS_HASLINES, CRect(0, 0, 0, 0), this, 0x1005);
	m_TreeCtrl.MoveWindow(20,20,200,300);
	m_TreeCtrl.ShowWindow(SW_SHOW);
	HTREEITEM Grades = m_TreeCtrl.InsertItem(_T("Grade"),0,0);
	HTREEITEM Grade1= m_TreeCtrl.InsertItem(_T("Grade 1"), 1, 1, Grades);
	HTREEITEM Grade2 = m_TreeCtrl.InsertItem(_T("Grade 2"), 1, 1, Grades);
	HTREEITEM Grade3 = m_TreeCtrl.InsertItem(_T("Grade 3"), 1, 1, Grades);
	m_TreeCtrl.Expand(Grades, TVE_EXPAND);
	m_TreeCtrl.InsertItem(_T("张三"), 2, 2, Grade1);
	m_TreeCtrl.InsertItem(_T("李军"), 2, 2, Grade1);
	m_TreeCtrl.InsertItem(_T("王勇"), 2, 2, Grade1);
	m_TreeCtrl.InsertItem(_T("王强"), 2, 2, Grade1);
	m_TreeCtrl.InsertItem(_T("刘梅"), 2, 2, Grade2);
	m_TreeCtrl.InsertItem(_T("李辉"), 2, 2, Grade2);
	m_TreeCtrl.InsertItem(_T("刘伟"), 2, 2, Grade2);
	m_TreeCtrl.InsertItem(_T("萧蔷"), 2, 2, Grade2);
	m_TreeCtrl.InsertItem(_T("陈蔷"), 2, 2, Grade3);
	m_TreeCtrl.InsertItem(_T("刘胜"), 2, 2, Grade3);
	m_TreeCtrl.InsertItem(_T("李希"), 2, 2, Grade3);
	m_TreeCtrl.InsertItem(_T("王敏"), 2, 2, Grade3);
	m_TreeCtrl.Expand(Grade1, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade2, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade3, TVE_EXPAND);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

执行程序(不调试),结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第7张图片

 上面的代码段中仿佛用到了函数InsertItem,修改上面代码中InsertItem函数的参数如下:

BOOL CCTreeTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_TreeCtrl.Create(TVS_HASLINES, CRect(0, 0, 0, 0), this, 0x1005);
	m_TreeCtrl.MoveWindow(20,20,200,300);
	m_TreeCtrl.ShowWindow(SW_SHOW);
	HTREEITEM Grades = m_TreeCtrl.InsertItem(_T("Grade"),0,0);
	HTREEITEM Grade1= m_TreeCtrl.InsertItem(_T("Grade 1"), 1, 1, Grades);
	HTREEITEM Grade2 = m_TreeCtrl.InsertItem(_T("Grade 2"), 1, 1, Grades);
	HTREEITEM Grade3 = m_TreeCtrl.InsertItem(_T("Grade 3"), 1, 1, Grades);
	m_TreeCtrl.Expand(Grades, TVE_EXPAND);
	m_TreeCtrl.InsertItem(_T("张三"), 0, 0, Grade1);
	m_TreeCtrl.InsertItem(_T("李军"), 0, 0, Grade1);
	m_TreeCtrl.InsertItem(_T("王勇"), 0, 0, Grade1);
	m_TreeCtrl.InsertItem(_T("王强"), 2, 0, Grade1);
	m_TreeCtrl.InsertItem(_T("刘梅"), 2, 1, Grade2);
	m_TreeCtrl.InsertItem(_T("李辉"), 2, 2, Grade2);
	m_TreeCtrl.InsertItem(_T("刘伟"), 2, 3, Grade2);
	m_TreeCtrl.InsertItem(_T("萧蔷"), 2, 4, Grade2);
	m_TreeCtrl.InsertItem(_T("陈蔷"), 3,3, Grade3);
	m_TreeCtrl.InsertItem(_T("刘胜"), 3, 3, Grade3);
	m_TreeCtrl.InsertItem(_T("李希"), 3, 3, Grade3);
	m_TreeCtrl.InsertItem(_T("王敏"), 3, 3, Grade3);
	m_TreeCtrl.Expand(Grade1, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade2, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade3, TVE_EXPAND);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

执行程序(不调试),结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第8张图片

 奇怪,尽管参数变了,执行结果确是一样的。下面来看一下InsertItem函数,器原型如下:

HTREEITEM InsertItem( LPTVINSERTSTRUCT lpInsertStruct );

HTREEITEM InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam, HTREEITEM hParent, HTREEITEM hInsertAfter );

HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST );

HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);

Return Value

Handle of the new item if successful; otherwise NULL.

参数:

lpInsertStruct 一个指向用来指定要插入的tree view项的属性的TVINSERTSTRUCT的指针。
nMask 用来指定要设置的属性的整数。
lpszItem 一个包含项的文本的字符串的地址。
nImage 项的图像在tree view控件的图像列表中的索引。
nSelectedImage 项的被选择图像在tree view控件的图像列表中的索引。
nState 为项的状态指定的值。
nStateMask 指定要设置的状态。
lParam 与此项关联的一个32位的应用程序指定的值。
hParent 要被插入的项的父项的句柄。
hInsertAfter 新项要被插入其后的项的句柄。

实际上我们用的是最后一个原型函数,变更到的是与图像有关的参数,由于没有设定相关的图像列表,所以这个变更并不影响显示结果。此时使用第三个原型函数更好,修改OnInitDialog()函数中的代码如下:

BOOL CCTreeTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_TreeCtrl.Create(TVS_HASLINES, CRect(0, 0, 0, 0), this, 0x1005);
	m_TreeCtrl.MoveWindow(20,20,200,300);
	m_TreeCtrl.ShowWindow(SW_SHOW);
	HTREEITEM Grades = m_TreeCtrl.InsertItem(_T("Grade"));
	HTREEITEM Grade1= m_TreeCtrl.InsertItem(_T("Grade 1"),Grades);
	HTREEITEM Grade2 = m_TreeCtrl.InsertItem(_T("Grade 2"), Grades);
	HTREEITEM Grade3 = m_TreeCtrl.InsertItem(_T("Grade 3"), Grades);
	m_TreeCtrl.Expand(Grades, TVE_EXPAND);
	m_TreeCtrl.InsertItem(_T("张三"),Grade1);
	m_TreeCtrl.InsertItem(_T("李军"), Grade1);
	m_TreeCtrl.InsertItem(_T("王勇"),Grade1);
	m_TreeCtrl.InsertItem(_T("王强"),Grade1);
	m_TreeCtrl.InsertItem(_T("刘梅"), Grade2);
	m_TreeCtrl.InsertItem(_T("李辉"),Grade2);
	m_TreeCtrl.InsertItem(_T("刘伟"), Grade2);
	m_TreeCtrl.InsertItem(_T("萧蔷"), Grade2);
	m_TreeCtrl.InsertItem(_T("陈蔷"),Grade3);
	m_TreeCtrl.InsertItem(_T("刘胜"), Grade3);
	m_TreeCtrl.InsertItem(_T("李希"), Grade3);
	m_TreeCtrl.InsertItem(_T("王敏"),Grade3);
	m_TreeCtrl.Expand(Grade1, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade2, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade3, TVE_EXPAND);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

执行程序(不调试),结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第9张图片

 结果一样的。当然OnInitDialog()函数中的代码修改如下,也是可以的。

BOOL CCTreeTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_TreeCtrl.Create(TVS_HASLINES, CRect(0, 0, 0, 0), this, 0x1005);
	m_TreeCtrl.MoveWindow(20,20,200,300);
	m_TreeCtrl.ShowWindow(SW_SHOW);
	HTREEITEM Grades = m_TreeCtrl.InsertItem(_T("Grade"));
	HTREEITEM Grade1= m_TreeCtrl.InsertItem(_T("Grade 1"),Grades, Grades);
	HTREEITEM Grade2 = m_TreeCtrl.InsertItem(_T("Grade 2"), Grades, Grades);
	HTREEITEM Grade3 = m_TreeCtrl.InsertItem(_T("Grade 3"), Grades, Grades);
	m_TreeCtrl.Expand(Grades, TVE_EXPAND);
	m_TreeCtrl.InsertItem(_T("张三"), Grade1,Grade1);
	m_TreeCtrl.InsertItem(_T("李军"), Grade1, Grade1);
	m_TreeCtrl.InsertItem(_T("王勇"),Grade1, Grade1);
	m_TreeCtrl.InsertItem(_T("王强"),Grade1, Grade1);
	m_TreeCtrl.InsertItem(_T("刘梅"), Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("李辉"),Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("刘伟"), Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("萧蔷"), Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("陈蔷"),Grade3, Grade3);
	m_TreeCtrl.InsertItem(_T("刘胜"), Grade3, Grade3);
	m_TreeCtrl.InsertItem(_T("李希"), Grade3, Grade3);
	m_TreeCtrl.InsertItem(_T("王敏"),Grade3, Grade3);
	m_TreeCtrl.Expand(Grade1, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade2, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade3, TVE_EXPAND);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

如果当一个项目含有子项时,当未展开时,前面需出现个+号,如何处理呢,只需修改函数参数如下即可(或上了TVS_HASBUTTONS):

m_TreeCtrl.Create(TVS_HASLINES|TVS_HASBUTTONS, CRect(0, 0, 0, 0), this, 0x1005);

执行程序(不调试),结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第10张图片

4. 事件响应 为动态添加的CTreeCtrl控件添加事件处理函数相对比较麻烦,这里以从工具箱添加到对话框中的CTreeCtrl控件为例,演示添加事件处理函数。

首选将控件关联一个变量(已经添加好,所以为灰色),如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第11张图片

 修改控件属性如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第12张图片

 修改OnInitDialog()函数中的代码如下:

BOOL CCTreeTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_TreeCtrl.Create(TVS_HASLINES|TVS_HASBUTTONS, CRect(0, 0, 0, 0), this, 0x1005);
	m_TreeCtrl.MoveWindow(20,20,200,300);
	m_TreeCtrl.ShowWindow(SW_SHOW);
	HTREEITEM Grades = m_TreeCtrl.InsertItem(_T("Grade"));
	HTREEITEM Grade1= m_TreeCtrl.InsertItem(_T("Grade 1"),Grades, Grades);
	HTREEITEM Grade2 = m_TreeCtrl.InsertItem(_T("Grade 2"), Grades, Grades);
	HTREEITEM Grade3 = m_TreeCtrl.InsertItem(_T("Grade 3"), Grades, Grades);
	m_TreeCtrl.Expand(Grades, TVE_EXPAND);
	m_TreeCtrl.InsertItem(_T("张三"), Grade1,Grade1);
	m_TreeCtrl.InsertItem(_T("李军"), Grade1, Grade1);
	m_TreeCtrl.InsertItem(_T("王勇"),Grade1, Grade1);
	m_TreeCtrl.InsertItem(_T("王强"),Grade1, Grade1);
	m_TreeCtrl.InsertItem(_T("刘梅"), Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("李辉"),Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("刘伟"), Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("萧蔷"), Grade2, Grade2);
	m_TreeCtrl.InsertItem(_T("陈蔷"),Grade3, Grade3);
	m_TreeCtrl.InsertItem(_T("刘胜"), Grade3, Grade3);
	m_TreeCtrl.InsertItem(_T("李希"), Grade3, Grade3);
	m_TreeCtrl.InsertItem(_T("王敏"),Grade3, Grade3);
	m_TreeCtrl.Expand(Grade1, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade2, TVE_EXPAND);
	m_TreeCtrl.Expand(Grade3, TVE_EXPAND);


	
	HTREEITEM Grades2 = m_CTreeCtrl2.InsertItem(_T("Grade"));
	HTREEITEM Grade2_1 = m_CTreeCtrl2.InsertItem(_T("Grade 1"),Grades2);
	HTREEITEM Grade2_2 = m_CTreeCtrl2.InsertItem(_T("Grade 2"),Grades2);
	HTREEITEM Grade2_3 = m_CTreeCtrl2.InsertItem(_T("Grade 3"),Grades2);
	m_CTreeCtrl2.Expand(Grades2, TVE_EXPAND);
	m_CTreeCtrl2.InsertItem(_T("张三"), Grade2_1);
	m_CTreeCtrl2.InsertItem(_T("李军"), Grade2_1);
	m_CTreeCtrl2.InsertItem(_T("王勇"), Grade2_1);
	m_CTreeCtrl2.InsertItem(_T("王强"), Grade2_1);
	m_CTreeCtrl2.InsertItem(_T("刘梅"), Grade2_2);
	m_CTreeCtrl2.InsertItem(_T("李辉"), Grade2_2);
	m_CTreeCtrl2.InsertItem(_T("刘伟"), Grade2_2);
	m_CTreeCtrl2.InsertItem(_T("萧蔷"), Grade2_2);
	m_CTreeCtrl2.InsertItem(_T("陈蔷"), Grade2_3);
	m_CTreeCtrl2.InsertItem(_T("刘胜"), Grade2_3);
	m_CTreeCtrl2.InsertItem(_T("李希"), Grade2_3);
	m_CTreeCtrl2.InsertItem(_T("王敏"), Grade2_3);
	m_CTreeCtrl2.Expand(Grade2_1, TVE_EXPAND);
	m_CTreeCtrl2.Expand(Grade2_2, TVE_EXPAND);
	m_CTreeCtrl2.Expand(Grade2_3, TVE_EXPAND);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

执行程序(不调试),结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第13张图片

 添加事件处理函数 ,选中类视图中的·CCTreeTestDlg,

MFC高级控件之树状视图控件(CTreeCtrl)_第14张图片

按鼠标右键选中属性,进入属性列表,如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第15张图片

点击事件图标,选中IDC_TREE2,可看到事件列表如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第16张图片

 这里选中TVN_SELCHANGED,并添加事件处理函数,如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第17张图片

 添加的事件处理函数如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第18张图片

我们在该函数中添加代码,完成后如下:

void CCTreeTestDlg::OnTvnSelchangedTree2(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	HTREEITEM mitem = m_CTreeCtrl2.GetSelectedItem();
	CString str = m_CTreeCtrl2.GetItemText(mitem);
	CString str1;
	str1.Format(_T("你选中的是%s"), str);
	MessageBox(str1);
	*pResult = 0;
}

执行程序(不调试),结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第19张图片

 点击右边CTreeCtrl中的“王敏:,结果如下:

MFC高级控件之树状视图控件(CTreeCtrl)_第20张图片

 CTreeCtrl控件有很多成员函数,这里就不一一演示了,需进一步了解其使用可查阅MSDNLibrary。

你可能感兴趣的:(MFC,C语言,C++,CTreeCtrl控件,CTreeCtrl控件详解,CTreeCtrl控件示例,CTreeCtrl控件实例)