在我的应用程序中,我希望 folderBrowserDialog 允许选择My Computer
. My Computer
但是从对话框中选择后,确定按钮会被禁用。
有什么方法可以选择My Computer
inBrowse Dialog
吗?
在我的应用程序中,我希望 folderBrowserDialog 允许选择My Computer
. My Computer
但是从对话框中选择后,确定按钮会被禁用。
有什么方法可以选择My Computer
inBrowse Dialog
吗?
我的电脑(或更新的 Windows 版本中的这台电脑)是一个特殊文件夹(不是文件系统文件夹),标准的 FolderBrowserDialog 类不支持它。
这是一个替换示例FolderBrowser
类,它允许用户选择任何文件夹。这是一个在 Windows 窗体应用程序中使用它的示例:
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
替换类。有趣的部分是这一行:
dialog.SetOptions(FOS.FOS_PICKFOLDERS | FOS.FOS_ALLNONSTORAGEITEMS);
这将指示代码仅选择文件夹并允许非文件系统项目。
对于普通文件夹,返回的SelectedPath
属性将包含文件夹路径。对于没有存储空间的特殊文件夹,它将是空的。但是 shell 为我们提供了一个规范的名字对象,其中包含普通文件夹的文件夹路径和将在SelectedDesktopAbsoluteParsing
属性中定义的其他文件夹的特殊值。对于我的电脑,该值将始终为“ ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}
”。
这种特殊的语法在这里正式定义了一些:指定命名空间扩展的位置。
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)
{
var 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 IShellItem result);
SelectedPath = GetDisplayName(result, SIGDN.SIGDN_FILESYSPATH);
SelectedNormalDisplay = GetDisplayName(result, SIGDN.SIGDN_NORMALDISPLAY);
SelectedDesktopAbsoluteParsing = GetDisplayName(result, SIGDN.SIGDN_DESKTOPABSOLUTEPARSING);
SelectedUrl = GetDisplayName(result, SIGDN.SIGDN_URL);
return DialogResult.OK;
}
private static string GetDisplayName(IShellItem item, SIGDN sigdnName)
{
item.GetDisplayName(sigdnName, out var ptr);
var name = Marshal.PtrToStringUni(ptr);
Marshal.FreeCoTaskMem(ptr);
return name;
}
private void SelectInitialPath(IFileOpenDialog dialog, string path)
{
uint atts = 0;
IntPtr idl = IntPtr.Zero;
if (SHILCreateFromPath(path, out idl, ref atts) == 0)
{
if (SHCreateShellItem(IntPtr.Zero, IntPtr.Zero, idl, out IShellItem 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(out IntPtr 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, out IntPtr 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
}
}
有一种可能:使用功能:
[StructLayout(LayoutKind.Sequential)]
public struct BROWSEINFO
{
public IntPtr hwndOwner;
public IntPtr pidlRoot;
//public IntPtr pszDisplayName;
public string pszDisplayName;
public string lpszTitle;
public uint ulFlags;
public BrowseCallbackProc lpfn;
public IntPtr lParam;
public int iImage;
}
[DllImport("shell32.dll")]
public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);
[DllImport("shell32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SHGetPathFromIDListW(IntPtr pidl, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszPath);
[DllImport("shell32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SHGetPathFromIDListW(IntPtr pidl, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszPath);
回调可以设置为:
private int _callback(IntPtr hDlg, int msg, IntPtr lParam, IntPtr lpData)
{
switch (msg)
{
case 2://BFFM_SELCHANGED:
StringBuilder sb1 = new StringBuilder();
Win32.SHGetPathFromIDListW((IntPtr)lParam, sb);
Win32.EnableWindow(Win32.GetDlgItem(hDlg, CtlIds.IDOK), true);
break;
}
return 0;
}
致电:
BROWSEINFO bi = new Win32.BROWSEINFO();
bi.lpfn = new Win32.BrowseCallbackProc(callback);
string selected = SHBrowseForFolder(ref bi);
OK 将是可点击的。我还没有发现的唯一问题是如何确保我的计算机被选中。
一些来源来自: http: //www.codeproject.com/Articles/159352/FolderBrowserDialogEx-AC-customization-of-FolderB