Windows Forms Folder Tree View control for .Net
Version 1.1, posted 20-Oct-2002
(c)Copyright 2002 Furty (furty74@yahoo.com
). All rights reserved.
Free for any use, so long as copyright is acknowledged.
This is an all-new version of the FolderTreeView control I posted here at CP some weeks ago.
The control now starts in the Desktop namespace, and a new DrillToFolder method has been added
so the startup folder can be specified. Please note that this control is not intended to have
all of the functionality of the actual Windows Explorer TreeView - it is a light-weight control
designed for use in projects where you want to supply a treeview for folder navigation, without supporting
windows shell extensions. If you are looking for a control that supports shell extensions
you should be looking at the excellent ヒxplorerTreeControl submitted by Carlos H Perez at the CP website.
The 3 classes that make up the control have been merged into the one file here for ease of
integration into your own projects. The reason for separate classes is that this code has been
extracted from a much larger project I'm working on, and the code that is not required for this
control has been removed.
Acknowledgments:
Substantial portions of the ShellOperations and ExtractIcons classes were borrowed from the
FTPCom article written by Jerome Lacaille, available on the www.codeproject.com
website.
If you improve this control, please email me the updated source, and if you have any
comments or suggestions, please post your thoughts in the feedback section on the
codeproject.com page for this control.
Version 1.11 Changes:
Updated the GetDesktopIcon method so that the small (16x16) desktop icon is returned instead of the large version
Added code to give the Desktop root node a FolderItem object tag equal to the DesktopDirectory SpecialFolder,
this ensures that the desktop node returns a file path.
*/
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using System.Diagnostics;
namespace Furty.Windows.Forms
{
#region FolderTreeView Class
public class FolderTreeView : System.Windows.Forms.TreeView
{
private System.Windows.Forms.ImageList folderTreeViewImageList;
private System.Globalization.CultureInfo cultureInfo = System.Globalization.CultureInfo.CurrentCulture;
#region Constructors
public FolderTreeView()
{
this.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.TreeViewBeforeExpand);
}
private void InitImageList()
{
// setup the image list to hold the folder icons
folderTreeViewImageList = new System.Windows.Forms.ImageList();
folderTreeViewImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
folderTreeViewImageList.ImageSize = new System.Drawing.Size(16, 16);
folderTreeViewImageList.TransparentColor = System.Drawing.Color.Transparent;
// add the Desktop icon to the image list
try
{
folderTreeViewImageList.Images.Add(ExtractIcons.GetDesktopIcon());
}
catch
{
// Create a blank icon if the desktop icon fails for some reason
Bitmap bmp = new Bitmap(16,16);
Image img = (Image)bmp;
folderTreeViewImageList.Images.Add((Image)img.Clone());
bmp.Dispose();
}
this.ImageList = folderTreeViewImageList;
}
tree.Nodes.Clear();
TreeNode desktop = new TreeNode("Desktop", 0, 0);
// Added in version 1.11
// add a FolderItem object to the root (Desktop) node tag that corresponds to the DesktopDirectory namespace
// This ensures that the GetSelectedNodePath will return the actual Desktop folder path when queried.
// There's possibly a better way to create a Shell32.FolderItem instance for this purpose,
// but I surely don't know it
Shell32.Folder dfolder = shell32.NameSpace(ShellFolder.DesktopDirectory);
foreach(Shell32.FolderItem fi in dfolder.ParentFolder.Items())
{
if(fi.Name == dfolder.Title)
{
desktop.Tag = fi;
break;
}
}
// Add the Desktop root node to the tree
tree.Nodes.Add(desktop);
// iterate through the Desktop namespace and populate the first level nodes
foreach(Shell32.FolderItem item in items)
{
if(item.IsFolder) // this ensures that desktop shortcuts etc are not displayed
{
TreeNode tn = AddTreeNode(item, ref imageCount, imageList, getIcons);
desktop.Nodes.Add(tn);
CheckForSubDirs(tn, imageList);
}
}
}
#endregion
#region Fill Sub Dirs
private static void FillSubDirectories(TreeNode tn, ref int imageCount, ImageList imageList, bool getIcons)
{
Shell32.FolderItem folderItem = (Shell32.FolderItem)tn.Tag;
Shell32.Folder folder = (Shell32.Folder)folderItem.GetFolder;
public class ExtractIcons
{
#region Structs & Enum
[StructLayout(LayoutKind.Sequential)]
private struct SHFILEINFO
{
public SHFILEINFO(bool b)
{
hIcon=IntPtr.Zero;iIcon=0;dwAttributes=0;szDisplayName="";szTypeName="";
}
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.LPStr, SizeConst=260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.LPStr, SizeConst=80)]
public string szTypeName;
};
private enum SHGFI
{
SHGFI_ICON = 0x000000100, // get icon
SHGFI_DISPLAYNAME = 0x000000200, // get display name
SHGFI_TYPENAME = 0x000000400, // get type name
SHGFI_ATTRIBUTES = 0x000000800, // get attributes
SHGFI_ICONLOCATION = 0x000001000, // get icon location
SHGFI_EXETYPE = 0x000002000, // return exe type
SHGFI_SYSICONINDEX = 0x000004000, // get system icon index
SHGFI_LINKOVERLAY = 0x000008000, // put a link overlay on icon
SHGFI_SELECTED = 0x000010000, // show icon in selected state
SHGFI_ATTR_SPECIFIED = 0x000020000, // get only specified attributes
SHGFI_LARGEICON = 0x000000000, // get large icon
SHGFI_SMALLICON = 0x000000001, // get small icon
SHGFI_OPENICON = 0x000000002, // get open icon
SHGFI_SHELLICONSIZE = 0x000000004, // get shell size icon
SHGFI_PIDL = 0x000000008, // pszPath is a pidl
SHGFI_USEFILEATTRIBUTES = 0x000000010 // use passed dwFileAttribute
}
public static Icon GetIcon(string strPath, bool selected, ImageList imageList)
{
SHFILEINFO info = new SHFILEINFO(true);
int cbFileInfo = Marshal.SizeOf(info);
SHGFI flags;
if (!selected)
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_SMALLICON;
else
flags = SHGFI.SHGFI_ICON|SHGFI.SHGFI_SMALLICON|SHGFI.SHGFI_OPENICON;
SHGetFileInfo(strPath, 256, out info,(uint)cbFileInfo, flags);
return Icon.FromHandle(info.hIcon);
}
#endregion
#region Get Desktop Icon
// Retreive the desktop icon from Shell32.dll - it always appears at index 34 in all shell32 versions.
// This is probably NOT the best way to retreive this icon, but it works - if you have a better way
// by all means let me know..
// [DllImport("Shell32.dll", CharSet=CharSet.Auto)]
// public static extern IntPtr ExtractIcon(int hInst, string lpszExeFileName, int nIconIndex);
//
// public static Icon GetDesktopIcon()
// {
// IntPtr i = ExtractIcon(0, Environment.SystemDirectory + "\\shell32.dll
", 34);
// return Icon.FromHandle(i);
// }
// Updated this method in v1.11 so that the icon returned is a small icon, not a large icon as
// returned by the old method above
[DllImport("Shell32.dll", CharSet=CharSet.Auto)]
public static extern uint ExtractIconEx(
string lpszFile, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, uint nIcons );
public static Icon GetDesktopIcon()
{
IntPtr[] handlesIconLarge = new IntPtr[1];
IntPtr[] handlesIconSmall = new IntPtr[1];
uint i = ExtractIconEx(Environment.SystemDirectory + "\\shell32.dll
", 34,
handlesIconLarge, handlesIconSmall, 1);