拾取文件夹
有的时候,我们需要通过类似打开文件那样的对话框来拾取一个已有的文件夹,但查阅相关帮助系统,发现.NET 1.0根本就不提供这样的功能,唯一的解决办法便只有调用WIN API来实现了。
下面的代码是本人在遇到这样的问题时,gOODiDEA给出的答案,这个解决方案从某种程度上解决拾取文件夹的问题,但还存在不足,比如:
1——
界面不是很好,使用的是类似“选择程序打开某个文件”那样的对话框,不友好。而在其他已有的应用中发现可以使用类似OpenFile界面的对话框。
2——
弹出的对话框是非模态的,作为实现文件夹拾取的功能来说,不是很好,而且更要命的是:当主程序关闭后,这个对话框不会自动关闭。
不知哪位网友是否有更好的解决方案共享。
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections;
namespace ArLi.CommonPrj {
#region how use this?
/*
FolderBrowser fbObj = new FolderBrowser();
fbObj.Title = "Select a Folder";
fbObj.Flags =
BrowseFlags.BIF_NEWDIALOGSTYLE|
BrowseFlags.BIF_EDITBOX|
BrowseFlags.BIF_STATUSTEXT
;
DialogResult result = fbObj.ShowFolderBrowser();
if (result == DialogResult.OK ) {
MessageBox.Show(fbObj.DirectoryPath);
}
*/
#endregion
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
[ComVisible(true)]
public class BROWSEINFO {
public IntPtr hwndOwner;
public IntPtr pidlRoot;
public IntPtr pszDisplayName;
public string lpszTitle;
public int ulFlags;
public IntPtr lpfn;
public IntPtr lParam;
public int iImage;
}
[Flags, Serializable]
public enum BrowseFlags {
BIF_DEFAULT = 0x0000,
BIF_BROWSEFORCOMPUTER = 0x1000,
BIF_BROWSEFORPRINTER = 0x2000,
BIF_BROWSEINCLUDEFILES = 0x4000,
BIF_BROWSEINCLUDEURLS = 0x0080,
BIF_DONTGOBELOWDOMAIN = 0x0002,
BIF_EDITBOX = 0x0010,
BIF_NEWDIALOGSTYLE = 0x0040,
BIF_NONEWFOLDERBUTTON = 0x0200,
BIF_RETURNFSANCESTORS = 0x0008,
BIF_RETURNONLYFSDIRS = 0x0001,
BIF_SHAREABLE = 0x8000,
BIF_STATUSTEXT = 0x0004,
BIF_UAHINT = 0x0100,
BIF_VALIDATE = 0x0020,
BIF_NOTRANSLATETARGETS = 0x0400,
}
public class API {
[DllImport("shell32.dll", PreserveSig=true, CharSet=CharSet.Auto)]
public static extern IntPtr SHBrowseForFolder(BROWSEINFO bi);
[DllImport("shell32.dll", PreserveSig=true, CharSet=CharSet.Auto)]
public static extern bool SHGetPathFromIDList(IntPtr pidl, IntPtr pszPath);
[DllImport("shell32.dll", PreserveSig=true, CharSet=CharSet.Auto)]
public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, ref IntPtr ppidl);
}
public class FolderBrowser {
private string m_strDirectoryPath;
private string m_strTitle;
private string m_strDisplayName;
private BrowseFlags m_Flags;
public FolderBrowser() {
m_Flags = BrowseFlags.BIF_DEFAULT;
m_strTitle = "";
}
public string DirectoryPath {
get{return this.m_strDirectoryPath;}
}
public string DisplayName {
get{return this.m_strDisplayName;}
}
public string Title {
set{this.m_strTitle = value;}
}
public BrowseFlags Flags {
set{this.m_Flags = value;}
}
public DialogResult ShowFolderBrowser() {
BROWSEINFO bi = new BROWSEINFO();
bi.pszDisplayName = IntPtr.Zero;
bi.lpfn = IntPtr.Zero;
bi.lParam = IntPtr.Zero;
bi.lpszTitle = "Select Folder";
IntPtr idListPtr = IntPtr.Zero;
IntPtr pszPath = IntPtr.Zero;
try {
if (this.m_strTitle.Length != 0) {
bi.lpszTitle = this.m_strTitle;
}
bi.ulFlags = (int)this.m_Flags;
bi.pszDisplayName = Marshal.AllocHGlobal(256);
idListPtr = API.SHBrowseForFolder(bi);
if (idListPtr == IntPtr.Zero) {
return DialogResult.Cancel;
}
pszPath = Marshal.AllocHGlobal(256);
bool bRet = API.SHGetPathFromIDList(idListPtr, pszPath);
m_strDirectoryPath = Marshal.PtrToStringAuto(pszPath);
this.m_strDisplayName = Marshal.PtrToStringAuto(bi.pszDisplayName);
}
catch (Exception ex) {
Trace.WriteLine(ex.Message);
return DialogResult.Abort;
}
finally {
if (idListPtr != IntPtr.Zero) {
Marshal.FreeHGlobal(idListPtr);
}
if (pszPath != IntPtr.Zero) {
Marshal.FreeHGlobal(pszPath);
}
if (bi != null) {
Marshal.FreeHGlobal(bi.pszDisplayName);
}
}
return DialogResult.OK;
}
}
}