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));
}