Here's a simple wrapper around the SHBrowseForFolder() shell function.
*EDIT* Updated with more features!
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace CommonDialogWrappers
{
public class BrowseForFolderDialog
{
#region Public Properties
public string SelectedFolder { get; protected set; }
public string Title
{
get { return BrowseInfo.lpszTitle; }
set { BrowseInfo.lpszTitle = value; }
}
public string InitialFolder { get; set; }
public string InitialExpandedFolder { get; set; }
public string OKButtonText { get; set; }
BROWSEINFOW browseInfo;
public BROWSEINFOW BrowseInfo
{
get { return browseInfo; }
protected set { browseInfo = value; }
}
public BrowseInfoFlags BrowserDialogFlags
{
get { return BrowseInfo.ulFlags; }
set { BrowseInfo.ulFlags = value; }
}
#endregion
#region Public Constructors
public BrowseForFolderDialog()
{
BrowseInfo = new BROWSEINFOW();
BrowseInfo.hwndOwner = IntPtr.Zero;
BrowseInfo.pidlRoot = IntPtr.Zero;
BrowseInfo.pszDisplayName = new String(' ', 260);
BrowseInfo.lpszTitle = "Select a folder:";
BrowseInfo.ulFlags = BrowseInfoFlags.BIF_NEWDIALOGSTYLE;
BrowseInfo.lpfn = new BrowseCallbackProc(BrowseEventHandler);
BrowseInfo.lParam = IntPtr.Zero;
BrowseInfo.iImage = -1;
}
#endregion
#region Public ShowDialog() Overloads
public Nullable<bool> ShowDialog()
{
return PInvokeSHBrowseForFolder(null);
}
public Nullable<bool> ShowDialog(Window owner)
{
return PInvokeSHBrowseForFolder(owner);
}
#endregion
#region PInvoke Stuff
private Nullable<bool> PInvokeSHBrowseForFolder(Window owner)
{
WindowInteropHelper windowhelper;
if (null != owner)
{
windowhelper = new WindowInteropHelper(owner);
BrowseInfo.hwndOwner = windowhelper.Handle;
}
IntPtr pidl = SHBrowseForFolderW(browseInfo);
if (IntPtr.Zero != pidl)
{
StringBuilder pathsb = new StringBuilder(260);
if (false != SHGetPathFromIDList(pidl, pathsb))
{
SelectedFolder = pathsb.ToString();
Marshal.FreeCoTaskMem(pidl);
return true;
}
}
return false;
}
private int BrowseEventHandler(IntPtr hwnd, MessageFromBrowser uMsg, IntPtr lParam, IntPtr lpData)
{
switch (uMsg)
{
case MessageFromBrowser.BFFM_INITIALIZED:
{
if (!string.IsNullOrEmpty(InitialExpandedFolder))
SendMessageW(hwnd, MessageToBrowser.BFFM_SETEXPANDED, new IntPtr(1), InitialExpandedFolder);
else if (!string.IsNullOrEmpty(InitialFolder))
SendMessageW(hwnd, MessageToBrowser.BFFM_SETSELECTIONW, new IntPtr(1), InitialFolder);
if (!string.IsNullOrEmpty(OKButtonText))
SendMessageW(hwnd, MessageToBrowser.BFFM_SETOKTEXT, new IntPtr(1), OKButtonText);
break;
}
case MessageFromBrowser.BFFM_SELCHANGED:
{
StringBuilder pathsb = new StringBuilder(260);
if (false != SHGetPathFromIDList(lParam, pathsb))
{
SelectedFolder = pathsb.ToString();
}
break;
}
case MessageFromBrowser.BFFM_VALIDATEFAILEDA:
{
break;
}
case MessageFromBrowser.BFFM_VALIDATEFAILEDW:
{
break;
}
case MessageFromBrowser.BFFM_IUNKNOWN:
{
break;
}
}
return 0;
}
public delegate int BrowseCallbackProc(IntPtr hwnd, MessageFromBrowser uMsg, IntPtr lParam, IntPtr lpData);
[Flags]
public enum BrowseInfoFlags : uint
{
BIF_None = 0x0000,
BIF_RETURNONLYFSDIRS = 0x0001,
BIF_DONTGOBELOWDOMAIN = 0x0002,
BIF_STATUSTEXT = 0x0004,
BIF_RETURNFSANCESTORS = 0x0008,
BIF_EDITBOX = 0x0010,
BIF_VALIDATE = 0x0020,
BIF_NEWDIALOGSTYLE = 0x0040,
BIF_USENEWUI = BIF_NEWDIALOGSTYLE | BIF_EDITBOX,
BIF_BROWSEINCLUDEURLS = 0x0080,
BIF_UAHINT = 0x0100,
BIF_NONEWFOLDERBUTTON = 0x0200,
BIF_NOTRANSLATETARGETS = 0x0400,
BIF_BROWSEFORCOMPUTER = 0x1000,
BIF_BROWSEFORPRINTER = 0x2000,
BIF_BROWSEINCLUDEFILES = 0x4000,
BIF_SHAREABLE = 0x8000
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class BROWSEINFOW
{
public IntPtr hwndOwner;
public IntPtr pidlRoot;
public string pszDisplayName;
public string lpszTitle;
public BrowseInfoFlags ulFlags;
public BrowseCallbackProc lpfn;
public IntPtr lParam;
public int iImage;
}
public enum MessageFromBrowser : uint
{
BFFM_INITIALIZED = 1,
BFFM_SELCHANGED = 2,
BFFM_VALIDATEFAILEDA = 3,
BFFM_VALIDATEFAILEDW = 4,
BFFM_IUNKNOWN = 5
}
public enum MessageToBrowser : uint
{
WM_USER = 0x0400,
BFFM_SETSTATUSTEXTA = WM_USER + 100,
BFFM_ENABLEOK = WM_USER + 101,
BFFM_SETSELECTIONA = WM_USER + 102,
BFFM_SETSELECTIONW = WM_USER + 103,
BFFM_SETSTATUSTEXTW = WM_USER + 104,
BFFM_SETOKTEXT = WM_USER + 105,
BFFM_SETEXPANDED = WM_USER + 106
}
[DllImport("shell32.dll")]
private static extern IntPtr SHBrowseForFolderW([MarshalAs(UnmanagedType.LPStruct), In, Out] BROWSEINFOW bi);
[DllImport("shell32.dll")]
private static extern bool SHGetPathFromIDList(IntPtr pidl, StringBuilder path);
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, MessageToBrowser msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string str);
#endregion
}
}
Sample usage:
CommonDialogWrappers.BrowseForFolderDialog dlg = new CommonDialogWrappers.BrowseForFolderDialog();
dlg.Title = "Select a folder and click OK!";
dlg.InitialExpandedFolder = @"c:\";
dlg.OKButtonText = "OK!";
if (true == dlg.ShowDialog(this))
{
MessageBox.Show(dlg.SelectedFolder, "Selected Folder");
}
Mark Salsbery
Microsoft MVP - Visual C++
modified on Wednesday, November 12, 2008 2:48 PM
|