如何配置OpenFileDialog选择文件夹?

时间:2020-03-05 18:44:04  来源:igfitidea点击:

在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可能为此任务滚动了一个自定义对话框。

解决方案

回答

最好为此使用FolderBrowserDialog。

using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
    dlg.Description = "Select a folder";
    if (dlg.ShowDialog() == DialogResult.OK)
    {
        MessageBox.Show("You selected: " + dlg.SelectedPath);
    }
}

回答

我假设我们在使用VS2008的Vista上?在那种情况下,我认为在调用Vista文件对话框IFileDialog时会使用FOS_PICKFOLDERS选项。恐怕在.NET代码中,这将涉及大量讨厌的P / Invoke互操作代码才能起作用。

回答

好,让我尝试连接第一个点;-)
与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是自定义对话框模板,将添加到对话框底部。请参见下面红色部分。
替代文字http://apptranslator.com/_so/customizedfiledialog.png

在这种情况下,自定义部分仅是标签+超链接,但可以是任何对话框。它可能包含一个"确定"按钮,使我们可以验证仅文件夹选择。

但是我不知道该如何摆脱对话框标准部分中的某些控件。

此MSDN文章中有更多详细信息。

回答

尝试从Codeproject(贷给Nitron)进行以下操作:

我认为这与我们正在谈论的对话框相同,如果添加屏幕截图可能会有所帮助?

bool GetFolder(std::string& folderpath, const char* szCaption=NULL, HWND hOwner=NULL)
{
    bool retVal = false;

    // The BROWSEINFO struct tells the shell how it should display the dialog.
    BROWSEINFO bi;
    memset(&bi, 0, sizeof(bi));

    bi.ulFlags   = BIF_USENEWUI;
    bi.hwndOwner = hOwner;
    bi.lpszTitle = szCaption;

    // must call this if using BIF_USENEWUI
    ::OleInitialize(NULL);

    // Show the dialog and get the itemIDList for the selected folder.
    LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

    if(pIDL != NULL)
    {
        // Create a buffer to store the path, then get the path.
        char buffer[_MAX_PATH] = {'
CFileDialog dlg(true, NULL, "Filename will be ignored", OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_PATHMUSTEXIST | OFN_READONLY, NULL, this);
dlg.DoModal();
'}; if(::SHGetPathFromIDList(pIDL, buffer) != 0) { // Set the string value. folderpath = buffer; retVal = true; } // free the item id list CoTaskMemFree(pIDL); } ::OleUninitialize(); return retVal; }

回答

我们可以对文件对话框进行子类化,并访问其所有控件。每个都有一个可用于获取其窗口句柄的标识符。然后,我们可以显示和隐藏它们,从中获取有关选择更改等的消息。等等。这一切都取决于我们要付出多少努力。

我们使用WTL类支持来完成我们的工作,并自定义文件对话框以包括自定义位置栏和插件COM视图。

MSDN提供了有关如何使用Win32进行此操作的信息,此CodeProject文章包括一个示例,而此CodeProject文章提供一个.NET示例。

回答

精确音频复制在Windows XP上可以这种方式工作。将显示标准文件打开对话框,但文件名字段包含文本"文件名将被忽略"。

只是在这里猜测,但是我怀疑每次对对话框进行重大更改时,字符串都会注入到组合框编辑控件中。只要该字段不是空白,并且对话框标志设置为不检查文件是否存在,就可以正常关闭对话框。

编辑:这比我想象的要容易得多。这是C ++ / MFC中的代码,我们可以将其转换为我们选择的环境。

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
}

编辑2:这应该是C#的翻译,但是我不太熟练Cso,如果它不起作用,请不要开枪打我。

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

编辑3:最后查看了在Visual Studio 2005中存在问题的实际对话框(我之前没有访问权限)。它不是标准文件打开对话框!如果我们在Spy ++中检查窗口并将它们与打开的标准文件进行比较,则会看到结构和类名不匹配。当我们仔细观察时,还可以发现对话框内容之间的一些差异。我的结论是,Microsoft完全替换了Visual Studio中的标准对话框以提供此功能。我的解决方案或者类似的解决方案将尽可能地接近我们,除非我们愿意从头开始编写自己的代码。

回答

Ookii.Dialogs程序包包含新的(Vista风格)文件夹浏览器对话框周围的托管包装。在较旧的操作系统上,它也会正常降级。

回答

我们可以使用这样的代码

  • 筛选器是隐藏文件
  • 文件名是隐藏第一个文本

要高级隐藏文本框的文件名,我们需要查看
打开文件对话框

代码:

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

回答

我编写了一个对话框,称为OpenFileOrFolder对话框,该对话框可让我们打开文件夹或者文件。

如果将其AcceptFiles值设置为false,则它仅在接受文件夹模式下运行。

我们可以在此处从GitHub下载源代码

回答

我们可以使用FolderBrowserDialogEx
内置FolderBrowserDialog的可重用派生类。这使我们可以键入一个路径,甚至是UNC路径。我们也可以使用它浏览计算机或者打印机。就像内置的FBD一样工作,但是……更好。

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

完整的源代码(一个简短的Cmodule)。自由。 MS-公共许可证。

使用它的代码:

##代码##