刚开始以为实现起来很难,所以就在网上寻找实现的扩展控件,到最后才发现只要把CTreeCtrl 控件的Check Boxes 属性设为真就可以了,会在每个树形节点前添加一个CheckBox。

多选已经实现了,下面就是取得选中的项了,在网上搜了以下也没有太好的办法,于是就自己动手写。大概思路是,遍历整个树形控件,访问每个节点并判断该节点是否被选中,使用CTreeCtrl类的成员函数GetCheck()来判断,返回真假。

实例的界面如下:

CTreeCtrl 控件实现多选并取得选中项_git

代码如下:

首先是插入测试节点函数,在OnInitDialog()函数中调用



1 void CCheckBoxTreeDlg::InsertNode()
2 {
3 HTREEITEM hRootItem, hSubItem;
4 CString strTest("TestNode");
5 for(int i = 0;i < 10;i++)
6 {
7 hSubItem = m_treeTest.InsertItem(strTest + TCHAR(48 + i), 0, 0, TVI_ROOT, TVI_LAST);
8 m_treeTest.InsertItem(strTest + TCHAR(48 + i) + "child", 0, 0, hSubItem, TVI_LAST);
9 }
10
11 hRootItem = m_treeTest.GetRootItem();
12 if(NULL != hRootItem)
13 {
14 hSubItem = m_treeTest.GetNextSiblingItem(hRootItem);
15 CString strText = m_treeTest.GetItemText(hSubItem);
16 }
17 }


接着是在增加按钮的点击消息处理函数中获取选中的节点并插入到右边的CListBox控件中



1 // 双击添加按钮
2 void CCheckBoxTreeDlg::OnBnClickedBtnAdd()
3 {
4 // TODO: 在此添加控件通知处理程序代码
5 HTREEITEM hRoot = m_treeTest.GetRootItem();
6
7 while(NULL != hRoot)
8 {
9 CheckAndAddNode(hRoot);
10 hRoot = m_treeTest.GetNextSiblingItem(hRoot);
11 }
12 }
13 // 递归遍历树形控件
14 void CCheckBoxTreeDlg::CheckAndAddNode(HTREEITEM hRoot)
15 {
16 // 如果不是叶子节点
17 if(TRUE == m_treeTest.ItemHasChildren(hRoot))
18 {
19 if(TRUE == m_treeTest.GetCheck(hRoot))
20 {
21 // 插入所有页节点
22 InsertAllLeaves(hRoot);
23 }
24 else
25 {
26 // 查询所有节点,递归
27 HTREEITEM hChild = m_treeTest.GetChildItem(hRoot);
28 while(NULL != hChild)
29 {
30 CheckAndAddNode(hChild);
31 hChild = m_treeTest.GetNextSiblingItem(hChild);
32 }
33 }
34 }
35 else // 是叶子节点
36 {
37 // 被选中
38 if(TRUE == m_treeTest.GetCheck(hRoot))
39 {
40 m_listClients.InsertString(m_listClients.GetCount(), m_treeTest.GetItemText(hRoot));
41 }
42 }
43 }
44 // 插入所有页节点
45 void CCheckBoxTreeDlg::InsertAllLeaves(HTREEITEM hRoot)
46 {
47 HTREEITEM hChild = m_treeTest.GetChildItem(hRoot);
48 while(NULL != hChild)
49 {
50 if(TRUE == m_treeTest.ItemHasChildren(hChild))
51 {
52 InsertAllLeaves(hChild);
53 }
54 else
55 {
56 m_listClients.InsertString(m_listClients.GetCount(), m_treeTest.GetItemText(hChild));
57 }
58 hChild = m_treeTest.GetNextSiblingItem(hChild);
59 }
60 }


有一点需要解释的是,考虑到非叶子节点一般都是作为分类来使用的,所以添加的时候只添加叶子节点。

至此这个小程序的功能就完成了,但是有点不完美的是不能实现父节点与子节点的级联选中或者取消选中。

这个功能在我的下篇博客中实现。