在VS .NET中,当您为项目选择文件夹时,会显示一个看起来像OpenFileDialog或SaveFileDialog的对话框,但设置为仅接受文件夹.自从我看到这个以来,我就想知道它是如何完成的.我知道FolderBrowserDialog,但我从来没有真正喜欢那个对话框.它开始太小,不让我利用能够键入路径.
我几乎可以肯定,现在没有办法从.NET做到这一点,但我也很好奇你是如何从非托管代码中做到这一点的.如果没有从头开始完全重新实现对话框,那么如何修改对话框以获得此行为?
我还要重申,我知道FolderBrowserDialog,但有时我不喜欢使用它,除了真正好奇如何以这种方式配置对话框.告诉我只使用FolderBrowserDialog可以帮助我保持一致的UI体验,但不能满足我的好奇心,所以它不会算作答案.
它也不是特定于Vista的东西; 自从VS .NET 2003以来我一直在看这个对话框,所以在Win2k和WinXP中它是可行的.这不是一个"我想知道正确的方法来做这个"的问题,更多的是"我一直很好奇这个,因为我第一次想在VS 2003中这样做"的问题.我知道Vista的文件对话框有一个选项可以做到这一点,但它一直在XP中工作,所以我知道他们做了一些事情让它工作.特定于Vista的答案不是答案,因为问题上下文中不存在Vista.
更新:我接受了Scott Wisniewski的答案,因为它附带了一个工作样本,但我认为Serge指出对话框定制(这无疑是.NET令人讨厌但它确实有效)和Mark Ransom弄清楚MS 是值得称赞的.可能为此任务滚动了一个自定义对话框.
我有一个我写的对话框叫做OpenFileOrFolder对话框,允许你打开文件夹或文件.
如果将其AcceptFiles值设置为false,则它仅以接受文件夹模式运行.
您可以在此处从GitHub下载源代码
您可以使用FolderBrowserDialogEx - 内置FolderBrowserDialog的可重用衍生物.这个允许您输入路径,甚至是UNC路径.您还可以使用它浏览计算机或打印机.就像内置的FBD一样,但是......更好.
(编辑:我应该指出这个对话框可以设置为选择文件或文件夹.)
完整源代码(一个简短的C#模块).自由.MS-Public许可证.
使用它的代码:
var dlg1 = new Ionic.Utils.FolderBrowserDialogEx(); dlg1.Description = "Select a folder to extract to:"; dlg1.ShowNewFolderButton = true; dlg1.ShowEditBox = true; //dlg1.NewStyle = false; dlg1.SelectedPath = txtExtractDirectory.Text; dlg1.ShowFullPathInEditBox = true; dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer; // Show the FolderBrowserDialog. DialogResult result = dlg1.ShowDialog(); if (result == DialogResult.OK) { txtExtractDirectory.Text = dlg1.SelectedPath; }
有Windows API代码包.它有很多与shell相关的东西,包括CommonOpenFileDialog
类(在Microsoft.WindowsAPICodePack.Dialogs
命名空间中).这是一个完美的解决方案 - 通常只打开文件夹的打开对话框.
以下是如何使用它的示例:
CommonOpenFileDialog cofd = new CommonOpenFileDialog(); cofd.IsFolderPicker = true; cofd.ShowDialog();
不幸的是,微软不再提供此软件包,但有几个人非正式地将二进制文件上传到NuGet.这里可以找到一个例子.这个包只是特定于shell的东西.如果您需要它,同一个用户有几个其他软件包,它们提供原始软件包中的更多功能.
该Ookii.Dialogs包中包含围绕新(Vista风格)的文件夹浏览器对话框的托管包装.它在旧操作系统上也会优雅地降级.
针对WPF的Ookii Dialogs针对 .NET 4.5并在NuGet上提供
面向 .NET 4.5的Ookii Dialogs for Windows Forms,可在NuGet上使用
最好使用FolderBrowserDialog.
using (FolderBrowserDialog dlg = new FolderBrowserDialog()) { dlg.Description = "Select a folder"; if (dlg.ShowDialog() == DialogResult.OK) { MessageBox.Show("You selected: " + dlg.SelectedPath); } }
经过搜索的时间,我发现这个答案由leetNightShade到一个有效的解决方案.
我相信有三件事情可以使这个解决方案比其他所有解决方案都好.
它使用简单. 它只需要在项目中包含两个文件(可以组合为一个).
在XP或旧系统上使用时,它会回退到标准的FolderBrowserDialog.
作者允许您将代码用于您认为合适的任何目的.
没有许可证,因为您可以随意使用代码.
在这里下载代码.
好吧,让我尝试连接第一个点;-)使用Spy ++或Winspector播放一点,表明VS Project Location中的Folder文本框是标准对话框的自定义.它与标准文件对话框(如记事本中的文件夹)中的文件名文本框不同.
从那以后,我想,VS隐藏了文件名和文件类型文本框/组合框,并使用自定义对话框模板在对话框的底部添加自己的部分.
编辑:这是一个这样的自定义和如何做的例子(在Win32.而不是.NET):
m_ofn是OPENFILENAME结构,它是文件对话框的基础.添加以下两行:
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF); m_ofn.Flags |= OFN_ENABLETEMPLATE;
其中IDD_FILEDIALOG_IMPORTXLIFF是一个自定义对话框模板,将添加到对话框的底部.请参阅下面的红色部分.
(来源:apptranslator.com)
在这种情况下,自定义部件只是标签+超链接,但它可以是任何对话框.它可以包含一个OK按钮,让我们验证仅文件夹选择.
但我不知道如何摆脱对话标准部分的一些控件.
这篇MSDN文章中有更多细节.
精确音频复制在Windows XP上以这种方式工作.将显示标准文件打开对话框,但文件名字段包含文本"将忽略文件名".
只是在这里猜测,但我怀疑每次对对话框进行重大更改时,字符串都会被注入到组合框编辑控件中.只要该字段不为空,并且对话框标志设置为不检查文件是否存在,就可以正常关闭该对话框.
编辑:这比我想象的容易得多.这是C++/MFC中的代码,您可以将其转换为您选择的环境.
CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this); dlg.DoModal();
编辑2:这应该是C#的翻译,但是我不熟练使用C#所以如果它不起作用,请不要开枪.
OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.FileName = "Filename will be ignored"; openFileDialog1.CheckPathExists = true; openFileDialog1.ShowReadOnly = false; openFileDialog1.ReadOnlyChecked = true; openFileDialog1.CheckFileExists = false; openFileDialog1.ValidateNames = false; if(openFileDialog1.ShowDialog() == DialogResult.OK) { // openFileDialog1.FileName should contain the folder and a dummy filename }
编辑3:最后在Visual Studio 2005中查看了有问题的实际对话框(我之前没有访问过它).它不是标准文件打开对话框!如果您在Spy ++中检查窗口并将它们与打开的标准文件进行比较,您将看到结构和类名称不匹配.仔细观察,您还可以发现对话框内容之间的一些差异.我的结论是,Microsoft完全取代了Visual Studio中的标准对话框,以赋予它这种能力.除非您愿意从头开始编写自己的代码,否则我的解决方案或类似的东西将尽可能接近您.
您可以子类化文件对话框并获取对其所有控件的访问权限.每个都有一个标识符,可用于获取其窗口句柄.然后,您可以显示和隐藏它们,从中获取有关选择更改等的消息.这一切都取决于您想要花多少精力.
我们使用WTL类支持并自定义文件对话框以包含自定义位置栏和插件COM视图.
MSDN提供了有关如何使用Win32执行此操作的信息,此CodeProject文章包含一个示例,此CodeProject文章提供了一个.NET示例.
你可以使用这样的代码
过滤器是隐藏文件
文件名是隐藏第一个文本
要高级隐藏文件名文件框,您需要查看
OpenFileDialogEx
代码:
{ openFileDialog2.FileName = "\r"; openFileDialog1.Filter = "folders|*.neverseenthisfile"; openFileDialog1.CheckFileExists = false; openFileDialog1.CheckPathExists = false; }
我假设你使用VS2008在Vista上?在这种情况下,我认为在调用Vista文件对话框IFileDialog时正在使用FOS_PICKFOLDERS选项.我担心在.NET代码中,这将涉及到大量粗糙的P/Invoke互操作代码才能正常工作.