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

MFC 樹形控件 CTreeCtrl 完整開發指南:節點操作、圖標綁定、遍歷與狀態控制

     編輯:關於C語言

樹形控件廣泛用於文件系統、組織架構、配置面板等層級數據展示。MFC CTreeCtrl 封裝了豐富的節點操作、圖標管理、編輯、拖放等功能。本文系統講解創建風格、節點增刪改查、圖標綁定、狀態控制、遍歷算法及實用技巧。

一、 創建控件與專用風格

BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);

風格常量(可組合)

二、 節點核心操作

1. 插入節點

HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);
  • hParent:父節點句柄,TVI_ROOT 表示根節點
  • hInsertAfter:插入位置,TVI_LAST 末尾,TVI_FIRST 首位,或具體兄弟句柄
  • 返回值:新節點句柄 HTREEITEM

2. 帶圖標插入

HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage,
                     HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);
  • nImage:未選中時圖標索引
  • nSelectedImage:選中時圖標索引

3. 構建樹形結構示例

HTREEITEM hRoot, hChild;

hRoot = m_tree.InsertItem(_T("Parent1"), TVI_ROOT);
hChild = m_tree.InsertItem(_T("Child1_1"), hRoot);
hChild = m_tree.InsertItem(_T("Child1_2"), hRoot, hChild); // 緊跟 Child1_1 後
hChild = m_tree.InsertItem(_T("Child1_3"), hRoot, hChild);

m_tree.InsertItem(_T("Parent2"), TVI_ROOT, hRoot);
m_tree.InsertItem(_T("Parent3"), TVI_ROOT, hRoot);

三、 圖標列表綁定

// 1. 創建圖標列表 (16x16, 4個圖標, 掩碼色黑色)
m_imageList.Create(IDB_TREE_BITMAP, 16, 4, RGB(0,0,0));

// 2. 綁定到樹控件
m_tree.SetImageList(&m_imageList, TVSIL_NORMAL);

// 3. 插入帶圖標節點
m_tree.InsertItem(_T("Parent1"), 0, 1); // 索引0未選中, 索引1選中

四、 節點狀態與文本控制

風格效果
TVS_HASLINES父子節點間繫連線
TVS_LINESATROOT根節點連線
TVS_HASBUTTONS節點前顯示展開/折疊按鈕(+/-)
TVS_EDITLABELS標籤可編輯
TVS_SHOWSELALWAYS失去焦點仍高亮選中項
TVS_DISABLEDRAGDROP禁用拖放
TVS_NOTOOLTIPS禁用工具提示
TVS_CHECKBOXES節點前顯示複選框(擴展風格)
TVS_FULLROWSELECT整行選中(擴展風格)
TVS_INFOTIP支持信息提示(擴展風格)
功能獲取設置
選中節點GetSelectedItem()SelectItem(HTREEITEM)
節點圖標GetItemImage(hItem, nImage, nSelImage)SetItemImage(hItem, nImage, nSelImage)
節點文本GetItemText(hItem)SetItemText(hItem, lpszText)
刪除節點-DeleteItem(hItem) / DeleteAllItems()
展開/折疊-Expand(hItem, CODE) (TVE_EXPAND/TVE_COLLAPSE/TVE_TOGGLE)
節點數據GetItemData(hItem)SetItemData(hItem, DWORD_PTR)

五、 樹遍歷算法

核心導航函數

  • GetRootItem():獲取根節點
  • GetChildItem(hParent):獲取第一個子節點
  • GetNextSiblingItem(hItem):獲取下一個兄弟節點
  • GetParentItem(hItem):獲取父節點
  • GetNextItem(hItem, CODE):通用導航(TVGN_NEXT, TVGN_PREVIOUS, TVGN_PARENT, TVGN_CHILD, TVGN_FIRSTVISIBLE 等)

遞歸遍歷模板

void TraverseTree(HTREEITEM hItem, int depth = 0) {
    if (!hItem) return;
    
    CString text = m_tree.GetItemText(hItem);
    CString indent(' ', depth * 4);
    TRACE(_T("%s%s\n"), indent, text);
    
    // 遍歷子節點
    HTREEITEM hChild = m_tree.GetChildItem(hItem);
    while (hChild) {
        TraverseTree(hChild, depth + 1);
        hChild = m_tree.GetNextSiblingItem(hChild);
    }
}

// 調用入口
HTREEITEM hRoot = m_tree.GetRootItem();
while (hRoot) {
    TraverseTree(hRoot);
    hRoot = m_tree.GetNextSiblingItem(hRoot);
}

非遞歸廣度優先遍歷(隊列)

void TraverseBFS() {
    std::queue<HTREEITEM> q;
    HTREEITEM hRoot = m_tree.GetRootItem();
    while (hRoot) {
        q.push(hRoot);
        hRoot = m_tree.GetNextSiblingItem(hRoot);
    }
    
    while (!q.empty()) {
        HTREEITEM h = q.front(); q.pop();
        // 處理節點 h
        HTREEITEM hChild = m_tree.GetChildItem(h);
        while (hChild) {
            q.push(hChild);
            hChild = m_tree.GetNextSiblingItem(hChild);
        }
    }
}

六、 常用消息映射

通知代碼觸發時機結構
TVN_SELCHANGED選中項改變NMTREEVIEW
TVN_ITEMEXPANDING節點即將展開/折疊NMTREEVIEW
TVN_ITEMEXPANDED節點已展開/折疊NMTREEVIEW
TVN_BEGINLABELEDIT開始編輯標籤NMTVDISPINFO
TVN_ENDLABELEDIT結束編輯標籤NMTVDISPINFO
TVN_GETDISPINFO動態文本回調NMTVDISPINFO
TVN_BEGINDRAG開始拖動NMTREEVIEW
NM_CLICK/NM_DBLCLK單擊/雙擊NMITEMACTIVATE
TVN_KEYDOWN按鍵按下NMTVKEYDOWN

七、 進階技巧

  • 動態文本回調:插入時用 LPSTR_TEXTCALLBACK,處理 TVN_GETDISPINFO 填充 item.pszText
  • 複選框支持:SetExtendedStyle(TVS_EX_CHECKBOXES),用 GetCheck(hItem)/SetCheck(hItem, BOOL) 讀寫狀態
  • 節點數據綁定:SetItemData(hItem, (DWORD_PTR)pMyStruct) 關聯業務對象
  • 自定義繪製:TVS_OWNERDRAW + NM_CUSTOMDRAW 實現節點高亮、圖標動態、多字體
  • 鍵盤導航增強:處理 TVN_KEYDOWN 實現字母快速定位、Enter 展開、空格勾選
  • 保存/恢復展開狀態:遞歸記錄 GetItemState(hItem, TVIS_EXPANDED) 到配置文件

本文整理自 MFC 經典技術文檔,適用於 VC6~VS2022 所有版本。

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