在项目产品中,经常会用到让用户指定目录的功能,即弹出一个目录选择窗口,获取用户选择的目录。
那么,在 Delphi 中有哪些实现方式呢?让我们一一展示分析。
简单来说,Vcl.FileCtrl.pas 单元封装了 SelectDirectory 函数,调用即可方便的实现选择目录,但该函数有三个重载版本,参数差异较大,最重要的是三个版本的实现完全不同。
SelectDirectory 传统版 (TSelectDirDlg)
这个复古的界面,相信没有人会在项目中使用了。其实这个版本也只是为了兼容性而存在,外观陈旧,功能很少,不支持现代 Windows 特性。
这个窗口是由基于 TForm 类而封装的 TSelectDirDlg 实现的,也就是说,它是 Delphi 自己实现的一个窗口,就连目录标签都是自绘出来的,感兴趣的朋友可以看看它的实现,完全可以基于此自定义一个目录选择窗口。

调用示例:
Dir := 'c:\';
if SelectDirectory(Dir, [], 0) then
ShowMessage('选择的目录: ' + Dir);
SelectDirectory 常规版(SHBrowseForFolder)
这是我们常规见到的目录选择窗口了,它是 SelectDirectory 的第二个重载版本,封装 SHBrowseForFolder 的调用实现的。
除了外观比较直观舒适外,还提供了更多功能选项:
- 可以指定标题、起始目录
- 可以显示文件
- 支持网络共享
- 可以创建新文件夹
调用示例:
Dir := 'c:\';
if SelectDirectory('选择目录', '', Dir, [sdNewUI], Self) then
ShowMessage('选择的目录: ' + Dir);
SelectDirectory 现代版 (IFileOpenDialog)
这个版本的效果更像是打开文件窗口,但可以通过参数控制不显示文件,外观和操作习惯和资源管理器一致。
在 Windows Vista 之后,更推荐该版本,它的特性如下:
- 使用现代 Windows 对话框接口
- 支持多选
- 更好的视觉效果
- 支持 Windows 新特性(如固定位置)
- 更好的 DPI 感知
调用示例:
var
Dirs: TArray<string>;、
begin、
if SelectDirectory('C:\', Dirs, [], '选择目录') then
ShowMessage('选择的目录: ' + Dirs[0]);
注意,它的输出参数是 string 数组,天然支持多选。

OLE 调用 Shell.Application
这个方式只能说提供了另外一种可能,但无论是从使用简单、控制丰富的角度来看,都不是最优解。
调用示例:
var
ShellApp: Variant;
begin
ShellApp := CreateOleObject('Shell.Application');
try
ShowMessage('选择的文件夹: ' +ShellApp.BrowseForFolder(0, '选择文件夹', 0, 0).Self.Path);
except
end;
end;
它的特点是:
- 通过 COM 自动化
- 简单易用
- 功能相对有限
- 性能较差
总结
那么产品项目中,该如何选择呢?
很明显,SelectDirectory 传统版已经不合时宜,常规版已经满足了基本的应用,而如果更为追求系统特性的完整,适应将来的新系统,现代版是最佳选择。
除此以外,还有一个选择。前面我们已经讲到,传统版的 SelectDirectory 实际上是 Delphi 内置了一个基于 TForm 的窗口,这是这个窗口外观过于陈旧,和现代系统不相匹配,但基本的选择目录功能是完善可靠的。那么我们可以基于该窗口做一些美化,实现自己的目录选择窗口,这样就更为自由,也可以做的更和产品UI特性匹配。这一点就留给有兴趣的朋友自行实践。