在VS . net中,当你为项目选择文件夹时,会显示一个类似于OpenFileDialog或SaveFileDialog的对话框,但设置为只接受文件夹。自从我看到这个,我就想知道它是怎么做到的。我知道FolderBrowserDialog,但我从来都不喜欢那个对话框。它开始太小,不让我利用能够键入路径的优势。

到目前为止,我几乎可以肯定在。net中没有办法做到这一点,但我很好奇在非托管代码中如何做到这一点。如果不从头开始完全重新实现对话框,如何修改对话框以使其具有这种行为呢?

我还想重申,我知道FolderBrowserDialog,但有时我不喜欢使用它,除了真正好奇如何以这种方式配置对话框。告诉我只使用FolderBrowserDialog可以帮助我保持一致的UI体验,但不能满足我的好奇心,所以它不能算作答案。

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.

更新:我接受Scott Wisniewski的答案,因为它附带了一个工作示例,但我认为Serge值得赞扬,因为他指出了对话框定制(这在。net中确实很讨厌,但它确实有效),Mark Ransom指出微软可能为这个任务推出了一个自定义对话框。


当前回答

好的,让我试着连接第一个点;-) 玩一点spy++或Winspector显示文件夹文本框在VS项目位置是一个自定义的标准对话框。它与标准文件对话框(如记事本中的文本框)中的文件名文本框不同。

从那里开始,我想,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文章。

其他回答

我猜你用的是Vista的VS2008?在这种情况下,我认为FOS_PICKFOLDERS选项在调用Vista文件对话框IFileDialog时被使用。我担心在。net代码中,这将涉及大量粗糙的P/Invoke互操作代码。

在Vista上,你可以使用IFileDialog和FOS_PICKFOLDERS选项集。这将导致显示类似于openfiledialog的窗口,您可以在其中选择文件夹:

var frm = (IFileDialog)(new FileOpenDialogRCW());
uint options;
frm.GetOptions(out options);
options |= FOS_PICKFOLDERS;
frm.SetOptions(options);

if (frm.Show(owner.Handle) == S_OK) {
    IShellItem shellItem;
    frm.GetResult(out shellItem);
    IntPtr pszString;
    shellItem.GetDisplayName(SIGDN_FILESYSPATH, out pszString);
    this.Folder = Marshal.PtrToStringAuto(pszString);
}

对于旧的Windows系统,你可以选择文件夹中的任何文件。

在。net Framework 2.0及更高版本上的工作示例可以在这里找到。

您可以使用folderbrowserdialgex - 内置FolderBrowserDialog的可重用衍生物。这个选项允许您输入路径,甚至是UNC路径。你也可以用它浏览电脑或打印机。工作原理就像内置的FBD,但是…更好。

(编辑:我应该指出这个对话框可以设置为选择文件或文件夹。)

完整的源代码(一个简短的c#模块)。免费的。微软公开许可。

使用它的代码:

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;
}

您可以使用这样的代码

过滤器为空字符串。 文件名为AnyName,但不为空

        openFileDialog.FileName = "AnyFile";
        openFileDialog.Filter = string.Empty;
        openFileDialog.CheckFileExists = false;
        openFileDialog.CheckPathExists = false;

您可以使用这样的代码

过滤器是隐藏文件 文件名是隐藏第一个文本

到高级隐藏文本框的文件名,你需要看 OpenFileDialogEx

代码:

{
    openFileDialog2.FileName = "\r";
    openFileDialog1.Filter = "folders|*.neverseenthisfile";
    openFileDialog1.CheckFileExists = false;
    openFileDialog1.CheckPathExists = false;
}