天天看點

MFC CTreeCtrl 設定checkbox顯隐

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