MFC应用技术之CTreeControl的使用
MFC应用技术之CTreeControl的使用
一丶MFC添加树控件.添加父节点跟子节点.
MFC上面放一个树控件.并未这个树控件绑定变量.然后添加一个按钮.按钮的作用就是添加父节点跟子节点.
PS: 关于MFC如果添加控件.这里不做讲解.此篇只用于应用.所以常用的都会列举出来.
树控件添加结点注意用的 方法是 InsertItem()
这个方法是重载的有很多种. 这里只讲解自己常用的一种.其余的查询MSDN即可.
添加父节点跟子节点.
void CTreeControlDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
HTREEITEM Root = m_RootControl.InsertItem(_T("父节点")); 返回一个句柄
m_RootControl.InsertItem(_T("子节点5"), Root,TVI_SORT); 继续调用这个方法添加的时候.参数二是父节点返回的句柄.则添加结点到父节点下面. 参数三是排序的意思.可以默认不加.
m_RootControl.InsertItem(_T("子节点4"), Root, TVI_SORT);
m_RootControl.InsertItem(_T("子节点3"), Root, TVI_SORT);
m_RootControl.InsertItem(_T("子节点2"), Root, TVI_SORT);
m_RootControl.InsertItem(_T("子节点1"), Root, TVI_SORT); }
应用截图:

二丶获取树控件父节点以及子节点
获取树控件父节点 方法是 GetRootItem() 返回的Item句柄就是父节点. GetChildItem() 则是获取子节点.传入父节点.返回子节点.
GetItemText(句柄) 返回这个句柄的字符串. GetParentItem() 获取子节点的父节点.
看如下代码:
void CTreeControlDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
HTREEITEM Root = m_RootControl.GetRootItem(); //获取顶层结点.
HTREEITEM ChildItem = m_RootControl.GetChildItem(Root);
CString strText = m_RootControl.GetItemText(ChildItem);
AfxMessageBox(strText);
}
应用截图:

三丶根据根节点获取兄弟结点
获取根节点我们知道了.就是GetRootItem(); 那么获取兄弟结点是什么意思?
意思就是兄弟的意思. 假设我们有三个父结点.
父结点0
父节点1
父节点2
我们首先获取父节点0的Item 然后继续获取他的兄弟结点.兄弟结点就是父节点1
方法: GetNextSiblingItem() 获取指定结点的下一个兄弟
方法: GetPrevSiblingItem(); 获取指定结点的上一个兄弟.
具体代码例子:
void CTreeControlDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
HTREEITEM Root = m_RootControl.GetRootItem(); //获取根节点
HTREEITEM BrothorItem = m_RootControl.GetNextSiblingItem(Root);//获取跟结点的下一个兄弟结点 CString strText = m_RootControl.GetItemText(BrothorItem); //获取兄弟结点的文本穿
AfxMessageBox(strText); }
应用截图:

获取上一个兄弟结点
void CTreeControlDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
HTREEITEM Root = m_RootControl.GetRootItem(); HTREEITEM BrothorItem1 = m_RootControl.GetNextSiblingItem(Root); //获取下一个兄弟结点 这里我们要先获取下一个兄弟.因为根节点的上一个兄弟没有了. HTREEITEM BrothorItem2 = m_RootControl.GetPrevSiblingItem(BrothorItem1); //获取上一个兄弟 这里就是获取第二个节点的上一个兄弟,也就是父节点0 CString strText = m_RootControl.GetItemText(BrothorItem2);
AfxMessageBox(strText); }
应用截图:

四丶根据指定结点.递归遍历下面所有子节点.
上面都是简单的使用. 所以真正使用我们要遍历结点. 比如遍历父节点下面的所有子节点.
递归遍历:
1.递归遍历指定结点下面所有的子节点
void CTreeControlDlg::OnBnClickedButton5()
{
// TODO: 在此添加控件通知处理程序代码
//1.获取根节点
HTREEITEM RootItem = m_RootControl.GetRootItem();
IteratorTreeChild(RootItem);
} void CTreeControlDlg::IteratorTreeChild(HTREEITEM item)
{
CString strText = m_RootControl.GetItemText(item); //获取字符串.并且弹出.
AfxMessageBox(strText); //定义两个结点.一个当前结点.一个下一个结点.
HTREEITEM CurItem;
HTREEITEM NextItem; CurItem = m_RootControl.GetChildItem(item); //当前结点是子节点.
while (CurItem != NULL)
{
//继续遍历集结点.
NextItem = CurItem;
IteratorTreeChild(NextItem);
CurItem = m_RootControl.GetNextSiblingItem(NextItem);
}
}
代码只打印了.
1.传入根节点.
2.定义两个结点.
3.当前结点是子节点的Item
4.下一个结点也是Item
5.递归遍历.
6.如果没有.则获取下一个子节点.也就是子节点的兄弟结点.
实现截图:

2.循环遍历指定结点下面的一层子节点
上图是递归遍历所有子节点.但是有的时候我们只需要遍历一层即可.
例如下图: 我们只需要遍历到子节点5.

实现代码:
void CTreeControlDlg::IteratorTreeChild2(HTREEITEM item) //循环遍历当前父节点的子节点.不深层遍历
{
HTREEITEM CurrItem = m_RootControl.GetChildItem(item); // 获取子节点句柄
CString strText;
while (CurrItem)
{
strText = m_RootControl.GetItemText(CurrItem);
AfxMessageBox(strText);
CurrItem = m_RootControl.GetNextSiblingItem(CurrItem); //获取子节点的兄弟结点即可.
}
} void CTreeControlDlg::OnBnClickedButton6()
{
// TODO: 在此添加控件通知处理程序代码
HTREEITEM RootItem = m_RootControl.GetRootItem(); //根据根节点遍历根节点下面的一层子节点.
IteratorTreeChild2(RootItem);
}
3.递归遍历所有父节点下面的所有子节点
如果我们要遍历所有父节点.跟他的子节点. 则需要稍微更改下代码即可.也就是第一种代码的改进.
实现代码:
void CTreeControlDlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码 HTREEITEM RootItem = m_RootControl.GetRootItem();
do
{
IteratorTreeChild1(RootItem); //递归方法是第一种里面的.所以不再重复写了
} while ((RootItem = m_RootControl.GetNextSiblingItem(RootItem)) != NULL); //主要就是这里.循环遍历父节点的兄弟结点. }

4.循环遍历所有父节点下的第一层子节点.
上面的是遍历父节点下的子节点. 所有的子节点. 子节点的子节点也遍历.但是我们只需要遍历一层
void CTreeControlDlg::OnBnClickedButton7()
{
// TODO: 在此添加控件通知处理程序代码 HTREEITEM RootItem = m_RootControl.GetRootItem();
HTREEITEM CurItem;
CString strText;
do
{
CurItem = m_RootControl.GetChildItem(RootItem); //双层循环.第一层遍历父节点.第二层遍历子节点的兄弟结点.
while (CurItem)
{
strText = m_RootControl.GetItemText(CurItem);
AfxMessageBox(strText); CurItem = m_RootControl.GetNextSiblingItem(CurItem);
} } while ((RootItem = m_RootControl.GetNextSiblingItem(RootItem)) != NULL); }
常用的遍历差不多就这些了.我们看下响应时间消息
五丶事件消息
树控件的消息有如下.
通知消息说明
TVN_BEGINDRAG指示拖放操作的开始。
TVN_BEGINLABELEDIT将通知开始就地编辑标签
TVN_BEGINRDRAG使用鼠标右键,终止拖放操作的开始,
TVN_DELETEITEM标志着特定中删除项
TVN_ENDLABELEDIT信号的结束编辑标签
TVN_GETDISPINFO请求树控件需要显示的项的信息。
TVN_ITEMEXPANDED子项父项的列表展开或折叠的信号
TVN_ITEMEXPANDING子项的父项列表会展开或折叠的信号
TVN_KEYDOWN信号键盘事件
TVN_SELCHANGE信号从中选择一项更改为另一个架构
TVN_SELCHANGING指示选定项即将从一项变为另一项
TVN_GETDISPINFO更新的信息通知为维护项
具体可以查询MSDN

MSDN 链接: https://technet.microsoft.com/zh-cn/library/38x8htxs.aspx/
关于我们主要讲解 TVN_SELCHANGE 也就是当选择则会改变.
如果添加事件消息.那么会有如下代码.
void CTreeControlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码 *pResult = ;
}
这个是给我们默认添加的. 而返回值是微软已经给我们转好的.所以我们需要的信息就在里面.我们可以看下结构内容.
LPNMTREEVIEW 这是一个宏.宽版本还是A版本. 熟悉Windows的都应该知道.
看下对应的结构
typedef struct tagNMTREEVIEWW {
NMHDR hdr;
UINT action;
TVITEMW itemOld; 旧的Item
TVITEMW itemNew; 当前点击的Item
POINT ptDrag; 坐标
} NMTREEVIEWW, *LPNMTREEVIEWW;
里面有一个新的结构体.也就是 TVITEMW
看下这个结构里面内容.
typedef struct tagTVITEMW {
UINT mask;
HTREEITEM hItem; 当前的hitem结构
UINT state; 状态.
UINT stateMask;
LPWSTR pszText; 文本.
int cchTextMax;
int iImage; 图像
int iSelectedImage; 选择图形
int cChildren;
LPARAM lParam; 附加参数
} TVITEMW, *LPTVITEMW;
当然上面是我自己理解的然后加的注释.不过没有错误. 而我们常用的就是 hitem结构.
所以如果我们要获取选择项的item文本就用如下代码.
void CTreeControlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码 HTREEITEM Root = pNMTreeView->itemNew.hItem;
CStringW str = m_RootControl.GetItemText(Root);
AfxMessageBox(str);
*pResult = ;
}
或者是点击子节点.获取她的父节点.
void CTreeControlDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码 HTREEITEM Child = pNMTreeView->itemNew.hItem;
HTREEITEM Root = m_RootControl.GetParentItem(Child);
CString str = m_RootControl.GetItemText(Root);
AfxMessageBox(str);
*pResult = ;
}
MFC应用技术之CTreeControl的使用的更多相关文章
- MFC 框架技术简单研讨
引用:http://www.cnblogs.com/chinazhangjie/archive/2011/09/20/2181986.html 正文: 第一讲 Win32 App 和 MFC Fr ...
- MFC多线程技术
MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没笑消息机制,通常用来执行后台计算和维护任务,如 ...
- VC++ MFC橡皮筋技术
在MFC下绘制直线,使用橡皮筋技术,可以使直线效果跟随鼠标移动 //OnLButtionDown m_ptOrigin = m_ptEnd = point; //OnMouseMove ...
- MFC类别概述
MFC 类别主要可分为下列数大群组: ■ General Purpose classes - 提供字符串类别.数据处理类别(如数组与串行),异 常情况处理类别.文件类别...等等. ■ Windows ...
- MFC 简介
参考:https://baike.baidu.com/item/MFC/2236974 MFC (微软基础类库) 编辑 锁定 讨论999 MFC(Microsoft Foundation Clas ...
- 基于VC++的网络扫描器设计与实现
本文正文其实是自己的毕业论文,现在搬上来有两个原因. 一是之前大学的文档都放在百度网盘上,大概去年的时候百度网盘改版搞得不太稳定,文件夹移动次数一多里边就会有一些文件丢失了,也没有很在意.但前几天看申 ...
- VC++/MFC(VC6)开发技术精品学习资料下载汇总
工欲善其事,必先利其器,VC开发MFC Windows程序,Visual C++或Visual Studio是必须的,恩,这里都给你总结好了,拿去吧:VC/MFC开发必备Visual C++.Visu ...
- 十年MFC经历认识的Microsoft技术 [转]
十年MFC经历认识的Microsoft技术[原创] 孙辉 自从2005年3月8日下午16时“十年MFC经历认识的Microsoft技术”以帖子的方式发表于CSDN论坛后,引起了许多网友得好评,使得笔者 ...
- 《MFC游戏开发》笔记六 图像双缓冲技术:实现一个流畅的动画
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9334121 作者:七十一雾央 新浪微博:http:/ ...
随机推荐
- intent和手势探测
一.三种启动方法 setComponent ComponentName comp = new ComponentName( this, SecondActivity.class); Intent in ...
- UML model refactoring: a systematic literature review
一.基本信息 标题:UML model refactoring: a systematic literature review 时间:2015 出版源:Empirical Software Engin ...
- 可遇不可求的Question之MySqlClient的Guid 类型的映射篇
关于 Guid 类型的映射 MySql 没有原生的 Guid 类型,一般使用 binary(16) 或者 char(36) 这两个类型.早期版本的 Connector/Net 将 binary(16) ...
- Runtime "Apache Tomcat v6.0 (3)" is invalid. The JRE could not be found. Edit the server and change the JRE location解决方案
使用eclipse,启动Tomcat时出现The JRE could not be found ,Edit server and change teh JRE location的错误提示! 原因:重装 ...
- STM32CubeMX+Keil裸机代码风格(1)
1.打开STM32CubeMX,New project 选好自己要用的芯片 2.选上左侧SYS中的debug Serial Wire(定义烧程序的端口) . 3,选上左侧TIM6,使TIM6可用(TI ...
- vue组件通信新姿势
在vue项目实际开发中我们经常会使用props和emit来进行子父组件的传值通信,父组件向子组件传递数据是通过prop传递的, 子组件传递数据给父组件是通过$emit触发事件来做到的.例如: Vue. ...
- 背水一战 Windows 10 (111) - 通知(Tile): secondary tile 模板之图片, secondary tile 模板之分组
[源码下载] 背水一战 Windows 10 (111) - 通知(Tile): secondary tile 模板之图片, secondary tile 模板之分组 作者:webabcd 介绍背水一 ...
- 第78节:Java中的网络编程(上)
第78节:Java中的网络编程(上) 前言 网络编程涉及ip,端口,协议,tcp和udp的了解,和对socket通信的网络细节. 网络编程 OSI开放系统互连 网络编程指IO加网络 TCP/IP模型: ...
- 【详记MySql问题大全集】三、安装之后没有my.ini配置文件怎么办
系列目录 一.安装MySql 二.安装并破解Navicat 三.没有my.in配置文件怎么办 四.设置MySql的大小写敏感 五.重置MySql登陆密码 之前说过,Windows操作系统中,我们安装M ...
- eureka相关异常
1. eureka相关异常 1.1. 异常信息 Error creating bean with name 'eurekaAutoServiceRegistration': Singleton bea ...