Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Vista Style Address Bar for .NET 2.0/WinForms

, 10 Apr 2010
WinForms version of the Vista style address bar that can be extended to support more than just browsing the file system.
AddressBarExt.zip
AddressBarEx
AddressBarExt.csproj.user
AddressBarExt.suo
bin
Debug
AddressBarExt.exe
AddressBarExt.vshost.exe
Controls
Node
Interface
GRSD_LowCompat.ico
Properties
Settings.settings
AddressBarExt2.zip
AddressBarExt
AddressBarExt.suo
AddressBarEx_2.0
AddressBarExt_2.0.csproj.user
Backup
AddressBarExt.csproj.user
AddressBarExt.suo
Controls
Node
Interface
GRSD_LowCompat.ico
Properties
Settings.settings
bin
Controls
Node
Interface
obj
Debug
AddressBarExt.Controls.AddressBarExt.resources
AddressBarExt.csproj.GenerateResource.Cache
AddressBarExt.dll
AddressBarExt.exe
AddressBarExt.Form1.resources
AddressBarExt.pdb
AddressBarExt.Properties.Resources.resources
AddressBarExt_2.0.csproj.GenerateResource.Cache
Refactor
TempPE
Properties.Resources.Designer.cs.dll
Release
AddressBarExt.csproj.GenerateResource.Cache
AddressBarExt.exe
TempPE
Properties.Resources.Designer.cs.dll
Properties
Settings.settings
DemoApp_2.0
bin
DemoApp_2.0.csproj.user
GRSD_LowCompat.ico
obj
Debug
AddressBarExt.Form1.resources
DemoApp_2.0.csproj.GenerateResource.Cache
DemoApp_2.0.exe
DemoApp_2.0.pdb
DemoApp_2._0.Properties.Resources.resources
Refactor
ResolveAssemblyReference.cache
TempPE
Release
TempPE
Properties
Settings.settings
AddressBarExt2_1.zip
AddressBarExt2_1
AddressBarExt
AddressBarExt.suo
AddressBarEx_2.0
Controls
Node
Interface
Properties
Settings.settings
DemoApp_2.0
GRSD_LowCompat.ico
Properties
Settings.settings
#region Using Statements

#region .NET Namespace

using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

#endregion

#endregion


namespace AddressBarExt
{
    /// <summary>
    /// Class that implements the IAddressNode Interface to allow for parsing a file system in the Address Bar.
    /// 
    /// Author : James Strain
    /// Email : leon_STARS@hotmail.com
    /// Tested Platforms : Windows Vista Ultimate x64 / WinXP  Pro 32-bit
    /// 
    /// Additional Work Needed :
    /// 
    /// None that I am aware of...
    /// 
    /// </summary>
    public class FileSystemNode : IAddressNode
    {
        #region Class Variables

        /// <summary>
        /// Stores the parent node to this node
        /// </summary>
        private IAddressNode parent = null;

        /// <summary>
        /// Stores the display name of this Node
        /// </summary>
        private String szDisplayName = null;

        /// <summary>
        /// Stores the full path to this node (Unique ID)
        /// </summary>
        private String fullPath = null;

        /// <summary>
        /// Stores the Icon for this node
        /// </summary>
        private Icon icon = null;

        /// <summary>
        /// Stores the child nodes
        /// </summary>
        private IAddressNode[] children = null;

        /// <summary>
        /// Stores user defined data for this node
        /// </summary>
        private Object tag = null;

        #endregion

        #region Properties

        /// <summary>
        /// Gets/Sets the parent node to this node
        /// </summary>
        public IAddressNode Parent
        {
            get { return this.parent; }
            set { this.parent = value; }
        }

        /// <summary>
        /// Gets/Sets the Display name of this node
        /// </summary>
        public String DisplayName
        {
            get{return this.szDisplayName;}
            set { this.szDisplayName = value; }
        }

        /// <summary>
        /// Gets the Icon that represents this node type.
        /// </summary>
        public Icon Icon
        {
            get { return this.icon; }
        }

        /// <summary>
        /// Returns the Unique Id for this node
        /// </summary>
        public Object UniqueID
        {
            get { return this.fullPath; }
        }

        /// <summary>
        /// Gets/Sets user defined data for this object
        /// </summary>
        public Object Tag
        {
            get { return this.tag; }
            set { this.tag = value; }
        }

        /// <summary>
        /// Gets the children of this node
        /// </summary>
        public IAddressNode[] Children
        {
            get { return this.children; }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Basic Constructor, initializes this node to start at the root of the first drive found on the disk. ONLY USE THIS FOR ROOT NODES
        /// </summary>
        public FileSystemNode()
        {
            //get the display name of the first logical drive
            szDisplayName = fullPath = Environment.GetLogicalDrives()[0];
            this.parent = null;

            //get the icon
            MakeIcon();
        }

        /// <summary>
        /// Creates a File System node with a given path
        /// </summary>
        /// <param name="path">Path that this node represents</param>
        /// <param name="depth">Integer represnting how deep in the hierarchy this node is</param>
        public FileSystemNode(string path, FileSystemNode parent)
        {
            //fill in the relevant details
            fullPath = path;
            szDisplayName = PathToDisplayName(path);
            this.parent = parent;

            //get the icon
            MakeIcon();
        }

        #endregion

        #region Destructor

        ~FileSystemNode()
        {
            if (children != null)
            {
                for (int i = 0; i < this.children.Length; i++)
                    this.children.SetValue(null, i);

                this.children = null;
            }

            if(icon != null)
                this.icon.Dispose();

            this.icon = null;
        }

        #endregion

        #region Node Update

        /// <summary>
        /// Updates the contents of this node.
        /// </summary>
        public void UpdateNode()
        {
            try
            {
                //get sub-folders for this folder
                Array subFolders = System.IO.Directory.GetDirectories(fullPath);

                //if we have not allocated our children yet
                if (children == null)
                {
                    //create space for the children
                    children = new FileSystemNode[subFolders.Length];

                    for (int i = 0; i < subFolders.Length; i++)
                    {
                        //create the child value
                        children[i] = new FileSystemNode(subFolders.GetValue(i).ToString(), this);
                    }
                }
            }
            /**
            * This is just a sample, so has bad error handling ;)
            * 
            **/
            catch (System.Exception ioex)
            {
                //write a message to stderr
                System.Console.Error.WriteLine(ioex.Message);
            }
        }

        #endregion

        #region General

        /// <summary>
        /// Method takes in a full path, and makes a clean display name
        /// </summary>
        /// <param name="path">String representation of the full path</param>
        /// <returns>Returns a clean string that represents a user friendly name for display</returns>
        private string PathToDisplayName(string path)
        {
            string aString = Path.GetFileName(path);

            if (aString.Length == 0)
                return path;
            else
                return aString;
        }

        /// <summary>
        /// Returns an individual child node, based on a given unique ID. NOT IMPLEMENTED.
        /// </summary>
        /// <param name="uniqueID">Unique Object to identify the child</param>
        /// <param name="recursive">Indicates whether we should recursively search child nodes</param>
        /// <returns>Returns a child node. Returns null if method fails.</returns>
        public IAddressNode GetChild(object uniqueID, bool recursive)
        {
            //sample version doesn't support recursive search ;)
            if(recursive)
                return null;

            for (int i = 0; i < children.Length; i++)
            {
                if (children[i].UniqueID.ToString() == uniqueID.ToString())
                    return children[i];
            }

            return null;
        }

        /// <summary>
        /// Creates a clone of this node
        /// </summary>
        /// <returns>Cloned Node</returns>
        public IAddressNode Clone()
        {
            //return the new node
            return new FileSystemNode(this.fullPath, (FileSystemNode)this.parent);
        }

        /// <summary>
        /// Sets the icon for the given path
        /// </summary>
        private void MakeIcon()
        {
            //if the path exists
            if (icon == null)
            {
                //needed to get a handle to our icon
                SHFILEINFO shinfo = new SHFILEINFO();

                //handle to the un-managed icon
                IntPtr hIcon = IntPtr.Zero;

                //get the item
                hIcon = Win32.SHGetFileInfo(fullPath, 0,ref shinfo, (uint)Marshal.SizeOf(shinfo),Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);

                //create the managed icon
                this.icon =(Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon).Clone();

                //dispose of the old icon
                Win32.DestroyIcon(shinfo.hIcon);
            }
        }

        #endregion
    }

    #region Win32 Interop for Icons

    [StructLayout(LayoutKind.Sequential)]
    public struct SHFILEINFO
    {
        public IntPtr hIcon;
        public IntPtr iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    };

    class Win32
    {
        public const uint SHGFI_ICON = 0x100;
        public const uint SHGFI_SMALLICON = 0x1;

        [DllImport("shell32.dll")]
        public static extern IntPtr SHGetFileInfo(string pszPath,
                                    uint dwFileAttributes,
                                    ref SHFILEINFO psfi,
                                    uint cbSizeFileInfo,
                                    uint uFlags);
        [DllImport("user32.dll")]
        public static extern bool DestroyIcon(IntPtr hIcon);
    }

    #endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

jwraith
Software Developer
United Kingdom United Kingdom
A graduate of the University of Dundee, and an ex-Microsoft UK Support Engineer currently happily employed at Codemasters, Southam.
Follow on   Twitter

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 10 Apr 2010
Article Copyright 2009 by jwraith
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid