Click here to Skip to main content
15,885,869 members
Articles / Desktop Programming / Windows Forms

Vista Style Address Bar for .NET 2.0/WinForms

Rate me:
Please Sign up or sign in to vote.
4.77/5 (12 votes)
10 Apr 2010CPOL2 min read 71.1K   2.4K   83  
WinForms version of the Vista style address bar that can be extended to support more than just browsing the file system.
#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)



Comments and Discussions