treectrl 设置左侧节点check统一显示隐藏
//1、设置图标
if (!CreateImageList(m_imgTree, IDB_BITMAP_PROJTREE)) return;
m_Tree.SetImageList(&m_imgTree, TVSIL_NORMAL);
TreeView_SetItemHeight(m_Tree, 20); // 2、给Tree增加Checkbox属性
m_Tree.ModifyStyle(TVS_CHECKBOXES, 0);
m_Tree.ModifyStyle(0, TVS_CHECKBOXES); //3、插入节点显示check判断
hNewItem = m_Tree.InsertItem(str, 0, 0, hItem);
int nIndexState = m_bshowcheck ? 1 : 0;
m_Tree.SetItemState(hNewItem, INDEXTOSTATEIMAGEMASK(nIndexState), TVIS_STATEIMAGEMASK);
m_Tree.Expand(hItem, TVE_EXPAND);
m_Tree.SetItemData(hNewItem, (DWORD_PTR)pNode);//4、tree的点击事件
void OnNmClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
CPoint point;
HTREEITEM hItem = m_Tree.GetSelectedItem();
GetCursorPos(&point);
m_Tree.ScreenToClient(&point);
{
UINT nFlag;
HTREEITEM hSelectTreeItem = m_Tree.HitTest(point, &nFlag);
if ((hSelectTreeItem != NULL) && (TVHT_ONITEMSTATEICON & nFlag))
{
ToggleCheckStateEx(hSelectTreeItem);
}
}
*pResult = 0;
}//选择节点
BOOL ToggleCheckStateEx(HTREEITEM hItem)
{
bool bCheckState = m_Tree.GetCheck(hItem);
BOOL bCheck = !bCheckState;
SetChildCheckEx(hItem, bCheck);
SetParentCheckEx(hItem, bCheck);
return TRUE;
} //设置子状态
BOOL SetChildStateEx(HTREEITEM hItem, int nState)
{
HTREEITEM hChild = m_Tree.GetChildItem(hItem);
while (hChild != NULL)
{
DWORD_PTR dwItem = m_Tree.GetItemData(hChild);
if (dwItem != 0)
{
m_Tree.SetCheck(hChild, FALSE);
m_Tree.SetItemState(hChild, INDEXTOSTATEIMAGEMASK(nState), TVIS_STATEIMAGEMASK);
}
if (m_Tree.GetChildItem(hChild) != NULL)
{
SetChildStateEx(hChild, nState);
}
hChild = m_Tree.GetNextSiblingItem(hChild);
}
return TRUE;
}void SetChildCheckEx(HTREEITEM hItem, BOOL bCheck)
{
hItem = m_Tree.GetChildItem(hItem); //获取子项句柄
while (hItem)
{
m_Tree.SetCheck(hItem, bCheck);
SetChildCheckEx(hItem, bCheck); // 递归调用
hItem = m_Tree.GetNextSiblingItem(hItem); // 获取兄弟结点的句柄
}
}//设置父状态
void SetParentCheckEx(HTREEITEM hItem, BOOL bCheck)
{
HTREEITEM hRootItem = m_Tree.GetRootItem();
HTREEITEM hParent = m_Tree.GetParentItem(hItem);
if (hParent == NULL)
{
return; // 自身就是根节点
}
if (bCheck)
{
HTREEITEM hSlibing = m_Tree.GetNextSiblingItem(hItem); // 找一下后继兄弟结点
BOOL bFlag = TRUE;
// 判断当前Item的前后兄弟节点中是否全都选中
while (hSlibing)
{
if (!m_Tree.GetCheck(hSlibing))
{
bFlag = FALSE; // 后继兄弟节点中有一个没有选中,只要有一个没选中,根节点就不该选中
break;
}
hSlibing = m_Tree.GetNextSiblingItem(hSlibing); // 找下一个后继兄弟结点
}
if (bFlag)
{
// 所有的后继兄弟结点都选中了
hSlibing = m_Tree.GetPrevSiblingItem(hItem); // 找下一个前驱兄弟结点
while (hSlibing)
{
if (!m_Tree.GetCheck(hSlibing))
{
bFlag = FALSE; // 前驱兄弟节点中有一个没有选中
break;
}
hSlibing = m_Tree.GetPrevSiblingItem(hSlibing); //GetNextItem(hSlibing, TVGN_PREVIOUS);
}
}
// bFlag为TRUE,表示当前节点的所有前后兄弟节点都已选中,因此设置其父节点也为选中
if (bFlag)
{
if (hRootItem != hParent)
{
m_Tree.SetCheck(hParent, TRUE);
}
}
}
else
{
// 当前节点设为未选中,当然其父节点也要设置为未选中
if (hRootItem != hParent)
{
m_Tree.SetCheck(hParent, FALSE);
}
}
// 递归调用
SetParentCheckEx(hParent, m_Tree.GetCheck(hParent));
}