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

MFC 遞迴建立目錄樹控制項完整教學

     編輯:關於VC++

專案目標

在對話式應用程式中使用 `CTreeCtrl` 以樹狀結構顯示指定資料夾下的所有檔案與子目錄,採用遞迴演算法實作。

介面設計

  1. 對話方塊放入 Tree Control (`IDC_FILE_TREE`)
  2. 屬性設定:Has Buttons、Has Lines、Lines At Root = TRUE
  3. 加入控制項變數:`CTreeCtrl m_FileTree`

資料成員宣告


class CFileTreeDlg : public CDialog {
    // ...
    CTreeCtrl m_FileTree;
    CImageList m_iImageList; // 節點圖示
    
    // 原版使用固定層級變數 (已棄用,參考改進版)
    HTREEITEM m_hRoot;
    HTREEITEM m_hLevel1, m_hLevel2, m_hLevel3, m_hLevel4, m_hLevel5;
    HTREEITEM m_hFileItem;
};

遞迴遍歷函式


void CFileTreeDlg::BrowseFile(int nLevel, CString strPath)
{
    nLevel++;
    CFileFind finder;
    CString strSearch = strPath;
    
    if (strSearch.Right(1) != _T("\\")) strSearch += _T("\\");
    strSearch += _T("*.*");
    
    BOOL bFound = finder.FindFile(strSearch);
    while (bFound) {
        bFound = finder.FindNextFile();
        if (finder.IsDots()) continue;
        
        CString strName = finder.GetFileName();
        HTREEITEM hParent = NULL;
        
        // 根據層級決定父節點 (原版寫法,建議改用改進版通用遞迴)
        switch (nLevel) {
            case 1: hParent = NULL; break;
            case 2: hParent = m_hLevel1; break;
            case 3: hParent = m_hLevel2; break;
            case 4: hParent = m_hLevel3; break;
            case 5: hParent = m_hLevel4; break;
            default: hParent = m_hLevel5; break;
        }
        
        if (finder.IsDirectory()) {
            HTREEITEM hItem = m_FileTree.InsertItem(strName, 0, 0, hParent);
            // 儲存各層級節點供後續使用
            switch (nLevel) {
                case 1: m_hLevel1 = hItem; break;
                case 2: m_hLevel2 = hItem; break;
                case 3: m_hLevel3 = hItem; break;
                case 4: m_hLevel4 = hItem; break;
                default: m_hLevel5 = hItem; break;
            }
            BrowseFile(nLevel, finder.GetFilePath()); // 遞迴
        } else {
            // 檔案節點
            m_FileTree.InsertItem(strName, 0, 0, hParent);
        }
    }
    finder.Close();
}

初始化與圖示設定


BOOL CFileTreeDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    
    // 設定視窗圖示
    SetIcon(m_hIcon, TRUE); SetIcon(m_hIcon, FALSE);
    
    // 建立圖示清單 (24x24)
    m_iImageList.Create(24, 24, TRUE, 1, 0);
    HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),
        MAKEINTRESOURCE(IDI_KEBIAO), IMAGE_ICON, 24, 24, 0);
    m_iImageList.Add(hIcon);
    m_FileTree.SetImageList(&m_iImageList, TVSIL_NORMAL);
    
    // 開始遍歷 (0 代表第 0 層,第一層會變成 1)
    BrowseFile(0, _T("課程表"));
    
    return TRUE;
}

執行結果

目錄樹執行畫面

已知限制與改進方向

  • 層級硬編碼:超過 5 層會共用第 5 層父節點 → 參考改進版通用遞迴
  • 無圖示區分:資料夾/檔案使用相同圖示 → 使用 `SHGetFileInfo` 取得系統圖示
  • 效能問題:大量檔案時 UI 凍結 → 採用虛擬模式或背景執行緒
  • 錯誤處理:無權限存取目錄會靜默失敗 → 加入 `GetLastError` 判斷

進階版本特性建議


// 取得系統圖示索引
SHFILEINFO sfi;
HIMAGELIST hSysImg = (HIMAGELIST)SHGetFileInfo(
    path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
m_FileTree.SetImageList(CImageList::FromHandle(hSysImg), TVSIL_NORMAL);

// 插入時指定圖示
int nImage = finder.IsDirectory() ? sfi.iIcon : sfi.iIcon;
m_FileTree.InsertItem(strName, nImage, nImage, hParent);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved