本文转载自:http://bbs.cskin.net/thread-1849-1-1.html
说明
我们选择文件夹就要使用net自带的folderBrowserDialog,但是这个dialog看上去并不是非常好看
因此使用IFileOpenDialog接口重写了一个folderBrowserDialog,可以实现类似OpenFileDialog的样式
效果图:
是不是觉得你的程序一下子大气多了呢?
源码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.ComponentModel; using System.Drawing.Design; using System.Runtime.InteropServices; using System.Windows.Forms; namespace FileBorserDialog { #region Editor /// <summary> /// FolderBrowser 的设计器基类 /// </summary> public class FolderNameEditor : UITypeEditor { public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { FolderBrowserDialog browser = new FolderBrowserDialog(); if (value != null) { browser.DirectoryPath = string.Format("{0}", value); } if (browser.ShowDialog(null) == DialogResult.OK) return browser.DirectoryPath; return value; } } #endregion #region FolderBrowserDialog Base /// <summary> /// Vista 样式的选择文件对话框的基类 /// </summary> [Description("提供一个Vista样式的选择文件对话框")] [Editor(typeof(FolderNameEditor), typeof(UITypeEditor))] public class FolderBrowserDialog : Component { /// <summary> /// 初始化 FolderBrowser 的新实例 /// </summary> public FolderBrowserDialog() { } #region Public Property /// <summary> /// 获取在 FolderBrowser 中选择的文件夹路径 /// </summary> public string DirectoryPath { get; set; } /// <summary> /// 向用户显示 FolderBrowser 的对话框 /// </summary> /// <param name="owner">任何实现 System.Windows.Forms.IWin32Window(表示将拥有模式对话框的顶级窗口)的对象。</param> /// <returns></returns> public DialogResult ShowDialog(IWin32Window owner) { IntPtr hwndOwner = owner != null ? owner.Handle : GetActiveWindow(); IFileOpenDialog dialog = (IFileOpenDialog)new FileOpenDialog(); try { IShellItem item; if (!string.IsNullOrEmpty(DirectoryPath)) { IntPtr idl; uint atts = 0; if (SHILCreateFromPath(DirectoryPath, out idl, ref atts) == 0) { if (SHCreateShellItem(IntPtr.Zero, IntPtr.Zero, idl, out item) == 0) { dialog.SetFolder(item); } } } dialog.SetOptions(FOS.FOS_PICKFOLDERS | FOS.FOS_FORCEFILESYSTEM); uint hr = dialog.Show(hwndOwner); if (hr == ERROR_CANCELLED) return DialogResult.Cancel; if (hr != 0) return DialogResult.Abort; dialog.GetResult(out item); string path; item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out path); DirectoryPath = path; return DialogResult.OK; } finally { Marshal.ReleaseComObject(dialog); } } #endregion #region BaseType [DllImport("shell32.dll")] private static extern int SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)] string pszPath, out IntPtr ppIdl, ref uint rgflnOut); [DllImport("shell32.dll")] private static extern int SHCreateShellItem(IntPtr pidlParent, IntPtr psfParent, IntPtr pidl, out IShellItem ppsi); [DllImport("user32.dll")] private static extern IntPtr GetActiveWindow(); private const uint ERROR_CANCELLED = 0x800704C7; [ComImport] [Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")] private class FileOpenDialog { } [ComImport] [Guid("42f85136-db7e-439c-85f1-e4075d135fc8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IFileOpenDialog { [PreserveSig] uint Show([In] IntPtr parent); // IModalWindow void SetFileTypes(); // not fully defined void SetFileTypeIndex([In] uint iFileType); void GetFileTypeIndex(out uint piFileType); void Advise(); // not fully defined void Unadvise(); void SetOptions([In] FOS fos); void GetOptions(out FOS pfos); void SetDefaultFolder(IShellItem psi); void SetFolder(IShellItem psi); void GetFolder(out IShellItem ppsi); void GetCurrentSelection(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(out IShellItem ppsi); void AddPlace(IShellItem psi, int alignment); void SetDefaultExtension([In, MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension); void Close(int hr); void SetClientGuid(); // not fully defined void ClearClientData(); void SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter); void GetResults([MarshalAs(UnmanagedType.Interface)] out IntPtr ppenum); // not fully defined void GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IntPtr ppsai); // not fully defined } [ComImport] [Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IShellItem { void BindToHandler(); // not fully defined void GetParent(); // not fully defined void GetDisplayName([In] SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName); void GetAttributes(); // not fully defined void Compare(); // not fully defined } private 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 } [Flags] private enum FOS { FOS_ALLNONSTORAGEITEMS = 0x80, FOS_ALLOWMULTISELECT = 0x200, FOS_CREATEPROMPT = 0x2000, FOS_DEFAULTNOMINIMODE = 0x20000000, FOS_DONTADDTORECENT = 0x2000000, FOS_FILEMUSTEXIST = 0x1000, FOS_FORCEFILESYSTEM = 0x40, FOS_FORCESHOWHIDDEN = 0x10000000, FOS_HIDEMRUPLACES = 0x20000, FOS_HIDEPINNEDPLACES = 0x40000, FOS_NOCHANGEDIR = 8, FOS_NODEREFERENCELINKS = 0x100000, FOS_NOREADONLYRETURN = 0x8000, FOS_NOTESTFILECREATE = 0x10000, FOS_NOVALIDATE = 0x100, FOS_OVERWRITEPROMPT = 2, FOS_PATHMUSTEXIST = 0x800, FOS_PICKFOLDERS = 0x20, FOS_SHAREAWARE = 0x4000, FOS_STRICTFILETYPES = 4 } #endregion } #endregion }
注意事项
(需要添加System.Drawing.Design引用)
调用方法和原版folderBrowserDialog一样
使用方法
if (folderBrowserDialog1.ShowDialog(this) == DialogResult.OK) { MessageBox.Show("选择了:" + folderBrowserDialog1.DirectoryPath); }
遗憾
原贴10楼有个人提出在 未选择具体文件夹时候,能禁用选择button就好了。希望日后有人加上时能@下我。
参考引用
https://bbs.csdn.net/topics/390448013