利用 TTreeView 展示目錄樹結構,TListView 顯示檔案詳細資訊,配合 TDriveComboBox 切換磁碟機,構建經典的雙面板檔案瀏覽器介面。本文提供完整遞歸掃描與事件聯動程式碼。
TDriveComboBox (選磁碟) + TTreeView (目錄樹)。TListView (ViewStyle=vsReport),欄位:名稱、大小、類型、修改時間。TTreeNode* currnode; // 遞歸掃描當前父節點
int DirCount, FileCount, DriveCount;
void TForm1::TreeInit(String path, TTreeNode *mynode) {
TSearchRec sr;
if (FindFirst(path + "\\*.*", faAnyFile, sr) == 0) {
do {
if ((sr.Attr & faDirectory) == faDirectory) {
if (sr.Name != "." && sr.Name != "..") {
currnode = TreeView1->Items->AddChild(mynode, sr.Name);
TreeInit(path + "\\" + sr.Name, currnode); // 遞歸
DirCount++;
}
}
// 檔案不加入樹 (可選擇性啟用)
} while (FindNext(sr) == 0);
FindClose(sr); // 重要:釋放搜尋控制代碼
}
}
void __fastcall TForm1::FormCreate(TObject *Sender) {
String Drive, path;
DirCount = FileCount = 0;
DriveCount = DriveComboBox1->Items->Count;
TreeView1->Items->BeginUpdate();
TreeView1->Items->Clear();
currnode = TreeView1->Items->Add(TreeView1->Selected, "我的電腦");
currnode->Selected = true;
for (int i = 0; i < DriveCount; i++) {
Drive = DriveComboBox1->Items->Strings[i].SubString(1, 1);
path = Drive + ":";
currnode = TreeView1->Items->AddChild(TreeView1->Selected, DriveComboBox1->Items->Strings[i]);
TreeInit(path, currnode);
}
TreeView1->Items->EndUpdate();
}
void __fastcall TForm1::TreeView1Click(TObject *Sender) {
int i;
String path;
TTreeNode *node = TreeView1->Selected;
// 1. 由節點向上遞歸構建完整路徑
if (node->Level) { // 非根節點
do {
if (node->Level == 1) // 磁碟機節點 (如 "C:\")
path = node->Text.SubString(1, 2) + (path.Length() ? "\\" : "") + path;
else
path = node->Text + (path.Length() ? "\\" : "") + path;
node = node->Parent;
} while (node->Level);
// 2. 掃描目錄填充 ListView
ListView1->Items->BeginUpdate();
ListView1->Items->Clear();
TSearchRec sr;
if (FindFirst(path + "\\*.*", faAnyFile, sr) == 0) {
do {
if (sr.Name != "." && sr.Name != "..") {
TListItem *li = ListView1->Items->Add();
li->Caption = sr.Name;
if (sr.Attr == faDirectory) {
li->SubItems->Add(""); // 大小
li->SubItems->Add("檔案夾"); // 類型
} else {
li->SubItems->Add(IntToStr(sr.Size)); // 大小
li->SubItems->Add("檔案"); // 類型
}
li->SubItems->Add(FileDateToDateTime(sr.Time).DateTimeString()); // 時間
}
} while (FindNext(sr) == 0);
FindClose(sr);
}
ListView1->AlphaSort(); // 按名稱排序
ListView1->Items->EndUpdate();
} else { // 根節點 "我的電腦"
ListView1->Items->BeginUpdate();
ListView1->Items->Clear();
for (i = 0; i < TreeView1->Selected->Count; i++) {
TListItem *li = ListView1->Items->Add();
li->Caption = TreeView1->Selected->Item[i]->Text;
}
ListView1->Items->EndUpdate();
}
}
| 技術點 | 實作要點 |
|---|---|
| 遞歸目錄掃描 | FindFirst/FindNext/FindClose 組合,faAnyFile 含目錄與檔案,需排除 . ..。 |
| 路徑構建 | 由葉節點向根遞歸拼接,處理磁碟機節點特殊格式 (含冒號)。 |
| UI 效能優化 | BeginUpdate/EndUpdate 批次更新,避免逐項重繪閃爍。 |
| 資源釋放 | 必須 呼叫 FindClose(sr),否則洩漏搜尋控制代碼導致後續掃描失敗。 |
| 磁碟機枚舉 | TDriveComboBox 自動枚舉系統磁碟機,Items->Strings[i] 格式如 "C:\"。 |
TImageList + SHGetFileInfo 取得系統檔案圖示,TreeView->Images/ListView->SmallImages 關聯。HasChildren 設為 true,OnExpanding 事件動態載入。ListView 右鍵選單實現複製、移動、刪除、重命名 (SHFileOperation)。ListView 項目。PostMessage 回主執行緒更新 UI。FindFirst 路徑格式、權限 (需讀取權限)、faDirectory 判斷邏輯。ViewStyle=vsReport、Columns 正確建立 (設計時或運行時 Columns->Add)。TDriveComboBox 預設不含網路磁碟,需自行枚舉 WNetOpenEnum 或使用 TDirectoryListBox。此範例展示了 VCL 檔案系統控制項的經典組合用法,代碼結構清晰,易於擴展為功能完整的檔案管理器核心模組。