拾取文件夹

有的时候,我们需要通过类似打开文件那样的对话框来拾取一个已有的文件夹,但查阅相关帮助系统,发现.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;
  }
 }
}

posted @ 2004-04-10 08:30  无之无  阅读(985)  评论(1编辑  收藏  举报