如何配置 OpenFileDialog 来选择文件夹?
在 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)发现微软可能为此任务推出了一个自定义对话框。
In VS .NET, when you are selecting a folder for a project, a dialog that looks like an OpenFileDialog or SaveFileDialog is displayed, but is set up to accept only folders. Ever since I've seen this I've wanted to know how it's done. I am aware of the FolderBrowserDialog, but I've never really liked that dialog. It starts too small and doesn't let me take advantage of being able to type a path.
I'm almost certain by now there's not a way to do this from .NET, but I'm just as curious how you do it from unmanaged code as well. Short of completely reimplementing the dialog from scratch, how do you modify the dialog to have this behavior?
I'd also like to restate that I am aware of the FolderBrowserDialog but sometimes I don't like to use it, in addition to being genuinely curious how to configure a dialog in this manner. Telling me to just use the FolderBrowserDialog helps me maintain a consistent UI experience but doesn't satisfy my curiosity so it won't count as an answer.
It's not a Vista-specific thing either; I've been seeing this dialog since VS .NET 2003, so it is doable in Win2k and WinXP. This is less of a "I want to know the proper way to do this" question and more of a "I have been curious about this since I first wanted to do it in VS 2003" question. I understand that Vista's file dialog has an option to do this, but it's been working in XP so I know they did something to get it to work. Vista-specific answers are not answers, because Vista doesn't exist in the question context.
Update: I'm accepting Scott Wisniewski's answer because it comes with a working sample, but I think Serge deserves credit for pointing to the dialog customization (which is admittedly nasty from .NET but it does work) and Mark Ransom for figuring out that MS probably rolled a custom dialog for this task.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
有 Windows API 代码包。 它有很多与 shell 相关的内容,包括 CommonOpenFileDialog 类(位于 Microsoft.WindowsAPICodePack.Dialogs 命名空间中)。 这是完美的解决方案 - 通常打开的对话框仅显示文件夹。
以下是如何使用它的示例:
不幸的是,Microsoft 不再提供此软件包,但有几个人已将二进制文件非正式上传到 NuGet。 可以在此处找到一个示例。 这个包只是 shell 特定的东西。 如果您需要它,同一用户还有其他几个软件包,它们提供了原始软件包中存在的更多功能。
There is the Windows API Code Pack. It's got a lot of shell related stuff, including the
CommonOpenFileDialog
class (in theMicrosoft.WindowsAPICodePack.Dialogs
namespace). This is the perfect solution - the usual open dialog with only folders displayed.Here is an example of how to use it:
Unfortunately Microsoft no longer ships this package, but several people have unofficially uploaded binaries to NuGet. One example can be found here. This package is just the shell-specific stuff. Should you need it, the same user has several other packages which offer more functionality present in the original package.
您可以使用 FolderBrowserDialogEx -
内置FolderBrowserDialog 的可重复使用的衍生产品。 该选项允许您输入路径,甚至是 UNC 路径。 您还可以使用它浏览计算机或打印机。 工作原理与内置 FBD 类似,但……更好。
(编辑:我应该指出,可以设置此对话框来选择文件或文件夹。)
完整源代码(一个简短的 C# 模块)。 自由的。 MS-公共许可证。
使用它的代码:
You can use FolderBrowserDialogEx -
a re-usable derivative of the built-in FolderBrowserDialog. This one allows you to type in a path, even a UNC path. You can also browse for computers or printers with it. Works just like the built-in FBD, but ... better.
(EDIT: I should have pointed out that this dialog can be set to select files or folders. )
Full Source code (one short C# module). Free. MS-Public license.
Code to use it:
我编写了一个名为 OpenFileOrFolder 对话框的对话框,它允许您打开文件夹或文件。
如果将其 AcceptFiles 值设置为 false,则它在仅接受文件夹模式下运行。
您可以在此处从 GitHub 下载源代码
I have a dialog that I wrote called an OpenFileOrFolder dialog that allows you to open either a folder or a file.
If you set its AcceptFiles value to false, then it operates in only accept folder mode.
You can download the source from GitHub here
好的,让我尝试连接第一个点;-)
稍微使用一下 Spy++ 或 Winspector 就会发现 VS 项目位置中的文件夹文本框是标准对话框的自定义。 它与标准文件对话框(例如记事本中的对话框)中的文件名文本框不是同一字段。
从那时起,我认为 VS 隐藏了文件名和文件类型文本框/组合框,并使用自定义对话框模板在对话框底部添加自己的部分。
编辑:这是此类自定义的示例以及如何执行此操作(在 Win32 中,而不是 .NET):
m_ofn 是文件对话框底层的 OPENFILENAME 结构。 添加以下 2 行:
其中 IDD_FILEDIALOG_IMPORTXLIFF 是将添加到对话框底部的自定义对话框模板。 见下图红色部分。
(来源:apptranslator.com)
在这种情况下,自定义的部分只是一个标签+一个超链接,但它可以是任何对话框。 它可能包含一个“确定”按钮,让我们验证仅对文件夹的选择。
但我不知道如何摆脱对话框标准部分中的一些控件。
更多详细信息,请参阅这篇 MSDN 文章。
OK, let me try to connect the first dot ;-)
Playing a little bit with Spy++ or Winspector shows that the Folder textbox in the VS Project Location is a customization of the standard dialog. It's not the same field as the filename textbox in a standard file dialog such as the one in Notepad.
From there on, I figure, VS hides the filename and filetype textboxes/comboboxes and uses a custom dialog template to add its own part in the bottom of the dialog.
EDIT: Here's an example of such customization and how to do it (in Win32. not .NET):
m_ofn is the OPENFILENAME struct that underlies the file dialog. Add these 2 lines:
where IDD_FILEDIALOG_IMPORTXLIFF is a custom dialog template that will be added in the bottom of the dialog. See the part in red below.
(source: apptranslator.com)
In this case, the customized part is only a label + an hyperlink but it could be any dialog. It could contain an OK button that would let us validate folder only selection.
But how we would get rid of some of the controls in the standard part of the dialog, I don't know.
More detail in this MSDN article.
Ookii.Dialogs 包包含新的(Vista 风格)文件夹浏览器对话框的托管包装器。 它也会在较旧的操作系统上正常降级。
The Ookii.Dialogs package contains a managed wrapper around the new (Vista-style) folder browser dialog. It also degrades gracefully on older operating systems.
最好使用FolderBrowserDialog。
Better to use the FolderBrowserDialog for that.
经过几个小时的搜索,我找到了 这个答案,作者是 leetNightShade 到 一个可行的解决方案。
我认为,三件事使得这个解决方案比其他所有解决方案都要好得多。
它只需要您在项目中包含两个文件(无论如何都可以合并为一个)。
<块引用>
没有任何许可,您可以自由地使用代码并做任何您想做的事情。
此处下载代码。
After hours of searching I found this answer by leetNightShade to a working solution.
There are three things I believe make this solution much better than all the others.
It only requires you include two files (which can be combined to one anyway) in your project.
Download the code here.
精确音频复制在 Windows XP 上以这种方式工作。 显示标准文件打开对话框,但文件名字段包含文本“文件名将被忽略”。
只是在这里猜测,但我怀疑每次对对话框进行重大更改时都会将字符串注入到组合框编辑控件中。 只要该字段不为空,并且对话框标志设置为不检查文件是否存在,对话框就可以正常关闭。
编辑:这比我想象的要容易得多。 这是 C++/MFC 中的代码,您可以将其翻译到您选择的环境中。
编辑2:这应该是C#的翻译,但我对C#不太流利,所以如果它不起作用,请不要开枪打我。
编辑 3: 最后在 Visual Studio 2005 中查看了相关的实际对话框(我之前无法访问它)。 这不是标准文件打开对话框!如果您检查 Spy++ 中的窗口并将它们与标准文件打开进行比较,您会发现结构和类名称不匹配。 当您仔细观察时,您还可以发现对话框内容之间的一些差异。 我的结论是 Microsoft 完全取代了 Visual Studio 中的标准对话框以赋予其此功能。 我的解决方案或类似的解决方案将尽可能接近您,除非您愿意从头开始编写自己的代码。
Exact Audio Copy works this way on Windows XP. The standard file open dialog is shown, but the filename field contains the text "Filename will be ignored".
Just guessing here, but I suspect the string is injected into the combo box edit control every time a significant change is made to the dialog. As long as the field isn't blank, and the dialog flags are set to not check the existence of the file, the dialog can be closed normally.
Edit: this is much easier than I thought. Here's the code in C++/MFC, you can translate it to the environment of your choice.
Edit 2: This should be the translation to C#, but I'm not fluent in C# so don't shoot me if it doesn't work.
Edit 3: Finally looked at the actual dialog in question, in Visual Studio 2005 (I didn't have access to it earlier). It is not the standard file open dialog! If you inspect the windows in Spy++ and compare them to a standard file open, you'll see that the structure and class names don't match. When you look closely, you can also spot some differences between the contents of the dialogs. My conclusion is that Microsoft completely replaced the standard dialog in Visual Studio to give it this capability. My solution or something similar will be as close as you can get, unless you're willing to code your own from scratch.
您可以对文件对话框进行子类化并访问其所有控件。 每个都有一个可用于获取其窗口句柄的标识符。 然后,您可以显示和隐藏它们,从它们那里获取有关选择更改的消息等。这完全取决于您想要付出多少努力。
我们使用 WTL 类支持来完成我们的工作,并自定义文件对话框以包括自定义位置栏和插件 COM 视图。
MSDN 提供了有关如何使用 Win32 执行此操作的信息、此 CodeProject 文章包含一个示例,以及这篇 CodeProject 文章提供了一个 .NET 示例。
You can subclass the file dialog and gain access to all its controls. Each has an identifier that can be used to obtain its window handle. You can then show and hide them, get messages from them about selection changes etc. etc. It all depends how much effort you want to take.
We did ours using WTL class support and customized the file dialog to include a custom places bar and plug-in COM views.
MSDN provides information on how to do this using Win32, this CodeProject article includes an example, and this CodeProject article provides a .NET example.
第一个解决方案
我将其开发为 .NET Win 的清理版本7 样式文件夹选择对话框,作者:lyquidity.com 的 Bill Seddon(我没有隶属关系)。 (我从此页面上的另一个答案了解到他的代码)。 我编写了自己的解决方案,因为他的解决方案需要一个额外的 Reflection 类,而该类不需要用于此重点目的,使用基于异常的流控制,不缓存其反射调用的结果。 请注意,嵌套静态
VistaDialog
类的目的是,如果从未调用Show
方法,则其静态反射变量不会尝试填充。 如果 Windows 版本不够高,它会退回到 Vista 之前的对话框。 应该适用于 Windows 7、8、9、10 及更高版本(理论上)。它在 Windows 窗体中的使用方式如下:
您当然可以尝试使用它的选项以及它公开的属性。 例如,它允许在 Vista 风格的对话框中进行多项选择。
第二个解决方案
Simon Mourier 给出了一个答案,展示了如何使用互操作来完成完全相同的工作直接使用 Windows API,尽管如果在旧版本的 Windows 中,则必须对其版本进行补充才能使用旧样式的对话框。 不幸的是,当我制定解决方案时,我还没有找到他的帖子。 说出你的毒药!
First Solution
I developed this as a cleaned up version of .NET Win 7-style folder select dialog by Bill Seddon of lyquidity.com (I have no affiliation). (I learned of his code from another answer on this page). I wrote my own because his solution requires an additional Reflection class that isn't needed for this focused purpose, uses exception-based flow control, doesn't cache the results of its reflection calls. Note that the nested static
VistaDialog
class is so that its static reflection variables don't try to get populated if theShow
method is never called. It falls back to the pre-Vista dialog if not in a high enough Windows version. Should work in Windows 7, 8, 9, 10 and higher (theoretically).It is used like so in a Windows Form:
You can of course play around with its options and what properties it exposes. For example, it allows multiselect in the Vista-style dialog.
Second Solution
Simon Mourier gave an answer that shows how to do the exact same job using interop against the Windows API directly, though his version would have to be supplemented to use the older style dialog if in an older version of Windows. Unfortunately, I hadn't found his post yet when I worked up my solution. Name your poison!
我假设你在 Vista 上使用 VS2008? 在这种情况下,我认为调用时使用了 FOS_PICKFOLDERS 选项 Vista 文件对话框 IFileDialog。 我担心在 .NET 代码中这将涉及大量粗糙的 P/Invoke 互操作代码才能正常工作。
I assume you're on Vista using VS2008? In that case I think that the FOS_PICKFOLDERS option is being used when calling the Vista file dialog IFileDialog. I'm afraid that in .NET code this would involve plenty of gnarly P/Invoke interop code to get working.
您可以使用这样的代码
要高级隐藏文件名的文本框,您需要查看
OpenFileDialogEx
代码:
You can use code like this
To advanced hide of textbox for filename you need to look at
OpenFileDialogEx
The code:
尝试一下 Codeproject 中的这个(归功于 Nitron):
我认为这是一样的您正在谈论的对话框 - 如果您添加屏幕截图也许会有所帮助?
Try this one from Codeproject (credit to Nitron):
I think it's the same dialog you're talking about - maybe it would help if you add a screenshot?
在 Vista 上,您可以使用 IFileDialog< /a> 设置了 FOS_PICKFOLDERS 选项。 这将导致显示类似 OpenFileDialog 的窗口,您可以在其中选择文件夹:
对于较旧的 Windows,您始终可以通过选择文件夹中的任何文件来实现。
可在此处找到适用于 .NET Framework 2.0 及更高版本的工作示例。
On Vista you can use IFileDialog with FOS_PICKFOLDERS option set. That will cause display of OpenFileDialog-like window where you can select folders:
For older Windows you can always resort to trick with selecting any file in folder.
Working example that works on .NET Framework 2.0 and later can be found here.
您可以使用这样的代码
过滤器是空字符串。
文件名是 AnyName 但不为空
You can use code like this
The filter is empty string.
The filename is AnyName but not blank
Ookii Dialogs for WPF 库有一个类,提供WPF 文件夹浏览器对话框的实现。
还有一个适用于 Windows 窗体 的版本。
The Ookii Dialogs for WPF library has a class that provides an implementation of a folder browser dialog for WPF.
There's also a version that works with Windows Forms.
我知道问题出在
OpenFileDialog
的配置上,但看到 Google 把我带到这里,我不妨指出,如果您只是寻找文件夹,您应该使用FolderBrowserDialog
相反,正如下面另一个问题所回答的如何在 vb.net 中使用打开文件对话框指定路径?
I know the question was on configuration of
OpenFileDialog
but seeing that Google brought me here i may as well point out that if you are ONLY looking for folders you should be using aFolderBrowserDialog
Instead as answered by another SO question belowHow to specify path using open file dialog in vb.net?