MFC的Tree-view Control树控件Checkbox复选框上下级关联勾选状态

版权声明:本文为博主原创文章,不需博主允许即可随意转载。 https://blog.csdn.net/a_dev/article/details/84580517

对带复选框的树控件,有个常见的需求,就是当我们勾选了某个父节点时,如果其下有子节点,则所有子节点也应当处于勾选状态。相应地,某个子节点连同其所有兄弟节点被勾选时,相应地其父节点也应当自动被选中。

如此,当我们对树控件的某个节点进行复选操作时,需要处理两个递归逻辑:

1.判断其是否具有子节点,如果有,则将所有子节点都设置为相同的复选状态。子节点的子节点进入递归。

2.判断其同级所有兄弟节点状态是否相同,当且仅当所有兄弟节点连同被操作的节点均处于选中状态时,父节点设置为选中状态,否则设置为未其父节点未选中。父节点进入递归。

逻辑厘清了,就开始写代码。

首先,我们要获得被点击的节点Item:

void CDialogSdeLayer::OnNMClickTreeSdeLayer(NMHDR *pNMHDR, LRESULT *pResult)
{
	NM_TREEVIEW* pHdr = (NM_TREEVIEW*)pNMHDR;
	CPoint point;
	UINT uFlag;
	GetCursorPos(&point);
	ScreenToClient(&point);
	HTREEITEM hItem = m_treeLayerInfo.HitTest(point, &uFlag);
	
	///处理点击操作
}

处理点击操作,先处理子级,再根据本级兄弟节点状态,决定是否处理父级:

void CDialogSdeLayer::SetCheckStatus(HTREEITEM hTreeItem, BOOL bCheck)
{
	if (NULL == hTreeItem)
		return;
	SetChildCheckStatus(hTreeItem, bCheck);
	HTREEITEM hParentItem = m_treeLayerInfo.GetParentItem(hTreeItem);
	if (NULL == hParentItem)
		return;
	BOOL bChecked = TRUE;
	HTREEITEM hFirstItem = m_treeLayerInfo.GetChildItem(hParentItem);
	if (FALSE == bCheck)
		bChecked = FALSE;
	if (hFirstItem != hTreeItem && FALSE == m_treeLayerInfo.GetCheck(hFirstItem))
		bChecked = FALSE;
	if (TRUE == bChecked)
	{
		HTREEITEM hNextItem = NULL;
		while ((hNextItem = m_treeLayerInfo.GetNextSiblingItem(hFirstItem)) != NULL)
		{
			if (hNextItem != hTreeItem && bCheck != m_treeLayerInfo.GetCheck(hNextItem))
			{
				bChecked = FALSE;
				break;
			}
			hFirstItem = hNextItem;
		}
	}
	m_treeLayerInfo.SetCheck(hParentItem, bChecked);
	SetParentCheckStatus(m_treeLayerInfo.GetParentItem(hParentItem));
}

处理子级的递归方法如下:

void CDialogSdeLayer::SetChildCheckStatus(HTREEITEM hTreeItem, BOOL bCheck)
{
	if (nullptr == hTreeItem)
		return;
	HTREEITEM hItem = hTreeItem;
	if (TRUE == m_treeLayerInfo.ItemHasChildren(hItem))
	{
		HTREEITEM hChildItem = m_treeLayerInfo.GetChildItem(hItem);
		m_treeLayerInfo.SetCheck(hChildItem, bCheck);
		SetChildCheckStatus(hChildItem, bCheck);
		HTREEITEM hSiblingItem = NULL;
		while ((hSiblingItem = m_treeLayerInfo.GetNextSiblingItem(hChildItem)) != NULL)
		{
			m_treeLayerInfo.SetCheck(hSiblingItem, bCheck);
			SetChildCheckStatus(hSiblingItem, bCheck);
			hChildItem = hSiblingItem;
		}
	}
}

处理父级的递归方法如下:

void CDialogSdeLayer::SetParentCheckStatus(HTREEITEM hTreeItem)
{
	if (nullptr == hTreeItem)
		return;
	BOOL bCheck = TRUE;
	HTREEITEM hFirstItem = m_treeLayerInfo.GetChildItem(hTreeItem);
	if (NULL == hFirstItem)
		return;
	if (FALSE == m_treeLayerInfo.GetCheck(hFirstItem))
		bCheck = FALSE;
	if (TRUE == bCheck)
	{
		HTREEITEM hNextItem = NULL;
		while ((hNextItem = m_treeLayerInfo.GetNextSiblingItem(hFirstItem)) != NULL)
		{
			if (FALSE == m_treeLayerInfo.GetCheck(hNextItem))
			{
				bCheck = FALSE;
				break;
			}
			hFirstItem = hNextItem;
		}
	}
	m_treeLayerInfo.SetCheck(hTreeItem, bCheck);
	SetParentCheckStatus(m_treeLayerInfo.GetParentItem(hTreeItem));
}

完毕。

猜你喜欢

转载自blog.csdn.net/a_dev/article/details/84580517