C# .NET 6.0 WinForm中如何隐藏FolderBrowserDialog子文件夹列表仅选驱动器
.NET 6 WinForm 实现仅选择驱动器盘符的文件夹选择对话框
原生FolderBrowserDialog封装自Windows系统通用对话框,没有公开属性直接实现「隐藏子文件夹、禁止双击展开驱动器」的效果,可通过以下两种方案实现:
方案1:自定义驱动器选择窗体(推荐,兼容性最佳)
该方案完全自主控制交互逻辑,不依赖系统对话框内部结构,不会出现版本兼容问题:
- 新建独立Windows窗体,布局对齐原生文件选择对话框样式
- 添加
ListView控件设置为列表视图模式,绑定系统图标列表展示和资源管理器一致的驱动器图标 - 窗体加载时通过
DriveInfo.GetDrives()枚举所有就绪的本地驱动器、移动驱动器、光驱等设备,过滤未就绪的无介质驱动器,将盘符、卷标信息加载为列表项 - 重写
ListView的双击事件,拦截默认展开逻辑:用户双击驱动器项时直接将对应盘符作为选中结果返回,不触发任何展开操作 - 添加确认、取消按钮,确认前校验选中项是否为合法驱动器根路径,校验通过则返回OK结果
核心代码参考:
public partial class DriveSelectorForm : Form { public string SelectedDrivePath { get; private set; } public DriveSelectorForm() { InitializeComponent(); // 初始化ListView配置 lstDrives.View = View.List; lstDrives.SmallImageList = new ImageList(); lstDrives.DoubleClick += LstDrives_DoubleClick; btnOk.Click += BtnOk_Click; btnCancel.Click += (s,e) => { DialogResult = DialogResult.Cancel; Close(); }; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); lstDrives.Items.Clear(); // 加载所有就绪驱动器 foreach (var drive in DriveInfo.GetDrives().Where(d => d.IsReady)) { var icon = Icon.ExtractAssociatedIcon(drive.Name); lstDrives.SmallImageList.Images.Add(drive.Name, icon); var item = new ListViewItem($"{drive.VolumeLabel} ({drive.Name[0]}:)") { ImageKey = drive.Name, Tag = drive.RootDirectory.FullName }; lstDrives.Items.Add(item); } } private void LstDrives_DoubleClick(object sender, EventArgs e) { if (lstDrives.SelectedItems.Count != 1) return; SelectedDrivePath = lstDrives.SelectedItems[0].Tag.ToString(); DialogResult = DialogResult.OK; Close(); } private void BtnOk_Click(object sender, EventArgs e) { if (lstDrives.SelectedItems.Count != 1) { MessageBox.Show("请先选择一个驱动器"); return; } SelectedDrivePath = lstDrives.SelectedItems[0].Tag.ToString(); DialogResult = DialogResult.OK; Close(); } }
调用方式和原生对话框一致:
using var selector = new DriveSelectorForm(); if (selector.ShowDialog() == DialogResult.OK) { var selectedDrive = selector.SelectedDrivePath; // 后续业务逻辑 }
方案2:Hook原生FolderBrowserDialog(保留系统原生样式)
如果需要完全复用系统原生对话框的视觉和交互逻辑,可以通过Win32 API Hook对话框过程修改行为:
- 导入
SetWindowLongPtr、GetDlgItem、SendMessage等必要的Win32接口 - 调用
FolderBrowserDialog.ShowDialog()前挂载全局消息钩子,捕获对话框初始化消息 - 收到
WM_INITDIALOG消息时,找到对话框内的树形文件夹控件(类名SysTreeView32),修改控件样式移除展开按钮、连接线属性 - 拦截树形控件的
TVM_EXPAND消息,所有节点展开请求直接返回失败,禁止双击驱动器时展开子文件夹 - 拦截节点选中变更通知,若选中项不是驱动器根节点则自动重置选中状态到对应根目录
注意:该方案依赖系统通用对话框的内部控件结构,不同Windows版本的控件ID、消息参数可能存在差异,需要针对Win10/Win11等不同系统做适配,稳定性弱于自定义窗体方案。
内容的提问来源于stack exchange,提问作者haseakash2009
相关产品推荐
相关产品推荐

