树形Control控件可以用于树形
![](/icons/56993de.gif)
结构
![](/icons/56993dou.gif)
其中有
![](/icons/56993yi.gif)
个根接点(Root)然后下面有许多子结点
![](/icons/56993dou.gif)
而每个子结点上有允许有
![](/icons/56993yi.gif)
个或多个或没有子结点
![](/icons/56993dou2.gif)
MFC中使用CTreeCtrl类来封装树形Control控件
![](/icons/56993de.gif)
各种操作
![](/icons/56993dou2.gif)
通过
![](/icons/56993diaoyong.gif)
BOOLCreate(DWORDdwStyle,constRECT&rect,CWnd*pParentWnd,UINTnID);创建
![](/icons/56993yi.gif)
个窗口
![](/icons/56993dou.gif)
dwStyle中可以使用以下
![](/icons/56993yi.gif)
些树形Control控件
![](/icons/56993de.gif)
专用风格:
TVS_HASLINES在父/子结点的间绘制连线
TVS_LINESATROOT在根/子结点的间绘制连线
TVS_HASBUTTONS在每
![](/icons/56993yi.gif)
个结点前添加
![](/icons/56993yi.gif)
个按钮
![](/icons/56993dou.gif)
用于表示当前结点是否已被展开
TVS_EDITLABELS结点
![](/icons/56993de.gif)
显示
![](/icons/56993zifu.gif)
可以被编辑
TVS_SHOWSELALWAYS在失去焦点时也显示当前选中
![](/icons/56993de.gif)
结点
TVS_DISABLEDRAGDROP不允许Drag/Drop
TVS_NOTOOLTIPS不使用ToolTip显示结点
![](/icons/56993de.gif)
显示
![](/icons/56993zifu.gif)
在树形Control控件中每
![](/icons/56993yi.gif)
个结点都有
![](/icons/56993yi.gif)
个句柄(HTREEITEM)
![](/icons/56993dou.gif)
同时添加结点时必须提供
![](/icons/56993de.gif)
参数是该结点
![](/icons/56993de.gif)
父结点句柄
![](/icons/56993dou.gif)
(其中根Root结点只有
![](/icons/56993yi.gif)
个
![](/icons/56993dou.gif)
既不可以添加也不可以删除)利用
HTREEITEMInsertItem(LPCTSTRlpszItem,HTREEITEMhParent=TVI_ROOT,HTREEITEMhInsertAfter=TVI_LAST);可以添加
![](/icons/56993yi.gif)
个结点
![](/icons/56993dou.gif)
pszItem为显示
![](/icons/56993de.gif)
![](/icons/56993zifu.gif)
![](/icons/56993dou.gif)
hParent代表父结点
![](/icons/56993de.gif)
句柄
![](/icons/56993dou.gif)
当前添加
![](/icons/56993de.gif)
结点会排在hInsertAfter表示
![](/icons/56993de.gif)
结点
![](/icons/56993de.gif)
后面
![](/icons/56993dou.gif)
返回值为当前创建
![](/icons/56993de.gif)
结点
![](/icons/56993de.gif)
句柄
![](/icons/56993dou2.gif)
下面
![](/icons/56993de.gif)
代码会建立
![](/icons/56993yi.gif)
个如下形式
![](/icons/56993de.gif)
树形结构:+---Parent1+---Child1_1+---Child1_2+---Child1_3+---Parent2+---Parent3/*假设m_tree为
![](/icons/56993yi.gif)
个CTreeCtrl对象
![](/icons/56993dou.gif)
而且该窗口已经创建*/HTREEITEMhItem,hSubItem;hItem=m_tree.InsertItem(\"Parent1\",TVI_ROOT);在根结点上添加Parent1hSubItem=m_tree.InsertItem(\"Child1_1\",hItem);//在Parent1上添加
![](/icons/56993yi.gif)
个子结点hSubItem=m_tree.InsertItem(\"Child1_2\",hItem,hSubItem);//在Parent1上添加
![](/icons/56993yi.gif)
个子结点
![](/icons/56993dou.gif)
排在Child1_1后面hSubItem=m_tree.InsertItem(\"Child1_3\",hItem,hSubItem);hItem=m_tree.InsertItem(\"Parent2\",TVI_ROOT,hItem);hItem=m_tree.InsertItem(\"Parent3\",TVI_ROOT,hItem);如果你希望在每个结点前添加
![](/icons/56993yi.gif)
个小图标
![](/icons/56993dou.gif)
就必需先
![](/icons/56993diaoyong.gif)
CImageList*SetImageList(CImageList*pImageList,
![](/icons/56993int.gif)
nImageListType);指明当前所使用
![](/icons/56993de.gif)
ImageList
![](/icons/56993dou.gif)
nImageListType为TVSIL_NORMAL
![](/icons/56993dou2.gif)
在
![](/icons/56993diaoyong.gif)
完成后Control控件中使用图片以设置
![](/icons/56993de.gif)
ImageList中图片为准
![](/icons/56993dou2.gif)
然后
HTREEITEMInsertItem(LPCTSTRlpszItem,
![](/icons/56993int.gif)
nImage,
![](/icons/56993int.gif)
nSelectedImage,HTREEITEMhParent=TVI_ROOT,HTREEITEMhInsertAfter=TVI_LAST);添加结点
![](/icons/56993dou.gif)
nImage为结点没被选中时所使用图片序号
![](/icons/56993dou.gif)
nSelectedImage为结点被选中时所使用图片序号
![](/icons/56993dou2.gif)
下面
![](/icons/56993de.gif)
代码演示了ImageList
![](/icons/56993de.gif)
设置
![](/icons/56993dou2.gif)
/*m_list为CImageList对象IDB_TREE为16*(16*4)
![](/icons/56993de.gif)
位图
![](/icons/56993dou.gif)
每个图片为16*16共4个图标*/m_list.Create(IDB_TREE,16,4,RGB(0,0,0));m_tree.SetImageList(&m_list,TVSIL_NORMAL);m_tree.InsertItem(\"Parent1\",0,1);//添加
![](/icons/56993dou.gif)
选中时显示图标1
![](/icons/56993dou.gif)
未选中时显示图标0 [Page]
此外CTreeCtrl还提供了
![](/icons/56993yi.gif)
些
![](/icons/56993hanshu.gif)
用于得到/修改Control控件
![](/icons/56993de.gif)
状态
HTREEITEMGetSelectedItem
![](/icons/56993kh.gif)
;将返回当前选中
![](/icons/56993de.gif)
结点
![](/icons/56993de.gif)
句柄
![](/icons/56993dou2.gif)
BOOLSelectItem(HTREEITEMhItem);将选中指明结点
BOOLGetItemImage(HTREEITEMhItem,
![](/icons/56993int.gif)
&nImage,
![](/icons/56993int.gif)
&nSelectedImage)/BOOLSetItemImage(HTREEITEMhItem,
![](/icons/56993int.gif)
nImage,
![](/icons/56993int.gif)
nSelectedImage)用于得到/修改某结点所使用图标索引
CStringGetItemText(HTREEITEMhItem)/BOOLSetItemText(HTREEITEMhItem,LPCTSTRlpszItem);用于得到/修改某
![](/icons/56993yi.gif)
结点
![](/icons/56993de.gif)
显示
![](/icons/56993zifu.gif)
BOOLDeleteItem(HTREEITEMhItem);用于删除某
![](/icons/56993yi.gif)
结点
![](/icons/56993dou.gif)
BOOLDeleteAllItems
![](/icons/56993kh.gif)
;将删除所有结点
此外如果想遍历树可以使用下面
![](/icons/56993de.gif)
![](/icons/56993hanshu.gif)
:
HTREEITEMGetRootItem
![](/icons/56993kh.gif)
;得到根结点
HTREEITEMGetChildItem(HTREEITEMhItem);得到子结点
HTREEITEMGetPrevSiblingItem/GetNextSiblingItem(HTREEITEMhItem);得到指明结点
![](/icons/56993de.gif)
上/下
![](/icons/56993yi.gif)
个兄弟结点
HTREEITEMGetParentItem(HTREEITEMhItem);得到父结点
树形Control控件
![](/icons/56993de.gif)
消息映射使用ON_NOTIFY宏
![](/icons/56993dou.gif)
形式如同:ON_NOTIFY(wNot
![](/icons/56993if.gif)
yCode,id,memberFxn)
![](/icons/56993dou.gif)
wNot
![](/icons/56993if.gif)
yCode为通知代码
![](/icons/56993dou.gif)
id为产生该消息
![](/icons/56993de.gif)
窗口ID
![](/icons/56993dou.gif)
memberFxn为处理
![](/icons/56993hanshu.gif)
![](/icons/56993dou.gif)
![](/icons/56993hanshu.gif)
![](/icons/56993de.gif)
原型如同voidOnXXXTree(NMHDR*pNMHDR,LRESULT*pResult)
![](/icons/56993dou.gif)
其中pNMHDR为
![](/icons/56993yi.gif)
数据结构
![](/icons/56993dou.gif)
在具体使用时需要转换成其他类型
![](/icons/56993de.gif)
结构
![](/icons/56993dou2.gif)
对于树形Control控件可能取值和对应
![](/icons/56993de.gif)
数据结构为:
TVN_SELCHANGED在所选中
![](/icons/56993de.gif)
结点发生改变后发送
![](/icons/56993dou.gif)
所用结构:NMTREEVIEW
TVN_ITEMEXPANDED在某结点被展开后发送
![](/icons/56993dou.gif)
所用结构:NMTREEVIEW
TVN_BEGINLABELEDIT在开始编辑结点
![](/icons/56993zifu.gif)
时发送
![](/icons/56993dou.gif)
所用结构:NMTVDISPINFO
TVN_ENDLABELEDIT在结束编辑结点
![](/icons/56993zifu.gif)
时发送
![](/icons/56993dou.gif)
所用结构:NMTVDISPINFO
TVN_GETDISPINFO在需要得到某结点信息时发送
![](/icons/56993dou.gif)
(如得到结点
![](/icons/56993de.gif)
显示
![](/icons/56993zifu.gif)
)所用结构:NMTVDISPINFO有关ON_NOTIFY有很多内容
![](/icons/56993dou.gif)
将在以后
![](/icons/56993de.gif)
内容中进行详细讲解
有关动态提供结点所显示
![](/icons/56993de.gif)
![](/icons/56993zifu.gif)
:首先你在添加结点时需要指明lpszItem参数为:LPSTR_TEXTCALLBACK
![](/icons/56993dou2.gif)
在Control控件显示该结点时会通过发送TVN_GETDISPINFO来取得所需要
![](/icons/56993de.gif)
![](/icons/56993zifu.gif)
![](/icons/56993dou.gif)
在处理该消息时先将参数pNMHDR转换为LPNMTVDISPINFO
![](/icons/56993dou.gif)
然后填充其中item.pszText
![](/icons/56993dou2.gif)
但是我们通过什么来知道该结点所对应
![](/icons/56993de.gif)
信息呢
![](/icons/56993dou.gif)
我
![](/icons/56993de.gif)
做法是在添加结点后设置其lParam参数
![](/icons/56993dou.gif)
然后在提供信息时利用该参数来查找所对应
![](/icons/56993de.gif)
信息
![](/icons/56993dou2.gif)
下面
![](/icons/56993de.gif)
代码介绍说明了这种思路方法:charszOut[8][3]={\"No.1\",\"No.2\",\"No.3\"};//添加结点HTREEITEMhItem=m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)m_tree.SetItemData(hItem,0);hItem=m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)m_tree.SetItemData(hItem,1);//处理消息voidCParentWnd::OnGetDispInfoTree(NMHDR*pNMHDR,LRESULT*pResult){TV_DISPINFO*pTVDI=(TV_DISPINFO*)pNMHDR;pTVDI->item.pszText=szOut[pTVDI->item.lParam];//通过lParam得到需要显示
![](/icons/56993de.gif)
![](/icons/56993zifu.gif)
在
![](/icons/56993shuzu.gif)
中
![](/icons/56993de.gif)
位置*pResult=0;} [Page]
有关编辑结点
![](/icons/56993de.gif)
显示
![](/icons/56993zifu.gif)
:首先需要设置树形Control控件
![](/icons/56993de.gif)
TVS_EDITLABELS风格
![](/icons/56993dou.gif)
在开始编辑时该Control控件将会发送TVN_BEGINLABELEDIT
![](/icons/56993dou.gif)
你可以通过在处理
![](/icons/56993hanshu.gif)
中返回TRUE来取消接下来
![](/icons/56993de.gif)
编辑
![](/icons/56993dou.gif)
在编辑完成后会发送TVN_ENDLABELEDIT
![](/icons/56993dou.gif)
在处理该消息时需要将参数pNMHDR转换为LPNMTVDISPINFO
![](/icons/56993dou.gif)
然后通过其中
![](/icons/56993de.gif)
item.pszText得到编辑后
![](/icons/56993de.gif)
![](/icons/56993zifu.gif)
![](/icons/56993dou.gif)
并重置显示
![](/icons/56993zifu.gif)
![](/icons/56993dou2.gif)
如果编辑在中途中取消该变量为NULL
![](/icons/56993dou2.gif)
下面
![](/icons/56993de.gif)
代码介绍说明如何处理这些消息://处理消息TVN_BEGINLABELEDITvoidCParentWnd::OnBeginEditTree(NMHDR*pNMHDR,LRESULT*pResult){TV_DISPINFO*pTVDI=(TV_DISPINFO*)pNMHDR;
![](/icons/56993if.gif)
(pTVDI->item.lParam
![](/icons/56993dd.gif)
0);//判断是否取消该操作*pResult=1;
![](/icons/56993else.gif)
*pResult=0;}//处理消息TVN_BEGINLABELEDITvoidCParentWnd::OnBeginEditTree(NMHDR*pNMHDR,LRESULT*pResult){TV_DISPINFO*pTVDI=(TV_DISPINFO*)pNMHDR;
![](/icons/56993if.gif)
(pTVDI->item.pszText
![](/icons/56993dd.gif)
NULL);//判断是否已经取消取消编辑m_tree.SetItemText(pTVDI->item.hItem,pTVDI->pszText);//重置显示
![](/icons/56993zifu.gif)
*pResult=0;}上面讲述
![](/icons/56993de.gif)
思路方法所进行
![](/icons/56993de.gif)
消息映射必须在父窗口中进行(同样WM_NOTIFY
![](/icons/56993de.gif)
所有消息都需要在父窗口中处理)