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 ...
随机推荐
- leetcode每日一题:图中的最长环
题目 2360. 图中的最长环 给你一个 n 个节点的 有向图 ,节点编号为 0 到 n - 1 ,其中每个节点 至多 有一条出边. 图用一个大小为 n 下标从 0 开始的数组 edges 表示,节点 ...
- 解决 Maven 打包项目中 Excel 文件乱码问题
在 Java 项目开发过程中,我们常常会使用 Maven 来管理项目依赖和进行项目打包.当涉及到使用 Freemarker 导出 Excel 文件时,不少开发者可能会遇到一个让人头疼的问题 --Exc ...
- 探秘Transformer系列之(26)--- KV Cache优化---分离or合并
探秘Transformer系列之(26)--- KV Cache优化 之 PD分离or合并 目录 探秘Transformer系列之(26)--- KV Cache优化 之 PD分离or合并 0x00 ...
- symfony3.4修改安全验证默认表配置
#security.yml security: # ··· providers: our_db_provider: entity: class: AppBundle:Users property: u ...
- servlet 作用域
作用域总结 HttpServletRequest:一次请求,请求响应之前有效 HttpSession:一次会话开始,浏览器不关闭或不超时之前有效 ServletContext:服务器启动开始,服务器停 ...
- 【记录】IDA|IDA怎么查看当前二进制文件自动分析出来的内存分布情况(内存范围和读写性)
IDA版本:7.6 背景:我之前一直是直接看Text View里面的地址的首尾地址来判断内存分布情况的,似乎是有点不准确,然后才想到IDA肯定自带查看内存分布情况的功能,而且很简单. 文章目录 1 查 ...
- 【HUST】网络攻防实践|5_二进制文件补丁技术|实验三 热补丁
文章目录 实验要求 实验过程 1. 64位Ubuntu下先安装32位库 2. 利用Preload Hook实现热补丁修补 3. 利用系统调用`ptrace`对运行状态的程序进行hook 3.1 编写补 ...
- vue3 基础-表单元素双向绑定
通常是在 form 表单相关的场景中会用到双向绑定相关, 核心是 v-model 的应用. input 输入框 <!DOCTYPE html> <html lang="en ...
- .NET程序启动就报错,如何截获初期化时的问题json
一:背景 1. 讲故事 前几天训练营里的一位朋友在复习课件的时候,程序一跑就报错,截图如下: 从给出的错误信息看大概是因为json格式无效导致的,在早期的训练营里曾经也有一例这样的报错,最后定位下来是 ...
- CUDA原子操作
这节主要涉及到一个多线程情况下存在的数据竞争问题 -- 多个线程同时访问共享数据时,由于没有正确的同步机制,导致数据出现不一致的情况. C/C++ 多线程中,可以通过互斥锁(mutex).原子操作(a ...