在對話框或視圖中以樹狀結構顯示指定路徑下的完整目錄/檔案結構,支援任意深度巢狀目錄。
使用 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()。finder.Close() 導致句柄洩漏,後續掃描失敗。IsDots() 造成無限遞歸棧溢位。PathAppend (Shlwapi.h) 或手動補 \\。CFileFind 正確處理中文路徑,無需額外轉換。