C# – Set folder view programmatically

CHECK THE UPDATE BELOW FOR BETTER SOLUTION
Making block code to accomplish a small task of Windows Explorer is always my favorite. Last week I read a thread on mycsharp.de asking about how to set folder view programmatically. I find this question interesting and try myself to write a small block code to set view for defined folder. As you can see in every version of Windows, we have 8 different views to choose : Extra large icons, Large icons, Medium icons, Small icons, List, Details, Tiles and Content. Just right click anywhere in your folder, hove the mouse over menu View, you’ll see the list of them as image below

Folder view of windows

At the beginning I think it’s pretty simple to do this, may be through an undocumented API or something like that. But after an hour of searching in Internet I could not find this simple API and it turns to be very difficult. There are some shell functions like SHCreateShellFolderView and IFolderView::SetCurrentViewMode which can be relevant to the topic but I am not good with Shell Programming therefore I decide to make a working example by opening the given folder with explorer and then using SendMessage function to send Windows messages to folder for setting its view. If you want to learn more about Win32 API Programming, you can read this book
Win32 Programming (Addison-Wesley Advanced Windows Series)(2 Vol set)

A pseudo code looks like this one

WinAPI.SendMessage(handle_of_view_window, WinAPI.WM_COMMAND, new IntPtr((int)view), IntPtr.Zero);

For the parameters I should give the function the handle of window and the enumerated value of view which I want to set. The enumerated value of 8 views are listed below

enum FolderView
{
	DETAILS = 0x704b,
	TILES = 0x704c,
	EXTRA_LARGE_ICONS = 0x704d,
	LARGE_ICONS = 0x704f,
	MEDIUM_ICONS = 0x704e,
	SMALL_ICONS = 0x7050,
	LIST = 0x7051,            
	CONTENT = 0x7052
}

Now it’s time to find out the handle of window which I must send the windows messages to. You can use Spy++ to get this handle in Windows-Handle-Tree window of Spy++

Window handle tree

Bases on this handle tree, I get each handle of child component until the “SHELLDLL_DefView” component

private static void SetFolderView(string path, FolderView view)
{
	try
	{
		if (Directory.Exists(path))
		{
			int tries = 0;

			WinAPI.ShellExecute(IntPtr.Zero, "Open", path, "", "", WinAPI.ShowCommands.SW_NORMAL);

			IntPtr hwndFolder = IntPtr.Zero;

			while (hwndFolder == IntPtr.Zero && tries < 100)
			{
				hwndFolder = WinAPI.FindWindow("CabinetWClass", Path.GetFileName(path));
				tries++;
				Thread.Sleep(100);
			}

			if (hwndFolder != IntPtr.Zero)
			{
				IntPtr hwndFolderShellTab = WinAPI.FindWindowEx(hwndFolder, IntPtr.Zero, "ShellTabWindowClass", Path.GetFileName(path));
				IntPtr hwndFolderDUIViewWnd = WinAPI.FindWindowEx(hwndFolderShellTab, IntPtr.Zero, "DUIViewWndClassName", "");
				IntPtr hwndFolderDirectUIHWND = WinAPI.FindWindowEx(hwndFolderDUIViewWnd, IntPtr.Zero, "DirectUIHWND", "");
				IntPtr hwndFolderCtrlNotifySink1 = WinAPI.FindWindowEx(hwndFolderDirectUIHWND, IntPtr.Zero, "CtrlNotifySink", "");
				IntPtr hwndFolderCtrlNotifySink2 = WinAPI.FindWindowEx(hwndFolderDirectUIHWND, hwndFolderCtrlNotifySink1, "CtrlNotifySink", "");
				IntPtr hwndFolderCtrlNotifySink3 = WinAPI.FindWindowEx(hwndFolderDirectUIHWND, hwndFolderCtrlNotifySink2, "CtrlNotifySink", "");
				IntPtr hwndFolderSHELLDLL_DefView = WinAPI.FindWindowEx(hwndFolderCtrlNotifySink3, IntPtr.Zero, "SHELLDLL_DefView", "ShellView");

				WinAPI.SendMessage(hwndFolderSHELLDLL_DefView, WinAPI.WM_COMMAND, new IntPtr((int)view), IntPtr.Zero);

				bool returnValue = WinAPI.PostMessage(hwndFolder, WinAPI.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
				if (!returnValue)
					throw new Win32Exception(Marshal.GetLastWin32Error());                           
			}
			else
			{
				Console.WriteLine("Can not get handle of opened folder");
			}

		}
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
	}
}

After opening the given folder, I must wait a little so that the folder is completely opened in explorer then I can catch its handle, start to move along the tree until I reach the View component, set its view and close folder with WM_CLOSE in explorer again. The screen flickers little with opening and closing folder. It’ll be better if we can directly set the folder view in registry as discussed here http://support.microsoft.com/kb/812003 . The structure format of this registry key is so complicated which requires a lot of time with reverse engineering to understand its format. Therefore I must give up the idea writing in registry cause of time consuming. My code is , of course , not the good one but it works at least. If you have time and want to challenge yourself, then try to make a class which helps us to generate this registry key storing the folder view. And as usual, you can download the complete source code at “Set folder view programmatically

UPDATE 20.02.2014
Because the method I discussed above doesn’t work anymore with Windows 8 therefore I would like to introduced another way to get/set folder view with C#. With this new one you need to use Microsoft Internet Controls SHDocVw. So, in your project, make a reference to SHDocVw.dll (which normally locates under c:\windows\system32\shdocvw.dll)

shdocvw reference

The new method will use IFolderView interface to get/set the folder view mode. The detailed source code can be downloaded from link above. The code listing below shows only how the main idea is

SHDocVw.ShellWindows shellWindows = null;
try
{
	shellWindows = new SHDocVw.ShellWindows();
	foreach (Set_folder_view_2.WinAPI._IServiceProvider serviceProvider in shellWindows)
	{
		SHDocVw.InternetExplorer ie = (SHDocVw.InternetExplorer)serviceProvider;

		if (Path.GetFileNameWithoutExtension(ie.FullName).Equals("explorer", StringComparison.OrdinalIgnoreCase) && ie.LocationURL.Equals("file:///" + path.Replace("\\", "/"), StringComparison.OrdinalIgnoreCase))
		{
			object oShellBrowser;
			serviceProvider.QueryService(Set_folder_view_2.WinAPI.ExplorerGUIDs.IID_IShellBrowser, Set_folder_view_2.WinAPI.ExplorerGUIDs.IID_IUnknown, out oShellBrowser);
			Set_folder_view_2.WinAPI.IShellBrowser shellBrowser = oShellBrowser as Set_folder_view_2.WinAPI.IShellBrowser;
			Set_folder_view_2.WinAPI.IShellView shellView = null;
			try
			{
				if (0 == shellBrowser.QueryActiveShellView(out shellView))
				{
					Set_folder_view_2.WinAPI.IFolderView folderView = shellView as Set_folder_view_2.WinAPI.IFolderView;

					if (folderView != null)
					{
						Set_folder_view_2.WinAPI.FOLDERVIEWMODE currentMode = 0;
						folderView.GetCurrentViewMode(ref currentMode);
						Console.WriteLine(currentMode.ToString());
						folderView.SetCurrentViewMode(folderViewMode);
					}
				}
			}
			catch
			{
			}
			finally
			{
				if (shellView != null)
					Marshal.ReleaseComObject(shellView);
			}
		}
	}
}
catch (Exception ex)
{
	Console.WriteLine(ex);
}
finally
{
	if (shellWindows != null)
	{
		Marshal.ReleaseComObject(shellWindows);
	}
}

With the help of ShellWindows object, we can get a list of opened windows by explorer.exe. We just need to loop through this list, find the folder we want to get/set view mode by comparing the path of folder. Then use QueryService() functions of _IServiceProvider to get IShellBrowser, when you have this object, the remain things are just simple. You get the IShellView, IFolderView and call GetCurrentViewMode()/SetCurrentViewMode() to get/set the folder view mode as you want. The advantage of this solution is that will work with all versions of Windows but you have to make a reference to SHDocVw.dll COM object which can cause unexpected behavior at run-time (such as unexpected crashing at start up because of compatibility).

6 thoughts on “C# – Set folder view programmatically”

  1. Hello,
    SetFolderView works fine for me.
    But how I can get the Folder view?
    Greetings and merry Xmas, Bernhard

  2. this is cool… I am also looking to display “date last saved” by default for a specific folder.. is that possible?

  3. @Bernhard Wiesweg : It’s too late response but I updated new solution so that you can read/set folder view mode of a specific windows. Check the update above for more details.

  4. @pinker: No, since Windows 7, IID_IDockingWindowFrame was not supported anymore (using QueryService causes error Interfaces not registered) therefore you have no chance to add toolbar to Windows Explorer

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>