LPARAM)。InsertItem, DeleteItem, Expand, SelectItem, EditLabel, SortChildren, GetCount, GetIndent, GetImageList。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; // 整棵樹搜尋完畢未找到
}
| 功能 | 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);
}
CMap 快取名稱→Handle 對應,插入/刪除時同步更新。TVS_EDITLABELS 樣式允許使用者就地編輯,編輯後同步更新快取。FindItemByData(LPARAM data):依附加資料查找。FindItemPath(HTREEITEM hItem, CStringArray& path):取得從根節點到目標節點的完整路徑。GetAllItems(CArray& arr) :一次性取得所有節點 Handle 供批次處理。內建遞迴查找功能的 CTreeCtrlEx 讓樹狀介面開發更安全、高效,避免使用者建立重複節點導致資料不一致。