You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 14:24:23