问题描述
在我的申请,我要的FolderBrowserDialog允许我的电脑
的选择。但OK按钮被选择后禁用我的电脑
从对话框中。
In my application, I want the folderBrowserDialog to allow selection of My Computer
. But the OK button gets disabled after selecting My Computer
from the dialog box.
有没有什么办法让我的电脑
中选择浏览对话框
?
Is there any way to allow the selection of My Computer
in Browse Dialog
?
推荐答案
我的电脑(或者这台电脑在最近的Windows版本)是一种特殊的文件夹(不是文件系统文件夹),以及标准的FolderBrowserDialog类不支持它。
My Computer (or This PC in more recent Windows versions) is a special folder (not a file system folder), and the standard FolderBrowserDialog class does not support it.
下面是替代样本 FolderBrowser
类,允许用户选择的任何文件夹。这是使用它的Windows窗体应用程序的例子:
Here is a replacement sample FolderBrowser
class that allows the user to select any folder. This is an example that uses it in a Windows form app:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// other special GUIDs are defined in Windows SDK's ShlGuid.h
Guid CLSID_MyComputer = new Guid("20D04FE0-3AEA-1069-A2D8-08002B30309D");
FolderBrowser dlg = new FolderBrowser();
dlg.Title = "Choose any folder you want";
// optionally uncomment the following line to start from a folder
//dlg.SelectedPath = @"c:\temp";
// optionally uncomment the following line to start from My Computer/This PC
//dlg.SelectedDesktopAbsoluteParsing = "::" + CLSID_MyComputer.ToString("B");
if (dlg.ShowDialog(null) == DialogResult.OK)
{
MessageBox.Show(dlg.SelectedDesktopAbsoluteParsing + Environment.NewLine +
dlg.SelectedNormalDisplay + Environment.NewLine +
dlg.SelectedPath + Environment.NewLine +
dlg.SelectedUrl);
if (dlg.SelectedDesktopAbsoluteParsing == "::" + CLSID_MyComputer.ToString("B").ToUpperInvariant())
{
MessageBox.Show("My Computer was selected!");
}
}
}
}
和在这个答案的底部,你会发现 FolderBrowser
替换类。有趣的是这一行:
And at the bottom of this answer you'll find the FolderBrowser
replacement class. The interesting part is this line:
dialog.SetOptions(FOS.FOS_PICKFOLDERS | FOS.FOS_ALLNONSTORAGEITEMS);
这将指示代码只挑选文件夹,并允许非文件系统的项目。
which will instruct the code to pick only folders and allow non file system items.
有关普通文件夹,返回 SelectedPath
属性将包含的文件夹路径。对于没有存储特殊文件夹,这将是空的。
,而外壳为我们提供了一个包含普通文件夹和将在 SelectedDesktopAbsoluteParsing
属性来定义其他文件夹中一个特殊值的文件夹路径规范绰号。
在我的电脑的情况下,该值将始终以 :: {20D04FE0-3AEA-1069-A2D8-08002B30309D}
For normal folders, the returned SelectedPath
property will contain the folder path. For special folders without a storage, it will be empty.But the shell provides us a canonical moniker that contains the folder path for normal folders and a special values for other folders that will be defined in the SelectedDesktopAbsoluteParsing
property.In the case of My Computer, the value will always be "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}
".
这特殊的语法定义有所这里正式:的。
This special syntax is somewhat defined officially here: Specifying a Namespace Extension's Location.
public class FolderBrowser
{
public string SelectedPath { get; set; }
public string SelectedDesktopAbsoluteParsing { get; set; }
public string Title { get; set; }
public string SelectedNormalDisplay { get; private set; }
public string SelectedUrl { get; private set; }
public DialogResult ShowDialog(IWin32Window owner)
{
IShellItem result = null;
IFileOpenDialog dialog = (IFileOpenDialog)new FileOpenDialog();
if (!string.IsNullOrEmpty(SelectedPath))
{
SelectInitialPath(dialog, SelectedPath);
}
else if (!string.IsNullOrEmpty(SelectedDesktopAbsoluteParsing))
{
SelectInitialPath(dialog, SelectedDesktopAbsoluteParsing);
}
if (!string.IsNullOrWhiteSpace(Title))
{
dialog.SetTitle(Title);
}
dialog.SetOptions(FOS.FOS_PICKFOLDERS | FOS.FOS_ALLNONSTORAGEITEMS);
uint hr = dialog.Show(owner != null ? owner.Handle : IntPtr.Zero);
if (hr == ERROR_CANCELLED)
return DialogResult.Cancel;
if (hr != 0)
return DialogResult.Abort;
dialog.GetResult(out result);
string path;
result.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out path);
SelectedPath = path;
result.GetDisplayName(SIGDN.SIGDN_NORMALDISPLAY, out path);
SelectedNormalDisplay = path;
result.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out path);
SelectedDesktopAbsoluteParsing = path;
result.GetDisplayName(SIGDN.SIGDN_URL, out path);
SelectedUrl = path;
return DialogResult.OK;
}
private void SelectInitialPath(IFileOpenDialog dialog, string path)
{
uint atts = 0;
IntPtr idl = IntPtr.Zero;
if (SHILCreateFromPath(path, out idl, ref atts) == 0)
{
IShellItem initial = null;
if (SHCreateShellItem(IntPtr.Zero, IntPtr.Zero, idl, out initial) == 0)
{
dialog.SetFolder(initial);
}
Marshal.FreeCoTaskMem(idl);
}
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
private static extern int SHILCreateFromPath(string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
[DllImport("shell32.dll")]
private static extern int SHCreateShellItem(IntPtr pidlParent, IntPtr psfParent, IntPtr pidl, out IShellItem ppsi);
private const uint ERROR_CANCELLED = 0x800704C7;
[ComImport]
[Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")]
private class FileOpenDialog
{
}
[Guid("42f85136-db7e-439c-85f1-e4075d135fc8")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IFileOpenDialog
{
[PreserveSig]
uint Show(IntPtr parent); // IModalWindow
void SetFileTypes(); // not fully defined
void SetFileTypeIndex(uint iFileType);
void GetFileTypeIndex(out uint piFileType);
void Advise(); // not fully defined
void Unadvise();
void SetOptions(FOS fos);
void GetOptions(out FOS pfos);
void SetDefaultFolder(IShellItem psi);
void SetFolder(IShellItem psi);
void GetFolder(out IShellItem ppsi);
void GetCurrentSelection(out IShellItem ppsi);
void SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName);
void GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName);
void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
void SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText);
void SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel);
void GetResult(out IShellItem ppsi);
void AddPlace(IShellItem psi, int alignment);
void SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension);
void Close(int hr);
void SetClientGuid(); // not fully defined
void ClearClientData();
void SetFilter([MarshalAs(UnmanagedType.Interface)] IntPtr pFilter);
void GetResults([MarshalAs(UnmanagedType.Interface)] out IntPtr ppenum); // not fully defined
void GetSelectedItems([MarshalAs(UnmanagedType.Interface)] out IntPtr ppsai); // not fully defined
}
[Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IShellItem
{
void BindToHandler(); // not fully defined
void GetParent(); // not fully defined
[PreserveSig]
int GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName);
void GetAttributes(); // not fully defined
void Compare(); // not fully defined
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb762544.aspx
private enum SIGDN : uint
{
SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,
SIGDN_FILESYSPATH = 0x80058000,
SIGDN_NORMALDISPLAY = 0,
SIGDN_PARENTRELATIVE = 0x80080001,
SIGDN_PARENTRELATIVEEDITING = 0x80031001,
SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
SIGDN_PARENTRELATIVEPARSING = 0x80018001,
SIGDN_URL = 0x80068000
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn457282.aspx
[Flags]
private enum FOS
{
FOS_ALLNONSTORAGEITEMS = 0x80,
FOS_ALLOWMULTISELECT = 0x200,
FOS_CREATEPROMPT = 0x2000,
FOS_DEFAULTNOMINIMODE = 0x20000000,
FOS_DONTADDTORECENT = 0x2000000,
FOS_FILEMUSTEXIST = 0x1000,
FOS_FORCEFILESYSTEM = 0x40,
FOS_FORCESHOWHIDDEN = 0x10000000,
FOS_HIDEMRUPLACES = 0x20000,
FOS_HIDEPINNEDPLACES = 0x40000,
FOS_NOCHANGEDIR = 8,
FOS_NODEREFERENCELINKS = 0x100000,
FOS_NOREADONLYRETURN = 0x8000,
FOS_NOTESTFILECREATE = 0x10000,
FOS_NOVALIDATE = 0x100,
FOS_OVERWRITEPROMPT = 2,
FOS_PATHMUSTEXIST = 0x800,
FOS_PICKFOLDERS = 0x20,
FOS_SHAREAWARE = 0x4000,
FOS_STRICTFILETYPES = 4
}
}
这篇关于C#如何让我的FolderBrowserDialog与电脑的选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!