.NET Win 7-style folder select dialog


Sometimes it’s necessary to allow a user to select a folder not a file. The .NET FolderBrowserDialog (part of System.Windows.Forms) is showing its age. With Vista came a new folder selection dialog based on the OpenFileDialog but the Vista-style dialog has not been added to .NET. This post includes code (c#) to display the Vista/Win 7 style folder selection dialog.

Download the source code. There’s no license as such as you are free to take and do with the code what you will.

Here’s what the old folder selection dialog looks. If you search for information about selecting folders from a .NET application, this is what you’ll be referred to.

By contrast, if you use a Windows 7 application, this is what you will see.

Much better. IMHO it’s better because you are able to sort and search plus, sometimes, the old dialog will not enumerate network computers making it impossible to select folders on networked resources. In the new-style dialog you are able to enter a clue into the address box to get it to the correct machine.

Graceful degradation

Being a Vista-style dialog box the dialog can only be shown on Vista or later (not WinNT, XP or 2003). The code gracefully reverts to show the old-style dialog if OS is not major version 6 or later.

How does it work?

It turns out that the ability to show a Vista-like dialog is present in .NET but the methods are not public. So the ShowDialog() method uses reflection to call CreateVistaDialog and pass in all the parameters. The technique to do this is taken from the Google code project FED.

Information and Links

Join the fray by commenting, tracking what others have to say, or linking to it from your blog.


Other Posts

Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Thank you – this was a great help; I hate the standard folder select dialog.

Is there a way to hide this dialog from taskbar? Because it don’t have icon: https://dl.dropboxusercontent.com/u/14076298/ShareX/2013/09/BnLoLMuTOH.png
Default .NET folder and file dialogs not show up in taskbar therefore not having icon is not a problem.

I don’t know the answer. Most Windows APIs calls work by passing a reference to a data structure containing information relevant to the API. I imagine there is an option to control whether or not the file select dialog also appears in the task bar and which icon it shows. Normally the icon displayed is that of the ‘owning’ application. That is, the application or form referenced in the owner field.

Absolutely excellent! With a little tweak, it also allows multiselecting folders too (a feature not available in traditional methods altogether).
Thank you!

Superb code sample, has been a real help, thanks.

Using the same code for a different example now, and with the FOS_PICKFOLDERS option removed, how can one modify the SetFileTypes options to filer by specific file types?

This resource may help:

http://msdn.microsoft.com/en-us/library/windows/desktop/bb761832%28v=vs.85%29.aspx

I thought filters could be set using code like this but when I try I receive a ‘catastrophic failure’ exception. The message seem a little sensational and not very helpful. Maybe you will have better success.

// This is the type to be passed to the SetFileTypes method
Type t = r.GetType(“FileDialogNative.COMDLG_FILTERSPEC”);

// Create an array of the COMDLG_FILTERSPEC type
Array specs3 = Array.CreateInstance(t, 2);

object spec = (object)Activator.CreateInstance(t);
spec.GetType().GetField(“pszName”, BindingFlags.NonPublic | BindingFlags.Instance).SetValue(spec, “My favorite JPEG files”);
spec.GetType().GetField(“pszSpec”, BindingFlags.NonPublic | BindingFlags.Instance).SetValue(spec, “*.jpg;*.jpeg”);
specs3.SetValue(spec, 0);

spec = (object)Activator.CreateInstance(t);
spec.GetType().GetField(“pszName”, BindingFlags.NonPublic | BindingFlags.Instance).SetValue(spec, “Uncompress raster files”);
spec.GetType().GetField(“pszSpec”, BindingFlags.NonPublic | BindingFlags.Instance).SetValue(spec, “*.bmp”);
specs3.SetValue(spec, 1);

object[] parameters = new object[] { (UInt32)2, specs3 };

// Exception here. The CallAs2 method retrieves the method information but fails when it is invoked
r.CallAs2(typeIFileDialog, dialog, “SetFileTypes”, parameters);

Cheers for the response – but what type is the variable “r” in that example?

It’s the ‘r’ in the original code. It the reference to the reflected dialog box.

Thank you for this elegant solution!

Brilliant!!! No words, I have been trying this for long without success.
Thanks a ton!

@Jaex

To remove “open folder” from task bar use:
FolderSelectDialog dlg = new FolderSelectDialog();
dlg.ShowDialog(this.Handle)

where “this” is the main Form that calls the FolderSelectDialog class.

Amazing!

Great work! This is what I’m looking for. Thanks!

@Julo

I checked how .NET doing it:

if (zero == IntPtr.Zero)
{
zero = UnsafeNativeMethods.GetActiveWindow();
}

So by default .NET dialogs getting active window handle.

[DllImport(“user32.dll”)]
public static extern IntPtr GetActiveWindow();

Thank you, works perfectly!!!