C# WinForm 选择文件夹对话框
选择文件夹只有选择 FolderBrowserDialog,这种选择对话框让人有些抓狂,特别当文件目录比较深、需要多次选择文件夹操作时。

参考:自定义文件夹选择对话框 - 我也是个傻瓜 - 博客园 (cnblogs.com)
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
using System.Windows.Forms; public class SelectFolderDialog
{
#region Internal Enums internal enum FDAP
{
FDAP_BOTTOM = 0,
FDAP_TOP = 1
} internal enum FDE_OVERWRITE_RESPONSE
{
FDEOR_DEFAULT = 0x00000000,
FDEOR_ACCEPT = 0x00000001,
FDEOR_REFUSE = 0x00000002
} internal enum FDE_SHAREVIOLATION_RESPONSE
{
FDESVR_DEFAULT = 0x00000000,
FDESVR_ACCEPT = 0x00000001,
FDESVR_REFUSE = 0x00000002
} [Flags]
internal enum FOS : uint
{
FOS_OVERWRITEPROMPT = 0x00000002,
FOS_STRICTFILETYPES = 0x00000004,
FOS_NOCHANGEDIR = 0x00000008,
FOS_PICKFOLDERS = 0x00000020,
FOS_FORCEFILESYSTEM = 0x00000040, // Ensure that items returned are filesystem items.
FOS_ALLNONSTORAGEITEMS = 0x00000080, // Allow choosing items that have no storage.
FOS_NOVALIDATE = 0x00000100,
FOS_ALLOWMULTISELECT = 0x00000200,
FOS_PATHMUSTEXIST = 0x00000800,
FOS_FILEMUSTEXIST = 0x00001000,
FOS_CREATEPROMPT = 0x00002000,
FOS_SHAREAWARE = 0x00004000,
FOS_NOREADONLYRETURN = 0x00008000,
FOS_NOTESTFILECREATE = 0x00010000,
FOS_HIDEMRUPLACES = 0x00020000,
FOS_HIDEPINNEDPLACES = 0x00040000,
FOS_NODEREFERENCELINKS = 0x00100000,
FOS_DONTADDTORECENT = 0x02000000,
FOS_FORCESHOWHIDDEN = 0x10000000,
FOS_DEFAULTNOMINIMODE = 0x20000000
} internal enum SIATTRIBFLAGS
{
SIATTRIBFLAGS_AND = 1,
SIATTRIBFLAGS_APPCOMPAT = 3,
SIATTRIBFLAGS_OR = 2
} internal enum SIGDN : uint
{
SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
SIGDN_FILESYSPATH = 0x80058000,
SIGDN_NORMALDISPLAY = 0,
SIGDN_PARENTRELATIVE = 0x80080001,
SIGDN_PARENTRELATIVEEDITING = 0x80031001,
SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
SIGDN_PARENTRELATIVEPARSING = 0x80018001,
SIGDN_URL = 0x80068000
} #endregion Internal Enums #region 公共属性 /// <summary>
/// 文件
/// </summary>
public string Folder { get; set; }
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; } #endregion 公共属性 #region 公共方法
/// <summary>
/// 显示对话框架
/// </summary>
/// <param name="owner"></param>
/// <returns></returns> public DialogResult ShowDialog(IWin32Window owner = null)
{
IntPtr hwndOwner = owner != null ? owner.Handle : NativeMethods.GetActiveWindow();
NativeInterfaces.IFileOpenDialog dialog = (NativeInterfaces.IFileOpenDialog)new FileOpenDialog();
try
{
if (!string.IsNullOrEmpty(Folder))
{
if (!IsValidFolderPath(Folder))
{
// 提示用户文件夹路径无效
MessageBox.Show("无效的文件夹路径,请重新选择。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return DialogResult.Cancel;
} Guid _shellItemGuid = typeof(NativeInterfaces.IShellItem).GUID;
NativeInterfaces.IShellItem item = (NativeInterfaces.IShellItem)NativeMethods.SHCreateItemFromParsingName(Folder, null, ref _shellItemGuid);
if (item != null)
dialog.SetFolder(item);
} dialog.SetOptions(FOS.FOS_PICKFOLDERS | FOS.FOS_FORCEFILESYSTEM); if (!string.IsNullOrEmpty(Title))
dialog.SetTitle(Title); int hr = dialog.Show(hwndOwner);
if (hr == NativeMethods.ERROR_CANCELLED)
return DialogResult.Cancel; if (hr != 0)
return DialogResult.Abort; NativeInterfaces.IShellItem resultItem;
dialog.GetResult(out resultItem); resultItem.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out string path);
Folder = path; return DialogResult.OK;
}
catch (Exception ex)
{
// 处理异常
MessageBox.Show($"发生错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return DialogResult.Abort;
}
} private bool IsValidFolderPath(string folderPath)
{
// 这里可以添加更复杂的逻辑来验证文件夹路径的有效性
// 例如,检查文件夹是否存在,是否可访问等
return Directory.Exists(folderPath);
} #endregion 公共方法 #region Internal Structs [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
internal struct COMDLG_FILTERSPEC
{
[MarshalAs(UnmanagedType.LPWStr)]
public string pszName; [MarshalAs(UnmanagedType.LPWStr)]
public string pszSpec;
} [StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct PROPERTYKEY
{
public Guid fmtid; public uint pid;
} #endregion Internal Structs #region Internal Classes internal static class NativeInterfaces
{
#region Public Interfaces [ComImport, Guid("42f85136-db7e-439c-85f1-e4075d135fc8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFileDialog : IModalWindow
{
[PreserveSig]
new int Show([In] IntPtr parent); void SetFileTypes([In] uint cFileTypes, [In][MarshalAs(UnmanagedType.LPArray)] COMDLG_FILTERSPEC[] rgFilterSpec); void SetFileTypeIndex([In] uint iFileType); void GetFileTypeIndex(out uint piFileType); void Advise([In, MarshalAs(UnmanagedType.Interface)] IFileDialogEvents pfde, out uint pdwCookie); void Unadvise([In] uint dwCookie); void SetOptions([In] FOS fos); void GetOptions(out FOS pfos); void SetDefaultFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi); void SetFolder([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi); void GetFolder([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi); void GetCurrentSelection([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi); void SetFileName([In, MarshalAs(UnmanagedType.LPWStr)] string pszName); void GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName); void SetTitle([In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle); void SetOkButtonLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszText); void SetFileNameLabel([In, MarshalAs(UnmanagedType.LPWStr)] string pszLabel); void GetResult([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi); void AddPlace([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, int alignment); void SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension); void Close([MarshalAs(UnmanagedType.Error)] int hr); void SetClientGuid([In] ref Guid guid); void ClearClientData(); void SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter);
} [ComImport, Guid("973510DB-7D7F-452B-8975-74A85828D354"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFileDialogEvents
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), PreserveSig]
int OnFileOk([In, MarshalAs(UnmanagedType.Interface)] IFileDialog pfd); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), PreserveSig]
int OnFolderChanging([In, MarshalAs(UnmanagedType.Interface)] IFileDialog pfd,
[In, MarshalAs(UnmanagedType.Interface)] IShellItem psiFolder); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void OnFolderChange([In, MarshalAs(UnmanagedType.Interface)] IFileDialog pfd); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void OnSelectionChange([In, MarshalAs(UnmanagedType.Interface)] IFileDialog pfd); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void OnShareViolation([In, MarshalAs(UnmanagedType.Interface)] IFileDialog pfd,
[In, MarshalAs(UnmanagedType.Interface)] IShellItem psi,
out FDE_SHAREVIOLATION_RESPONSE pResponse); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void OnTypeChange([In, MarshalAs(UnmanagedType.Interface)] IFileDialog pfd); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void OnOverwrite([In, MarshalAs(UnmanagedType.Interface)] IFileDialog pfd,
[In, MarshalAs(UnmanagedType.Interface)] IShellItem psi,
out FDE_OVERWRITE_RESPONSE pResponse);
} [ComImport, Guid("d57c7288-d4ad-4768-be02-9d969532d960"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFileOpenDialog : IFileDialog
{
void AddPlace([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, FileDialogCustomPlace fdcp); void GetResults([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppenum); void GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IShellItemArray ppsai);
} [ComImport, Guid("b4db1657-70d7-485e-8e3e-6fcb5a5c1802"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IModalWindow
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), PreserveSig]
uint Show([In] IntPtr parent);
} [ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellItem
{
void BindToHandler([In, MarshalAs(UnmanagedType.Interface)] IntPtr pbc, [In] ref Guid bhid, [In] ref Guid riid, out IntPtr ppv); void GetParent([MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi); void GetDisplayName([In] SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName); void GetAttributes([In] uint sfgaoMask, out uint psfgaoAttribs); void Compare([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, [In] uint hint, out int piOrder);
} [ComImport, Guid("B63EA76D-1F85-456F-A19C-48159EFA858B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellItemArray
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void BindToHandler([In, MarshalAs(UnmanagedType.Interface)] IntPtr pbc, [In] ref Guid rbhid,
[In] ref Guid riid, out IntPtr ppvOut); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetPropertyStore([In] int Flags, [In] ref Guid riid, out IntPtr ppv); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetPropertyDescriptionList([In] ref PROPERTYKEY keyType, [In] ref Guid riid, out IntPtr ppv); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetAttributes([In] SIATTRIBFLAGS dwAttribFlags, [In] uint sfgaoMask, out uint psfgaoAttribs); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetCount(out uint pdwNumItems); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetItemAt([In] uint dwIndex, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppsi); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumItems([MarshalAs(UnmanagedType.Interface)] out IntPtr ppenumShellItems);
} #endregion Public Interfaces
} [SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
{
#region Public Fields public const int ERROR_CANCELLED = unchecked((int)0x800704C7); #endregion Public Fields #region Public Methods [DllImport("user32.dll")]
public static extern IntPtr GetActiveWindow(); [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern object SHCreateItemFromParsingName(
[MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, ref Guid riid); #endregion Public Methods
} #endregion Internal Classes #region Private Classes [ComImport, Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")]
private class FileOpenDialog { } #endregion Private Classes
}
C# WinForm 选择文件夹对话框的更多相关文章
- winform 实现选择文件和选择文件夹对话框
//选择文件,点击[浏览],选择文件 private void button1_Click(object sender, EventArgs e) { OpenFileDialog openFileD ...
- Delphi 弹出Windows风格的选择文件夹对话框, 还可以新建文件夹
Delphi 弹出Windows风格的选择文件夹对话框, 还可以新建文件夹 unit Unit2; interface uses Windows, Messages, SysUtils, V ...
- java 选择文件夹对话框
java swing 选择文件夹对话框 import java.io.File; import javax.swing.JFileChooser; public class Test2 { publi ...
- NX二次开发-弹出选择文件夹对话框
这个UFUN和NOPEN里没有对应的函数和类,要用C++的方法去做. #include "afxdialogex.h"//弹出选择文件夹对话框头文件 #include " ...
- MFC中打开选择文件夹对话框,并将选中的文件夹地址显示在编辑框中
一般用于选择你要将文件保存到那个目录下,此程序还包含新建文件夹功能 BROWSEINFO bi; ZeroMemory(&bi, sizeof(BROWSEINFO)); //指定存放文件的 ...
- c++选择文件夹对话框
1,目的 提供一个对话框供用户选择一个文件夹路径. 2,原理&实现 先贴上这个工具类的源码: 在你的程序中使用静态方法 CSelectFolderDlg::Show() 就能显示一个选择文件夹 ...
- NX二次开发-UFUN打开选择文件夹对话框UF_UI_create_filebox
#include <uf.h> #include <uf_ui.h> #include <string> using namespace std; string O ...
- CodeSmith使用总结--下拉列表和文件夹对话框属性
上一篇有点短了,因为实在没有什么可说的,这一篇会多一点.O(∩_∩)O~ 一.下拉列表 关于如何在CodeSmith中创建一个下拉列表的属性框其实很简单,是要使用C#中的枚举就行了,看操作. 首先定义 ...
- C# WINFORM 编程中,选择**文件夹**而不是文件的方法(转)
我们选择文件可以用 OpenFileDialog ,但是文件夹有两种方法. 法一: 用C#的FolderNameEditor类的子类FolderBrowser类来实现获取浏览文件夹对话框的功能.下面来 ...
- C# winform文件批量转编码 选择文件夹
C# winform文件批量转编码 选择文件夹 打开指定目录 private void btnFile_Click(object sender, EventArgs e) { OpenFileDial ...
随机推荐
- 用99元买的服务器搭一套CI/CD系统
故事的开始是这样的:无聊的时候在阿里云买了一个99/年的服务,上面部署了一个Git服务,用于托管自己无聊时写的一些代码,顺便也拿它做开发服务器.为了方便应用管理,起初用docker来管理和部署应用,后 ...
- 4G模块详解
在之前的教程中,无线通信技术我们学习了蓝牙和 WiFi,今天我们要来学习 4G. 4G 模块在距离上有个突破,它不像蓝牙短距离,也不像 WiFi 只能在局域网,4G 模块可使用户无论在哪,只要有 4G ...
- LinkedBlockingQueue的take方法底层源码
一.LinkedBlockingQueue的take方法底层源码 LinkedBlockingQueue 的 take 方法是其核心方法之一,用于从队列头部移除并返回元素.如果队列为空,调用 take ...
- c++指针传递与引用传递
c 不支持引用传递的! 在 C++中,指针传递和引用传递是两种常用的参数传递方式,它们各自有不同的特点和适用场景.下面是两者之间的主要区别: 1. 语法和使用 指针传递 定义和调用:函数参数是一个指针 ...
- fiddler断点应用
一.作用 1.模拟网络中断 2.断点时篡改数据 3.测试时做一些极端测试 二.断点步骤 1.全局断点 1)全局断点的两种方式 点击状态栏空白框,点击一下请求前断点,两下请求后断点,三下取消断点 Rul ...
- 《Deep Learning Inference on Embedded Devices: Fixed-Point vs Posit》(一)
After the success of performing deep learning inference by using an 8-bit precision representation o ...
- [设计模式/Java] 设计模式之解释器模式【27】
概述:解释器模式 := Interpreter Pattern ∈ 行为型模式 模式定义 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式 属于行为型模式. 解释 ...
- 【漏洞扫描】Nuclei v3.4.1 下载方法(附快速下载链接)
简介 Nuclei v3.4.1是一款强大的漏洞扫描器,并且拥有社区维护的海量漏洞POC,工具质量十分的高.Nuclei 用于基于模板跨目标发送请求,从而实现零误报并提供对大量主机的快速扫描.Nucl ...
- 【记录】Word 2021|编号缩进调整
版本: Word 2021 专业版 Word编号缩进调整 有时候会觉得word列表的悬挂缩进太大或太小了. 第一步:右键编号的数字-调整列表缩进. 第二步:编辑格式-编号. 第三步:点击更多,选择编号 ...
- RPC实战与核心原理之动态代理了
动态代理 回顾 用来解决两个应用之间的通信,而网络则是两台l两台机器之间的"桥梁",只有搭好桥梁才能把请求数据从一端传输到另一端,其中关键就是"可靠的传输" 背 ...