MFC 带有 CheckBox 的 CTreeCtrl 结点

初始化 CTreeCtrl

BOOL OnInitDialog()
{
    CDialogEx::OnInitDialog();

    HTREEITEM hTempBuilding; 

    m_hPublicBuilding = m_treeRoomType.InsertItem(_T("公共建筑"), NULL, NULL); 
    hTempBuilding = m_treeRoomType.InsertItem(_T("办公室"), NULL, NULL, m_hPublicBuilding, TVI_LAST); 
    hTempBuilding = m_treeRoomType.InsertItem(_T("会议室"), NULL, NULL, m_hPublicBuilding, TVI_LAST); 

    m_hResidentialBuilding = m_treeRoomType.InsertItem(_T("居住建筑"), NULL, NULL); 
    hTempBuilding = m_treeRoomType.InsertItem(_T("卧室"), NULL, NULL, m_hResidentialBuilding, TVI_LAST);   
    hTempBuilding = m_treeRoomType.InsertItem(_T("其他"), NULL, NULL, m_hResidentialBuilding, TVI_LAST); 

    ExpandTreeAllItem();
    return TRUE;  
}

递归展开 CTreeCtrl

///--------------------------------------------------------
void ExpandTreeAllItem()
{
    ExpandTreeItem(m_hPublicBuilding);         // 展开公共建筑
    ExpandTreeItem(m_hResidentialBuilding);    // 展开居住建筑
}

///---------------------------------------------------------
void ExpandTreeItem(HTREEITEM hTreeItem)
{
    if(!m_treeRoomType.ItemHasChildren(hTreeItem))
    {
        return;
    }
    HTREEITEM hNextItem = m_treeRoomType.GetChildItem(hTreeItem);
    while (hNextItem != NULL)
    {
        ExpandTreeItem(hNextItem);
        hNextItem = m_treeRoomType.GetNextItem(hNextItem, TVGN_NEXT);
    }
    m_treeRoomType.Expand(hTreeItem,TVE_EXPAND);
}

勾选根节点同步勾选子节点

void CTCDAnalysisConfig::SetChildCheck(HTREEITEM hItem, BOOL bCheck)
{
    hItem = m_treeRoomType.GetChildItem(hItem);  //获取子项句柄
    while (hItem)
    {
        m_treeRoomType.SetCheck(hItem, bCheck);
        SetChildCheck(hItem,bCheck);                        // 递归调用
        hItem = m_treeRoomType.GetNextSiblingItem(hItem);   // 获取兄弟结点的句柄
    }
}

勾选所有子节点同步勾选它的根节点

///--------------------------------------------------------------
void CTCDAnalysisConfig::SetParentCheck(HTREEITEM hItem, BOOL bCheck)
{
    HTREEITEM hParent = m_treeRoomType.GetParentItem(hItem);
    if(hParent == NULL)
    {
        return; // 自身就是根节点
    }
        
    if(bCheck) 
    {
        HTREEITEM hSlibing = m_treeRoomType.GetNextSiblingItem(hItem); // 找一下后继兄弟结点
        BOOL bFlag = TRUE;
        // 判断当前Item的前后兄弟节点中是否全都选中
        while(hSlibing) 
        {
            if(!m_treeRoomType.GetCheck(hSlibing)) 
            {
                bFlag = FALSE; // 后继兄弟节点中有一个没有选中,只要有一个没选中,根节点就不该选中
                break;
            }
            hSlibing = m_treeRoomType.GetNextSiblingItem(hSlibing); // 找下一个后继兄弟结点
        }

        if(bFlag) 
        {
            // 所有的后继兄弟结点都选中了
            hSlibing = m_treeRoomType.GetPrevSiblingItem(hItem); // 找下一个前驱兄弟结点
            while(hSlibing) 
            {
                if(!m_treeRoomType.GetCheck(hSlibing)) 
                {
                    bFlag = FALSE; // 前驱兄弟节点中有一个没有选中
                    break;
                }
                hSlibing = m_treeRoomType.GetPrevSiblingItem(hSlibing); //GetNextItem(hSlibing, TVGN_PREVIOUS);
            }
        }

        // bFlag为TRUE,表示当前节点的所有前后兄弟节点都已选中,因此设置其父节点也为选中
        if(bFlag)
        {
            m_treeRoomType.SetCheck(hParent, TRUE);
        }
                
    } 
    else 
    { 
        // 当前节点设为未选中,当然其父节点也要设置为未选中
        m_treeRoomType.SetCheck(hParent, FALSE);
    }
    // 递归调用
    SetParentCheck(hParent, m_treeRoomType.GetCheck(hParent));
}

你可能感兴趣的:(MFC 带有 CheckBox 的 CTreeCtrl 结点)