首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

支援資料項查找的 CTreeCtrl 擴充類別:遞迴搜尋避免節點重複

     編輯:VC 教學

樹狀控制項 (CTreeCtrl) 基礎

  • 結構:根節點 → 子節點 → 孫節點...,節點間為父子/同輩關係。
  • 核心屬性:文字標籤、影像索引 (Image List)、展開/摺疊狀態、資料指標 (LPARAM)。
  • 常用操作:InsertItem, DeleteItem, Expand, SelectItem, EditLabel, SortChildren, GetCount, GetIndent, GetImageList。

建立方式

  • 靜態:資源編輯器拖放 → ClassWizard 加入 CTreeCtrl 成員變數。
  • 動態:treeCtrl.Create(WS_VISIBLE|WS_CHILD|TVS_HASLINES, rect, this, IDC_TREE)。

遞迴查找節點函數

// 於衍生類 CTreeCtrlEx 中實作
HTREEITEM CTreeCtrlEx::FindItem(HTREEITEM hItem, const CString& strText)
{
    if (hItem == NULL) return NULL;

    while (hItem != NULL)
    {
        // 1. 比對目前節點文字
        if (GetItemText(hItem) == strText)
            return hItem;  // 找到,傳回 handle

        // 2. 若有子節點,遞迴搜尋子樹
        if (ItemHasChildren(hItem))
        {
            HTREEITEM hChild = GetChildItem(hItem);
            HTREEITEM hFound = FindItem(hChild, strText);
            if (hFound != NULL)
                return hFound;  // 子樹中找到,向上傳回
        }

        // 3. 移至下一個同輩節點
        hItem = GetNextSiblingItem(hItem);
    }
    return NULL;  // 整棵樹搜尋完畢未找到
}

關鍵 API 對照

功能CTreeCtrl 成員函數Win32 宏/訊息
取得節點文字GetItemText(hItem)TVM_GETITEM + TVIF_TEXT
判斷是否有子節點ItemHasChildren(hItem)TVM_GETITEM + TVIF_CHILDREN
取得第一個子節點GetChildItem(hItem)TVM_GETNEXTITEM + TVGN_CHILD
取得下一個同輩節點GetNextSiblingItem(hItem)TVM_GETNEXTITEM + TVGN_NEXT
取得父節點GetParentItem(hItem)TVM_GETNEXTITEM + TVGN_PARENT

使用範例:新增節點前檢查重複

void CMyDialog::OnBtnAddNode()
{
    CString strNewName;
    GetDlgItemText(IDC_EDIT_NAME, strNewName);
    strNewName.Trim();
    if (strNewName.IsEmpty()) return;

    // 從根節點開始搜尋
    HTREEITEM hRoot = m_treeCtrl.GetRootItem();
    HTREEITEM hFound = m_treeCtrl.FindItem(hRoot, strNewName);

    if (hFound != NULL)
    {
        CString msg;
        msg.Format(_T("節點「%s」已存在!"), strNewName);
        AfxMessageBox(msg);
        return;
    }

    // 不重複,插入新節點
    HTREEITEM hParent = m_treeCtrl.GetSelectedItem(); // 或指定父節點
    if (hParent == NULL) hParent = TVI_ROOT;
    m_treeCtrl.InsertItem(strNewName, 0, 1, hParent, TVI_LAST);
}

效能考量與優化

  • 遞迴深度受限於樹高,Windows 樹控制項節點數通常 < 10,000,遞迴安全。
  • 大量節點 (> 5,000) 時,可改用反覆器模式 (堆疊/佇列) 避免堆疊溢位。
  • 頻繁查找可建立 CMap 快取名稱→Handle 對應,插入/刪除時同步更新。
  • 搭配 TVS_EDITLABELS 樣式允許使用者就地編輯,編輯後同步更新快取。

擴充建議

  • FindItemByData(LPARAM data):依附加資料查找。
  • FindItemPath(HTREEITEM hItem, CStringArray& path):取得從根節點到目標節點的完整路徑。
  • GetAllItems(CArray& arr):一次性取得所有節點 Handle 供批次處理。

內建遞迴查找功能的 CTreeCtrlEx 讓樹狀介面開發更安全、高效,避免使用者建立重複節點導致資料不一致。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved