如何配置一个OpenFileDialog选择文件夹?如何配置一个OpenFileDialog选择文件

2019-05-10 13:26发布

在VS .NET,当你为一个项目选择一个文件夹,看起来像一个OpenFileDialog或SaveFileDialog显示,而是被设置为只接受文件夹的对话框。 自从我已经看到了这个,我想知道它是如何做。 我知道的FolderBrowserDialog,但我从来没有真正喜欢该对话框。 它开始太小,不会让我利用能够键入路径的优势。

我几乎可以肯定现在有没有办法从.NET做到这一点,但我只是好奇你是如何从非托管代码做得一样好。 短从头重新实现完全的对话框,你如何修改对话框中有此行为?

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

这不是无论是Vista的具体的东西; 我已经看到自VS .NET 2003此对话框,所以它是在Win2K和WinXP是可行的。 这是更小的“我想知道正确的方式做到这一点”问题,更多的是“我一直好奇这个,因为我第一次想要做它在VS 2003年的”问题。 据我所知,Vista的文件对话框中有一个选项可以做到这一点,但它在XP一直工作,所以我知道他们做了什么来得到它的工作。 Vista的具体答案不是答案,因为Vista不中的问题上下文中。

更新:我接受斯科特的Wisniewski的答案,因为它带有一个工作样本,但我认为塞尔值得信贷的指向对话框定制(这是从.NET固然讨厌,但它工作)和马克赎金为搞清楚的是MS可能推出此任务自定义对话框。

Answer 1:

我有一个,我写称为OpenFileOrFolder对话框,允许你打开文件夹或文件对话框。

如果其AcceptFiles值设置为false,那么它工作在只接受文件夹模式。

您可以从GitHub下载源在这里



Answer 2:

没有Windows API代码包。 它有大量的外壳相关的东西,包括CommonOpenFileDialog类(在Microsoft.WindowsAPICodePack.Dialogs命名空间)。 这是一个完美的解决方案 - 通常打开的对话框只显示文件夹。

下面是如何使用它的一个例子:

CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();

遗憾的是微软不再附带这个包,但还是有些人非正式上传的二进制文件的NuGet。 一个例子可以发现在这里 。 这个包仅仅是特定于shell的东西。 如果你需要它,同一个用户拥有它们提供存在于原始包装更多的功能,其他几个包。



Answer 3:

您可以使用FolderBrowserDialogEx -的可重复使用的衍生内置的FolderBrowserDialog。 这一次,您可以键入路径,甚至一个UNC路径。 您也可以浏览计算机或打印机它。 作品就像内置FBD,但是...更好。

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

完整的源代码(一个短C#模块)。 自由。 MS-公共许可证。

代码使用它:

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


Answer 4:

该Ookii.Dialogs包中包含围绕新(Vista风格)的文件夹浏览器对话框的托管包装。 它也缓慢下降的旧版操作系统。

  • Ookii对话框进行WPF靶向.NET 4.5和提供上的NuGet
  • Ookii对话框Windows窗体靶向.NET 4.5和提供上的NuGet


Answer 5:

最好使用的FolderBrowserDialog了点。

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


Answer 6:

经过搜索的时间,我发现这个答案由leetNightShade到一个有效的解决方案 。

有三件事情,我相信使这个解决方案比其他要好得多。

  1. 它简单易用。 它只需要你在项目中包含两个文件(可组合成一个反正)。
  2. 它回落到标准的FolderBrowserDialog在XP以上系统中使用时。
  3. 笔者授予许可使用的代码,您认为合适的任何目的。

    有没有牌照,比如你可以自由地采取与代码你会做什么。

下载代码这里 。



Answer 7:

精确的音频复制适用于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中(我没有更早地进入到它)。 这不是标准的文件打开对话框! 如果您在检查间谍++的窗户和打开他们比较标准的文件,你会看到的结构和类的名称不匹配。 当你仔细观察,你也可以当场对话的内容之间存在一些差异。 我的结论是,微软完全取代了标准的对话框在Visual Studio中给它这种能力。 我的解决方案或类似的东西会接近你可以得到的,除非你愿意你自己从头开始编写代码。



Answer 8:

OK,让我尝试连接第一个点;-)播放一点点与间谍++或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 )

在这种情况下,定制的一部分,只是一个标签+一个超链接,但它可以是任何对话。 它可以包含一个确定按钮,将让我们验证文件夹中唯一的选择。

但是,我们如何才能摆脱一些在对话框的标准部分的控制,我不知道。

更详细地说这个MSDN文章 。



Answer 9:

你也可以继承文件对话框,并获得其所有控件访问。 每个具有可以被用于获得它的窗口句柄的标识符。 然后,您可以显示和隐藏他们,从他们那里得到有关选择改变等等,等等这一切都取决于你想要多少努力采取消息。

我们做我们的使用WTL的一流的支持和定制的文件对话框,包括自定义位置栏和插件COM意见。

MSDN提供了有关如何做到这一点使用Win32,信息这CodeProject上的文章包括一个例子 ,而这CodeProject上的文章提供了一个.NET示例 。



Answer 10:

您可以使用这样的代码

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

要为文本文件名的高级隐藏你需要看看OpenFileDialogEx

代码:

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


Answer 11:

我假设你在Vista上使用VS2008? 在这种情况下,我认为FOS_PICKFOLDERS选项调用Vista文件对话框时正在使用IFileDialog 。 恐怕在.NET代码这将涉及大量的粗糙的P / Invoke的互操作代码,以获得工作。



Answer 12:

首个解决方案

我开发这个作为一个清理版本.NET的Win 7风格的文件夹选择对话框由比尔·塞登lyquidity.com (我有没有隶属关系)。 (我得知他的代码从另一个答案在此页 )。 我写我自己,因为他的解决方案需要不需要为这个中心的宗旨的附加反射类,使用基于异常的流量控制,不会缓存其反射调用的结果。 需要注意的是嵌套静态VistaDialog类,这样它的静态反射变量不要尝试,如果得到填充Show方法不会被调用。 它回落到Vista之前的对话,如果没有足够高的Windows版本。 应在Windows 7,8,9,10和更高的(理论上)工作。

using System;
using System.Reflection;
using System.Windows.Forms;

namespace ErikE.Shuriken {
    /// <summary>
    /// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions
    /// </summary>
    public class FolderSelectDialog {
        private string _initialDirectory;
        private string _title;
        private string _fileName = "";

        public string InitialDirectory {
            get { return string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory; }
            set { _initialDirectory = value; }
        }
        public string Title {
            get { return _title ?? "Select a folder"; }
            set { _title = value; }
        }
        public string FileName { get { return _fileName; } }

        public bool Show() { return Show(IntPtr.Zero); }

        /// <param name="hWndOwner">Handle of the control or window to be the parent of the file dialog</param>
        /// <returns>true if the user clicks OK</returns>
        public bool Show(IntPtr hWndOwner) {
            var result = Environment.OSVersion.Version.Major >= 6
                ? VistaDialog.Show(hWndOwner, InitialDirectory, Title)
                : ShowXpDialog(hWndOwner, InitialDirectory, Title);
            _fileName = result.FileName;
            return result.Result;
        }

        private struct ShowDialogResult {
            public bool Result { get; set; }
            public string FileName { get; set; }
        }

        private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title) {
            var folderBrowserDialog = new FolderBrowserDialog {
                Description = title,
                SelectedPath = initialDirectory,
                ShowNewFolderButton = false
            };
            var dialogResult = new ShowDialogResult();
            if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK) {
                dialogResult.Result = true;
                dialogResult.FileName = folderBrowserDialog.SelectedPath;
            }
            return dialogResult;
        }

        private static class VistaDialog {
            private const string c_foldersFilter = "Folders|\n";

            private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
            private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly;
            private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog");
            private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags);
            private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags);
            private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags);
            private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags);
            private readonly static uint s_fosPickFoldersBitFlag = (uint) s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialogNative+FOS")
                .GetField("FOS_PICKFOLDERS")
                .GetValue(null);
            private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly
                .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents")
                .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null);
            private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise");
            private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise");
            private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show");

            public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title) {
                var openFileDialog = new OpenFileDialog {
                    AddExtension = false,
                    CheckFileExists = false,
                    DereferenceLinks = true,
                    Filter = c_foldersFilter,
                    InitialDirectory = initialDirectory,
                    Multiselect = false,
                    Title = title
                };

                var iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { });
                s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog });
                s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint) s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag });
                var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U };
                s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken);

                try {
                    int retVal = (int) s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle });
                    return new ShowDialogResult {
                        Result = retVal == 0,
                        FileName = openFileDialog.FileName
                    };
                }
                finally {
                    s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] });
                }
            }
        }

        // Wrap an IWin32Window around an IntPtr
        private class WindowWrapper : IWin32Window {
            private readonly IntPtr _handle;
            public WindowWrapper(IntPtr handle) { _handle = handle; }
            public IntPtr Handle { get { return _handle; } }
        }
    }
}

它用于像这样在Windows窗体中:

var dialog = new FolderSelectDialog {
    InitialDirectory = musicFolderTextBox.Text,
    Title = "Select a folder to import music from"
};
if (dialog.Show(Handle)) {
    musicFolderTextBox.Text = dialog.FileName;
}

当然,你可以玩弄它的选择和哪些属性它公开。 例如,它允许多选在Vista风格的对话框。

第二个解决方案

西蒙Mourier作出了回答 ,显示了如何做使用互操作对Windows的API直接完全相同的工作,虽然他的版本将不得不加以补充,以使用旧风格的对话框,如果在旧版本的Windows。 不幸的是,我还没有找到他的岗位然而,当我的工作我的解决方案。 命名你的毒药!



Answer 13:

试试这个从CodeProject上 (信贷硝酮):

我认为这是你在谈论同一个对话框 - 也许,如果你添加的截图,这将有助于?

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] = {'\0'};
        if(::SHGetPathFromIDList(pIDL, buffer) != 0)
        {
            // Set the string value.
            folderpath = buffer;
            retVal = true;
        }       

        // free the item id list
        CoTaskMemFree(pIDL);
    }

    ::OleUninitialize();

    return retVal;
}


Answer 14:

在Vista中,你可以使用IFileDialog与FOS_PICKFOLDERS选项集。 这将导致打开文件对话框般的窗口,您可以选择文件夹的显示:

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的工作,后来可以发现在这里 。



Answer 15:

您可以使用这样的代码

该过滤器是空字符串。 文件名是AnyName但不是空白

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


Answer 16:

Ookii对话框进行WPF库有一个类,可以为WPF的文件夹浏览器对话框的实现。

https://github.com/caioproiete/ookii-dialogs-wpf

还有,随着工作的版本Windows窗体 。



Answer 17:

我知道这个问题是对的配置OpenFileDialog ,但鉴于谷歌把我带到这里我不妨指出,如果你只是在寻找的文件夹,你应该使用FolderBrowserDialog相反的回答另一个下方,从而质疑

如何在vb.net中使用打开文件对话框,指定路径?



文章来源: How do you configure an OpenFileDialog to select folders?