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

MFC CTreeCtrl 遞歸遍歷任意層級目錄樹完整實現

     編輯:VC 教學

需求

在對話框或視圖中以樹狀結構顯示指定路徑下的完整目錄/檔案結構,支援任意深度巢狀目錄。

核心演算法:深度優先搜尋 (DFS)

使用 CFileFind 遞歸掃描,遇到子目錄即遞歸進入,檔案直接添加為葉節點。DFS 空間複雜度 O(h) (h=樹高),比廣度優先更節省堆疊。

完整代碼

// 對話框類成員:CTreeCtrl m_Tree;

void CFileTreeDlg::AddFile(CString strPath, HTREEITEM hParent)
{
    CFileFind finder;
    CString strFilter = strPath + _T("\\*.*");
    BOOL bWorking = finder.FindFile(strFilter);

    while (bWorking) {
        bWorking = finder.FindNextFile();

        // 跳過 "." 與 ".."
        if (finder.IsDots()) continue;

        if (finder.IsDirectory()) {
            // 目錄節點
            CString strName = finder.GetFileName();
            HTREEITEM hItem = m_Tree.InsertItem(strName, hParent);
            // 遞歸處理子目錄
            AddFile(finder.GetFilePath(), hItem);
        }
        else {
            // 檔案節點
            CString strName = finder.GetFileName();
            m_Tree.InsertItem(strName, hParent);
        }
    }
    finder.Close();
}

// 初始化調用
BOOL CFileTreeDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    // 假設掃描 C:\Test
    AddFile(_T("C:\\Test"), TVI_ROOT);
    m_Tree.Expand(TVI_ROOT, TVE_EXPAND); // 預設展開根節點
    return TRUE;
}

關鍵點詳解

API用途
CFileFind::FindFile/FindNextFile枚舉目錄項目,支援通配符
IsDirectory()判斷是否目錄
IsDots()過濾 "." ".." 避免無限遞歸
GetFilePath()取得完整路徑 (含檔名),用於遞歸傳遞
GetFileName()僅取得檔名/目錄名,用於樹節點顯示
CTreeCtrl::InsertItem(text, hParent)在父項下插入子項,返回新項句柄
Close()釋放搜尋句柄,必須調用

效能優化建議

  • 虛擬化/延遲載入:節點展開時才掃描子目錄 (TVN_ITEMEXPANDING 通知),避免啟動時掃描海量目錄卡死 UI。
  • 執行緒分離:將掃描移至工作執行緒,透過 PostMessage 將結果分批送回 UI 執行緒插入。
  • 圖標映射:使用 CImageList 關聯系統圖標 (SHGetFileInfo),區分資料夾/檔案類型。
  • 記憶體釋放:大量節點時,對話框銷毀前呼叫 m_Tree.DeleteAllItems()。

常見坑點

  1. 忘記 finder.Close() 導致句柄洩漏,後續掃描失敗。
  2. 未檢查 IsDots() 造成無限遞歸棧溢位。
  3. 路徑拼接缺少反斜線:使用 PathAppend (Shlwapi.h) 或手動補 \\。
  4. Unicode 專案下 CFileFind 正確處理中文路徑,無需額外轉換。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved