Skip to content

Instantly share code, notes, and snippets.

@shadowfox
Created June 23, 2013 08:26
Show Gist options
  • Save shadowfox/5844287 to your computer and use it in GitHub Desktop.
Save shadowfox/5844287 to your computer and use it in GitHub Desktop.
A dialog the can select either a folder or a file. Only one selection is possible.
using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class DirectoryDialog
{
/// <summary>
/// The BROWSEINFO structure used by SHBrowseForFolder.
/// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb773205%28v=vs.85%29.aspx
/// </summary>
public struct BROWSEINFO
{
public IntPtr hWndOwner;
public int pIDLRoot;
public string pszDisplayName;
public string lpszTitle;
public int ulFlags;
public int lpfnCallback;
public int lParam;
public int iImage;
}
/// <summary>
/// What to show in the directory dialog
/// See 'ulFlags' at http://msdn.microsoft.com/en-us/library/windows/desktop/bb773205%28v=vs.85%29.aspx
/// </summary>
public enum BrowseForTypes : int
{
Directories = 1, // BIF_RETURNONLYFSDIRS (0x00000001)
FileSystemAncestors = 8, // BIF_RETURNFSANCESTORS (0x00000008)
Computers = 4096, // BIF_BROWSEFORCOMPUTER (0x00001000)
FilesAndDirectories = 16384 // BIF_BROWSEINCLUDEFILES (0x00004000)
}
/// <summary>
/// The maximum path length.
/// A value of 260 matches the value used in the Windows API.
/// </summary>
const int MAX_PATH = 260;
private BrowseForTypes browseFor = BrowseForTypes.Directories;
private string title = "";
private string selected = "";
/// <summary>
/// The title of the dialog
/// </summary>
public string Title
{
get
{
return title;
}
set
{
if (object.ReferenceEquals(value, DBNull.Value))
{
throw new ArgumentNullException();
}
title = value;
}
}
/// <summary>
/// The selected item
/// </summary>
public string Selected
{
get
{
return selected;
}
}
/// <summary>
/// What the dialog is browsing for
/// </summary>
public BrowseForTypes BrowseFor
{
get
{
return browseFor;
}
set
{
browseFor = value;
}
}
/// <summary>
/// DirectoryDialog constructor
/// </summary>
public DirectoryDialog()
{
}
[DllImport("ole32", EntryPoint = "CoTaskMemFree", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int CoTaskMemFree(IntPtr hMem);
[DllImport("kernel32", EntryPoint = "lstrcat", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr lstrcat(string lpString1, string lpString2);
[DllImport("shell32", EntryPoint = "SHBrowseForFolder", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);
[DllImport("shell32", EntryPoint = "SHGetPathFromIDList", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int SHGetPathFromIDList(IntPtr pidList, StringBuilder lpBuffer);
/// <summary>
/// Show the directory dialog
/// The PInvoke for SHBrowseForFolder and friends is required for this
/// </summary>
/// <param name="hMem"></param>
/// <returns></returns>
protected bool RunDialog(IntPtr hWndOwner)
{
BROWSEINFO udtBI = new BROWSEINFO();
IntPtr lpIDList = default(IntPtr);
GCHandle hTitle = GCHandle.Alloc(Title, GCHandleType.Pinned);
udtBI.hWndOwner = hWndOwner;
udtBI.lpszTitle = Title;
udtBI.ulFlags = (int)BrowseFor;
StringBuilder buffer = new StringBuilder(MAX_PATH);
buffer.Length = MAX_PATH;
udtBI.pszDisplayName = buffer.ToString();
lpIDList = SHBrowseForFolder(ref udtBI);
hTitle.Free();
if (lpIDList.ToInt64() == 0)
{
return false;
}
if (BrowseFor == BrowseForTypes.Computers)
{
selected = udtBI.pszDisplayName.Trim();
}
else
{
StringBuilder path = new StringBuilder(MAX_PATH);
SHGetPathFromIDList(lpIDList, path);
selected = path.ToString();
}
CoTaskMemFree(lpIDList);
return true;
}
/// <summary>
/// Show the directory dialog box
/// </summary>
/// <returns>A DialogResult enum</returns>
public DialogResult ShowDialog()
{
return ShowDialog(null);
}
/// <summary>
/// Show the directory dialog box
/// </summary>
/// <param name="owner">The owner window handler</param>
/// <returns>A DialogResult enum</returns>
public DialogResult ShowDialog(IWin32Window owner)
{
IntPtr handle = default(IntPtr);
if ((owner != null))
{
handle = owner.Handle;
}
else
{
handle = IntPtr.Zero;
}
if (RunDialog(handle))
{
return DialogResult.OK;
}
else
{
return DialogResult.Cancel;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment