你如何配置OpenFileDialog选择的文件夹?
-
09-06-2019 - |
题
在VS。净,当你选择一个文件夹,用于一个项目,一个对话,这看起来像一个OpenFileDialog或SaveFileDialog显示,但是设立仅接受的文件夹。自从我已经看到这我一直想知道它是如何做。我知道FolderBrowserDialog,但我从来没有真的很喜欢这个对话。它开始太小,并且不让我利用能够型的道路。
我几乎可以肯定,现在没有一种方法来这样做。净,但是我只是好奇你如何做到这一点从不受管理的代码。短期的重新实现完全的对话,从头开始,你如何修改的对话,以有这样的行为?
我还想重申,我知道FolderBrowserDialog但有时候我不喜欢用它,除了真正的好奇如何配置一个对话以这种方式。告诉我要的只是使用FolderBrowserDialog帮助我保持一致的用户界面的经验,但不能满足我的好奇心,所以它不会计为一个答案。
这不是一个Vista具体的事;我已经看到这一对话由于VS。净2003年,因此它是可行的,在Win2k和WinXP.这是下一个"我想知道的正确方法这样做"的问题,并更加一个"我是好奇的关于这一点,因为我第一个想做到这一点,在VS2003年"的问题。我的理解是,Vista的对话文件有一个选项,要做到这一点,但它已经在工作XP所以我知道他们做的 的东西 来获得它的工作。Vista的具体答案是不是答案,因为Vista不存在这个问题的上下文。
更新:我接受斯科特*维斯涅夫斯基的答案,因为它带有一个工作样,但我认为,塞尔值得信贷,用于向该对话定制(这是无可否认的令人讨厌。净但它 做 工作)和马赎金搞清楚,MS可能推出一个自定义的对话对于这一任务。
解决方案
其他提示
有窗户代码组。它有很多的外壳有关的东西,包括 CommonOpenFileDialog
类(在 Microsoft.WindowsAPICodePack.Dialogs
namespace).这是一个完美的解决方案-通常开放的对话只有文件夹中显示。
这里是一个如何使用它:
CommonOpenFileDialog cofd = new CommonOpenFileDialog();
cofd.IsFolderPicker = true;
cofd.ShowDialog();
不幸的是Microsoft不再是船舶这个包,但是有几个人已经非正式的二进制文件上传到NuGet.一个例子中可以找到 在这里,.这个包是只是外壳具体的东西。你应该需要它,相同的用户有若干其他的软件包提供更多的功能存在的原始包装。
你可以使用 FolderBrowserDialogEx - 重复使用的衍生物的内在FolderBrowserDialog.这个人允许你在一条路径,即使一个UNC的道路。你也可以浏览的计算机或打印机。就像内森林生物多样性,但是...更好。
(编辑:我应该指出,这种对话可以集中选择的文件或文件夹。)
完整的源代码(一个短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;
}
的 Ookii.的对话 包含一个管理的包装的新的(Vista式)文件夹,浏览器的对话。它还会降低优雅地在较早的操作系统。
- Ookii对话WPF 瞄准.净额4.5和 可在NuGet
- Ookii对话对于Windows的形式 瞄准.净额4.5和 可在NuGet
更好地使用FolderBrowserDialog。
using (FolderBrowserDialog dlg = new FolderBrowserDialog())
{
dlg.Description = "Select a folder";
if (dlg.ShowDialog() == DialogResult.OK)
{
MessageBox.Show("You selected: " + dlg.SelectedPath);
}
}
几小时后搜索,我发现 这个答案 通过 leetNightShade 要 一个工作方案.
有三件事情我相信,使这个解决方案更好于所有其他人。
- 它是简单的使用。 它只需要你的包括两个文件(其中可以合并到一个无论如何)在您的项目。
- 它回落到标准 FolderBrowserDialog 使用时XP或旧的系统。
- 提交人授予许可使用代码,用于任何目的,您认为合适的。
有没有许可为例如你可以自由采取与代码什么你会的。
下载码 在这里,.
确切的声音复制 这种方式工作,在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 Studio2005年(我没有访问它早)。 这不是标准的文件开放的对话! 如果你检查窗户的间谍++并比较它们的标准文件,打开,你会看到结构和级的名字不匹配。当你仔细看,你还可以发现一些差异的内容之间的对话。我的结论是,Microsoft完全替换的标准的对话中Visual Studio给它的这种能力。我的解决方案或类似的东西将尽可能靠近你可以得到的,除非你愿意代码你自己从头开始。
好吧,让我尝试连接的第一点;-) 玩一点小小间谍++或Winspector显示,文件夹中的文本框在VS项目的位置是一个自定义的标准的对话。这不是相同的领域作为文件文本在标准文件,对话如在记事本。
从那里,我图,与隐藏的文件和文件类型的文本框/组合框并使用一个定义对话的模板,以增加其自己的部分的底部的对话。
编辑:这是一例这样定义和如何做到这一点(在Win32.不。净):
m_ofn的OPENFILENAME结构的基础文件的对话。添加这些2行:
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEDIALOG_IMPORTXLIFF);
m_ofn.Flags |= OFN_ENABLETEMPLATE;
在IDD_FILEDIALOG_IMPORTXLIFF是一个自定义对话的模板,这将增加在底部的对话。看看这部分红色如下。
(资料来源: apptranslator.com)
在这种情况下,定制的部分仅是一个标签,一个超级链接,但它可能是任何对话。它可以包含一个"确定"的按钮,让我们验证文件夹的唯一选择。
但我们如何摆脱一些控制的标准的一部分的对话,我不知道。
更详细 这MSDN文章.
你可以类的文件对话并获得其所有控制。每个人都有一个标识符,可以用来获得它的窗口处理。然后你可以显示和隐藏他们得到的消息,从他们关于选择的更改等等。等等。这一切取决于如何很大的努力要取。
我们没有我们使用维拓级的支持和定制的文件对话,以包括一个自定义的场所条件在COM景。
MSDN 提供的信息关于如何做到这一使用Win32, 这个演示文包括一个例子, , 这个演示文提供。净例.
你可以用这样的代码
- 滤波器隐藏的文件
- 该文件被隐瞒的第一个文本
以先进的隐藏的文本为文件你需要看看
OpenFileDialogEx
代码:
{
openFileDialog2.FileName = "\r";
openFileDialog1.Filter = "folders|*.neverseenthisfile";
openFileDialog1.CheckFileExists = false;
openFileDialog1.CheckPathExists = false;
}
我假设你在Vista使用VS2008?在这种情况下,我认为 FOS_PICKFOLDERS的选择 正在使用时调用Vista对话文件 IFileDialog.我害怕。净的代码这将涉及大量的粗糙的P/调用互操作码,以获得工作。
第一个解决方案
我发明了这个作为清理的版本 .净赢得7式文件夹选择对话 由比尔登的 lyquidity.com (我没有从属关系).(我知道他的代码 另一个答案在这个页面).我写了我自己,因为他的解决方案需要的额外反射类,不需要对这一重点的目的,使用基于异常的流动的控制,不缓的结果,其反思的电话。注意嵌套静 VistaDialog
类是这样,其静态反射的变量不要尝试去填充如果 Show
方法是从来没有所谓。它回落到预Vista对话,如果未在足够高的窗版本。应该在Windows7、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; } }
}
}
}
它是用于像这样在一个窗户的形式:
var dialog = new FolderSelectDialog {
InitialDirectory = musicFolderTextBox.Text,
Title = "Select a folder to import music from"
};
if (dialog.Show(Handle)) {
musicFolderTextBox.Text = dialog.FileName;
}
你当然可以玩弄其选择以及什么样的属性,它暴露了.例如,它可以允许多选在Vista式对话。
第二方案
西蒙风穆里耶给了答案 这显示了,如何做到确切的同样的工作,使用互操作对Windows API直接的,虽然他的版本将具有予以补充,使用老式的对话,如果在一个旧版本的Windows。不幸的是,我没有找到他的岗位然而,当我工作了我的解决方案。名字你的毒药!
试试这个 演示 (信贷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] = {'\0'};
if(::SHGetPathFromIDList(pIDL, buffer) != 0)
{
// Set the string value.
folderpath = buffer;
retVal = true;
}
// free the item id list
CoTaskMemFree(pIDL);
}
::OleUninitialize();
return retVal;
}
在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你总是可以诉诸的伎俩选择的任何文件,在文件夹。
工作实例,工作。净框架2.0和以后可以发现 在这里,.
你可以用这样的代码
滤波器是空的串。文件名是AnyName但不是空白的
openFileDialog.FileName = "AnyFile";
openFileDialog.Filter = string.Empty;
openFileDialog.CheckFileExists = false;
openFileDialog.CheckPathExists = false;
我知道问题是在结构 OpenFileDialog
但看到那谷歌把我带到这里我可以指出,如果只是在寻找的文件夹你应该用一个 FolderBrowserDialog
而作为回答此问题的下面