实现的功能主要是点击父节点,子节点全部选中;子节点需要全部选中,父节点才可以选中:
头文件:
BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
void SetChildCheck(HTREEITEM hItem, BOOL bCheck);
void SetParentCheck(HTREEITEM hItem);
LRESULT OnUserMsg(WPARAM wParam, LPARAM lParam);
实现文件中:
#define UM_CHANGE_PARENT_CHECK_STATUS (WM_USER+1011)
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((lp & 0xFFFF0000)>>16)
BEGIN_MESSAGE_MAP(MainFrm, CUIWnd)
ON_MESSAGE(UM_CHANGE_PARENT_CHECK_STATUS, &MainFrm::OnUserMsg)
END_MESSAGE_MAP()
BOOL MainFrm::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
// TODO: Add your specialized code here and/or call the base class
LPNMHDR lpnmh = (LPNMHDR)lParam;
TVHITTESTINFO ht = { 0 };
if ((lpnmh->code == NM_CLICK) && (lpnmh->idFrom == IDC_TREECTRL_1))
{
DWORD dwpos = GetMessagePos();
// include <windowsx.h> and <windows.h> header files
ht.pt.x = GET_X_LPARAM(dwpos);
ht.pt.y = GET_Y_LPARAM(dwpos);
::MapWindowPoints(HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1);
TreeView_HitTest(lpnmh->hwndFrom, &ht);
if (TVHT_ONITEMSTATEICON & ht.flags)
{
// 获取当前选中状态(点击完成后的状态相反)
BOOL bChecked = m_pTree1->GetCheck(ht.hItem);
// 设置子结点选中状态
SetChildCheck(ht.hItem, !bChecked);
// 设置父结点的状态
// 由于是当前点击的状态,而不是点击后的状态, 还未更新, 所以通过消息来设置
::PostMessage(m_hWnd, UM_CHANGE_PARENT_CHECK_STATUS, (WPARAM)ht.hItem, 0);
}
}
return CUIWnd::OnNotify(wParam, lParam, pResult);
}
// 设置子结点选中状态
void MainFrm::SetChildCheck(HTREEITEM hItem, BOOL bCheck)
{
// 得到子结点
HTREEITEM hChildItem = m_pTree1->GetChildItem(hItem);
while (hChildItem != NULL)
{
// 设置子结点选中状态
m_pTree1->SetCheck(hChildItem, bCheck);
// 递归遍历孩子节点
SetChildCheck(hChildItem, bCheck);
// 对兄弟结点进行遍历
hChildItem = m_pTree1->GetNextItem(hChildItem, TVGN_NEXT);
}
}
// 设置父结点选中状态
void MainFrm::SetParentCheck(HTREEITEM hItem)
{
// 得到父节点
HTREEITEM hParent = m_pTree1->GetParentItem(hItem);
if (NULL != hParent)
{
// 记录父结点的状态
BOOL bParentIsChecked = TRUE;
// 检查父结点的所有子结点
HTREEITEM hChild = m_pTree1->GetNextItem(hParent, TVGN_CHILD);
while (hChild)
{
// 如有任一子结点为非选中状态, 父节点不满足全选条件,置为unchecked
if (!m_pTree1->GetCheck(hChild))
{
bParentIsChecked = FALSE;
break;
}
hChild = m_pTree1->GetNextSiblingItem(hChild);
}
// 设置父结点的状态
m_pTree1->SetCheck(hParent, bParentIsChecked);
// 递归检查父节点
SetParentCheck(hParent);
}
}
// 自定义消息处理
LRESULT MainFrm::OnUserMsg(WPARAM wParam, LPARAM lParam)
{
HTREEITEM hItem = (HTREEITEM)(wParam);
if (hItem)
{
SetParentCheck(hItem);
}
return 0L;
}