本文实现了下面的功能:

  1. 当选中父节点时, 其所有子节点全部选中.
  2. 当取消选中父节点时, 其所以子节点全部取消选中.
  3. 点击子节点时, 根据子节点与其兄弟节点的选中状态, 自动设置父节点的选中状态.

通过继承CTreeCtrl实现, 代码如下(注释已经写得很清楚了):

CustomTreeCtrl.h


#pragma once // CCustomTreeCtrl class CCustomTreeCtrl : public CTreeCtrl
{
DECLARE_DYNAMIC(CCustomTreeCtrl) public:
CCustomTreeCtrl();
virtual ~CCustomTreeCtrl(); private: // 设置子结点选中状态
void SetChildCheck(HTREEITEM hItem, BOOL bCheck); // 设置父结点选中状态
void SetParentCheck(HTREEITEM hItem); // 自定义消息处理
afx_msg LRESULT OnUserMsg(WPARAM wParam, LPARAM lParam); protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnNMClick(NMHDR *pNMHDR, LRESULT *pResult);
};

CustomTreeCtrl.cpp


// CustomTreeCtrl.cpp : implementation file
// #include "stdafx.h"
#include "CustomTreeCtrl.h" #define UM_CHANGE_PARENT_CHECK_STATUS (WM_USER+1011) // CCustomTreeCtrl IMPLEMENT_DYNAMIC(CCustomTreeCtrl, CTreeCtrl) CCustomTreeCtrl::CCustomTreeCtrl()
{ } CCustomTreeCtrl::~CCustomTreeCtrl()
{
} BEGIN_MESSAGE_MAP(CCustomTreeCtrl, CTreeCtrl)
ON_NOTIFY_REFLECT(NM_CLICK, &CCustomTreeCtrl::OnNMClick)
ON_MESSAGE(UM_CHANGE_PARENT_CHECK_STATUS, &CCustomTreeCtrl::OnUserMsg)
END_MESSAGE_MAP() // CCustomTreeCtrl message handlers void CCustomTreeCtrl::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
// 获取点击坐标
CPoint pt;
::GetCursorPos(&pt);
::ScreenToClient(m_hWnd, &pt); UINT nFlags = 0;
HTREEITEM hItem = HitTest(pt, &nFlags);
if (hItem)
{
// 选中当前结点
this->SelectItem(hItem); // 如果是点击的CheckBox
if (TVHT_ONITEMSTATEICON == (nFlags & TVHT_ONITEMSTATEICON))
{
// 获取当前选中状态(点击完成后的状态相反)
BOOL bChecked = GetCheck(hItem); // 设置子结点选中状态
SetChildCheck(hItem, !bChecked); // 设置父结点的状态
// 由于是当前点击的状态,而不是点击后的状态, 还未更新, 所以通过消息来设置
::PostMessage(m_hWnd, UM_CHANGE_PARENT_CHECK_STATUS, (WPARAM)hItem, 0);
}
} *pResult = 0;
} // 设置子结点选中状态
void CCustomTreeCtrl::SetChildCheck(HTREEITEM hItem, BOOL bCheck)
{
// 得到子结点
HTREEITEM hChildItem = GetChildItem(hItem);
while (hChildItem != NULL)
{
// 设置子结点选中状态
SetCheck(hChildItem, bCheck); // 递归遍历孩子节点
SetChildCheck(hChildItem, bCheck); // 对兄弟结点进行遍历
hChildItem = GetNextItem(hChildItem, TVGN_NEXT);
}
} // 设置父结点选中状态
void CCustomTreeCtrl::SetParentCheck(HTREEITEM hItem)
{
// 得到父节点
HTREEITEM hParent = GetParentItem(hItem);
if (NULL != hParent)
{
// 记录父结点的状态
BOOL bParentIsChecked = TRUE; // 检查父结点的所有子结点
HTREEITEM hChild = GetNextItem(hParent, TVGN_CHILD);
while (hChild)
{
// 如有任一子结点为非选中状态, 父节点不满足全选条件,置为unchecked
if (!GetCheck(hChild))
{
bParentIsChecked = FALSE;
break;
}
hChild = GetNextSiblingItem(hChild);
} // 设置父结点的状态
SetCheck(hParent, bParentIsChecked); // 递归检查父节点
SetParentCheck(hParent);
}
} // 自定义消息处理
LRESULT CCustomTreeCtrl::OnUserMsg(WPARAM wParam, LPARAM lParam)
{
HTREEITEM hItem = (HTREEITEM)(wParam);
if (hItem)
{
SetParentCheck(hItem);
} return 0L;
}

使用例子


// 定义
CCustomTreeCtrl m_wndTreeCtrl; BOOL CTreeCtrlTest::OnInitDialog()
{
CDialogEx::OnInitDialog(); CRect rc;
GetClientRect(&rc); // 在父/子结点之间绘制连线, 在根/子结点之间绘制连线, 在失去焦点时也显示当前选中的结点, 状态选择框, 在每一个结点前添加一个按钮用于表示当前结点是否已被展开
m_wndTreeCtrl.Create(WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | TVS_CHECKBOXES | TVS_HASBUTTONS, rc, this, 123333); for (size_t i = 0; i < 3; i++)
{
CString strRoot;
if (0 == i)
{
strRoot = _T("AA");
}
else if (1 == i)
{
strRoot = _T("BB");
}
else
{
strRoot = _T("CC");
} HTREEITEM hRoot = m_wndTreeCtrl.InsertItem(strRoot); for (int j = 0; j < 5; j++)
{
CString strChild;
strChild.Format(_T("%s_%02d"), strRoot.GetBuffer(), j); HTREEITEM hChild = m_wndTreeCtrl.InsertItem(strChild, hRoot); for (int k = 200; k < 210; k++)
{
CString strCSubChild;
strCSubChild.Format(_T("%s_%03d"), strChild.GetBuffer(), k); HTREEITEM hSubChild = m_wndTreeCtrl.InsertItem(strCSubChild, hChild);
}
}
} return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}

实现CTreeCtrl父子节点的联动选择的更多相关文章

  1. 7.Android开源项目WheelView的时间和地址联动选择对话框

    类似WheelView的时间和地址联动选择对话框在现在App经常看到,今天小结下. 主布局界面: <LinearLayout xmlns:android="http://schemas ...

  2. Devexpress TreeList控件绑定显示父子节点对像

    今天一位同事咨询Devexpress TreeList控件绑定自动显示父子节点对像,但结果是不会显示带父子节点关系,而是将所有的节点作为父节点显示出来了,对像类的代码如下 public class I ...

  3. [js开源组件开发]js手机联动选择地区仿ios 开源git

    js手机联动选择地区 前言:由于网上找到了一个mobiscrool,比较全,但是不开源,只能试用15天,正式版竟然要三千块钱,穷人只能自己动手,写了个只针对弹窗地区选择的. 本站点所有的资源均在git ...

  4. [js开源组件开发]js手机联动选择日期 开源git

    js手机联动选择日期 这里在前面的<js手机联动选择地区>的基础上,改造数据源之后形成的一个日期的选择器,当然你可以使用之前的PC上模式的<日期控件>,它同时也支持手机端,ht ...

  5. 4个好用的JS联动选择插件

    jQuery City Select 一个简单的jQuery省市联动插件,可以自定义JSON字典实现其他内容的联动选择菜单. PCAS省.市.地区联动选择JS封装类 PCAS可能是国内使用人数最多的J ...

  6. JQUERY省、市、县城市联动选择

    JQUERY 插件开发——CITYLINKAGE(省.市.县城市联动选择) 第一部分:背景   开发源于需求,本次城市联动选择插件算是我写插件的一个特例吧,不是我目前工作需要些的,算是兴趣驱使吧.之前 ...

  7. Android学习小Demo(21)ListView的联动选择

    在日常的App开发中,尤其是在开发生活服务的应用上,非常多时候,我们会须要联动地展现省市区的数据等,需求大概例如以下: 1)展现全部省份 2)当点击某省份的时候,在二级菜单上展现此省份以下所属的城市列 ...

  8. ASP.NET MVC页面UI之联动下拉选择控件(省、市、县联动选择)

    地区选择操作在WEB应用中比较常见的操作,本文在.net mvc3下实现了省市县三级联动选择功能. 本文博客出处:http://www.kwstu.com/ArticleView/admin_2013 ...

  9. easyui Tree模拟级联勾选cascadeCheck,节点选择,父节点自动选中,节点取消,父节点自动取消选择,节点选择,所有子节点全部选择,节点取消,所有子节点全部取消勾选

    最近项目中用到easyui tree,发现tree控件的cascadeCheck有些坑,不像miniui 的tree控件,级联勾选符合业务需求,所以就自己重新改写了onCheck事件,符合业务需求.网 ...

随机推荐

  1. MYSQLI_USE_RESULT or MYSQLI_STORE_RESULT

    之前都是使用同事封装好的mysql类,今天做性能测试时自己手动编写了查询mysql的操作.偶然发现mysqli::query(或者mysqli_query)有一个参数$resultmode取值为MYS ...

  2. SpringBoot入门 (九) MQ使用

    本文记录学习在Spring Boot中使用MQ. 一 什么是MQ MQ全称(Message Queue)又名消息队列,是一种异步通讯的中间件.它的作用类似于邮局,发信人(生产者)只需要将信(消息)交给 ...

  3. 使用keepalived实现双机热备

    通常说的双机热备是指两台机器都在运行,但并不是两台机器都同时在提供服务.当提供服务的一台出现故障的时候,另外一台会马上自动接管并且提供服务,而且切换的时间非常短.下面来以keepalived结合tom ...

  4. MFC RichText 滚动条问题

    一共涉及两个问题: 1.如何更加轻快的在RichText不覆盖之前的文本而添加新的文本 CString text("add text\n"); //想插入的文本,为了使下次输入我们 ...

  5. PowerBuilder编程新思维5:包装(界面美化与WebUI+React)

    PowerBuilder编程新思维5:包装(界面美化与WebUI+React) 前一节,分析了三种界面美化方案,都是控件级的美化.今天再来分析一下窗口级的美化.上一次讲的DirectUI,大家反响一般 ...

  6. core Animation之CAKeyframeAnimation(关键帧动画)

    CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSA ...

  7. webpack3新特性简介

    6月20号webpack推出了3.0版本,官方也发布了公告.根据公告介绍,webpack团队将未来版本的改动聚焦在社区提出的功能需求,同时将保持一个快速.稳定的发布节奏.本文主要依据公告内容,简单介绍 ...

  8. 用python写web一定要去破解的异步请求问题.经历web.py和tornado,完破!

    1.问题 上个学期,给学校写了一个数据服务,主要从oracle里面读取一些数据供查询使用,非常快速的用web.py搭建了起来.调试顺利,测试正常,上线!接下来就是挨骂了,我铁定知道会卡,但是没想到会那 ...

  9. 使用pl/sql的文本导入器时如何设置主键自增长

    在使用文本导入器批量导入数据时,如果需要设置主键自增长,可以先创建一个序列: create sequence SEQ_Userinf start with 1 increment by 1nomaxv ...

  10. javaer有福了,基于Web的mysql数据库管理工具TreeSoft发布了。

    基于Web的数据库管理工具TreeSoft数据库管理系统发布快3年了,版本不断更快速迭代开发中,QQ群也积累了300多位粉丝,虽然时不时也掉粉,但总体还是增加中.大家虽然捐赠不多,但是苍蝇再小也是肉啊 ...