www.pudn.com > ObjectListViewDemo.zip > ShellUtilities.cs


/* 
 * [File purpose] 
 * Author: Phillip Piper 
 * Date: 1 May 2007 7:44 PM 
 *  
 * CHANGE LOG: 
 * when who what 
 * 1 May 2007 JPP  Initial Version 
 */ 
 
using System; 
using System.Drawing; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 
 
namespace BrightIdeasSoftware 
{ 
    ///  
    /// This helper class allows listviews and tree views to use image from the system image list. 
    ///  
    /// Instances of this helper class know how to retrieve icon from the Windows shell for 
    /// a given file path. These icons are then added to the imagelist on the given control. ListViews need  
    /// special handling since they have two image lists which need to be kept in sync. 
	public class SysImageListHelper 
	{ 
        private SysImageListHelper() 
        { 
        } 
 
        ///  
        /// Create a SysImageListHelper that will fetch images for the given tree control 
        ///  
        /// The tree view that will use the images 
        public SysImageListHelper(TreeView treeView) 
        { 
            if (treeView.ImageList == null) { 
                treeView.ImageList = new ImageList(); 
                treeView.ImageList.ImageSize = new Size(16, 16); 
            } 
            this.smallImageCollection = treeView.ImageList.Images; 
        } 
 
        ///  
        /// Create a SysImageListHelper that will fetch images for the given listview control. 
        ///  
        /// The listview that will use the images 
        /// Listviews manage two image lists, but each item can only have one image index. 
        /// This means that the image for an item must occur at the same index in the two lists.  
        /// SysImageListHelper instances handle this requirement. However, if the listview already 
        /// has image lists installed, they must be of the same length. 
        public SysImageListHelper(ListView listView) 
        { 
            if (listView.SmallImageList == null) { 
                listView.SmallImageList = new ImageList(); 
                listView.SmallImageList.ImageSize = new Size(16, 16); 
            } 
 
            if (listView.LargeImageList == null) { 
                listView.LargeImageList = new ImageList(); 
                listView.LargeImageList.ImageSize = new Size(32, 32); 
            } 
 
            if (listView.SmallImageList.Images.Count != listView.LargeImageList.Images.Count) 
                throw new ArgumentException("Small and large image lists must have the same number of items."); 
 
            this.smallImageCollection = listView.SmallImageList.Images; 
            this.largeImageCollection = listView.LargeImageList.Images; 
        } 
 
        ///  
        /// Return the index of the image that has the Shell Icon for the given file/directory. 
        ///  
        /// The full path to the file/directory 
        /// The index of the image or -1 if something goes wrong. 
        public int GetImageIndex(string path) 
        { 
            if (System.IO.Directory.Exists(path)) 
                path = System.Environment.SystemDirectory; // optimization! give all directories the same image 
            else 
                if (System.IO.Path.HasExtension(path)) 
                    path = System.IO.Path.GetExtension(path); 
 
            if (this.smallImageCollection.ContainsKey(path)) 
                return this.smallImageCollection.IndexOfKey(path); 
 
            try { 
                this.smallImageCollection.Add(path, ShellUtilities.GetFileIcon(path, true, true)); 
                if (this.largeImageCollection != null) 
                    this.largeImageCollection.Add(path, ShellUtilities.GetFileIcon(path, false, true)); 
            } catch (ArgumentNullException) { 
                return -1; 
            } 
 
            return this.smallImageCollection.IndexOfKey(path); 
        } 
 
        private ImageList.ImageCollection smallImageCollection = null; 
        private ImageList.ImageCollection largeImageCollection = null; 
    } 
	 
	///  
	/// ShellUtilities contains routines to interact with the Windows Shell. 
	///  
	public static class ShellUtilities 
	{ 
        ///  
        /// Execute the default verb on the file or directory identified by the given path. 
        /// For documents, this will open them with their normal application. For executables, 
        /// this will cause them to run. 
        ///  
        /// The file or directory to be executed 
        /// Values < 31 indicate some sort of error. See ShellExecute() documentation for specifics. 
        /// The same effect can be achieved by System.Diagnostics.Process.Start(path). 
        public static int Execute(string path) 
        { 
            return ShellUtilities.Execute(path, ""); 
        } 
 
        ///  
        /// Execute the given operation on the file or directory identified by the given path. 
        /// Example operations are "edit", "print", "explore". 
        ///  
        /// The file or directory to be operated on 
        /// Values < 31 indicate some sort of error. See ShellExecute() documentation for specifics. 
        public static int Execute(string path, string operation) 
        { 
            IntPtr result = ShellUtilities.ShellExecute(0, operation, path, "", "", SW_SHOWNORMAL); 
            return result.ToInt32(); 
        } 
 
        ///  
        /// Get the string that describes the file's type. 
        ///  
        /// The file or directory whose type is to be fetched 
        /// A string describing the type of the file, or an empty string if something goes wrong. 
        public static String GetFileType(string path) 
        { 
            SHFILEINFO shfi = new SHFILEINFO(); 
            int flags = SHGFI_TYPENAME; 
            IntPtr result = ShellUtilities.SHGetFileInfo(path, 0, out shfi, Marshal.SizeOf(shfi), flags); 
            if (result.ToInt32() == 0) 
                return String.Empty; 
            else 
                return shfi.szTypeName; 
        } 
 
        ///  
        /// Return the icon for the given file/directory. 
        ///  
        /// The full path to the file whose icon is to be returned 
        /// True if the small (16x16) icon is required, otherwise the 32x32 icon will be returned 
        /// The icon of the given file, or null if something goes wrong 
        public static Icon GetFileIcon(string path, bool isSmallImage, bool useFileType) 
        { 
            int flags = SHGFI_ICON; 
            if (isSmallImage) 
                flags |= SHGFI_SMALLICON; 
 
            int fileAttributes = 0; 
            if (useFileType) { 
                flags |= SHGFI_USEFILEATTRIBUTES; 
                if (System.IO.Directory.Exists(path)) 
                    fileAttributes = FILE_ATTRIBUTE_DIRECTORY; 
                else 
                    fileAttributes = FILE_ATTRIBUTE_NORMAL; 
            } 
 
            SHFILEINFO shfi = new SHFILEINFO(); 
            IntPtr result = ShellUtilities.SHGetFileInfo(path, fileAttributes, out shfi, Marshal.SizeOf(shfi), flags); 
            if (result.ToInt32() == 0) 
                return null; 
            else 
                return Icon.FromHandle(shfi.hIcon); 
        } 
 
        ///  
        /// Return the index into the system image list of the image that represents the given file. 
        ///  
        /// The full path to the file or directory whose icon is required 
        /// The index of the icon, or -1 if something goes wrong 
        /// This is only useful if you are using the system image lists directly. Since there is 
        /// no way to do that in .NET, it isn't a very useful. 
        public static int GetSysImageIndex(string path) 
        { 
            SHFILEINFO shfi = new SHFILEINFO(); 
            int flags = SHGFI_ICON | SHGFI_SYSICONINDEX; 
            IntPtr result = ShellUtilities.SHGetFileInfo(path, 0, out shfi, Marshal.SizeOf(shfi), flags); 
            if (result.ToInt32() == 0) 
                return -1; 
            else 
                return shfi.iIcon; 
        } 
 
        #region Native methods 
 
        private const int SHGFI_ICON               = 0x00100;     // get icon 
        private const int SHGFI_DISPLAYNAME        = 0x00200;     // get display name 
        private const int SHGFI_TYPENAME           = 0x00400;     // get type name 
        private const int SHGFI_ATTRIBUTES         = 0x00800;     // get attributes 
        private const int SHGFI_ICONLOCATION       = 0x01000;     // get icon location 
        private const int SHGFI_EXETYPE            = 0x02000;     // return exe type 
        private const int SHGFI_SYSICONINDEX       = 0x04000;     // get system icon index 
        private const int SHGFI_LINKOVERLAY        = 0x08000;     // put a link overlay on icon 
        private const int SHGFI_SELECTED           = 0x10000;     // show icon in selected state 
        private const int SHGFI_ATTR_SPECIFIED     = 0x20000;     // get only specified attributes 
        private const int SHGFI_LARGEICON          = 0x00000;     // get large icon 
        private const int SHGFI_SMALLICON          = 0x00001;     // get small icon 
        private const int SHGFI_OPENICON           = 0x00002;     // get open icon 
        private const int SHGFI_SHELLICONSIZE      = 0x00004;     // get shell size icon 
        private const int SHGFI_PIDL               = 0x00008;     // pszPath is a pidl 
        private const int SHGFI_USEFILEATTRIBUTES  = 0x00010;     // use passed dwFileAttribute 
		//if (_WIN32_IE >= 0x0500) 
        private const int SHGFI_ADDOVERLAYS        = 0x00020;     // apply the appropriate overlays 
        private const int SHGFI_OVERLAYINDEX       = 0x00040;     // Get the index of the overlay 
 
        private const int FILE_ATTRIBUTE_NORMAL    = 0x00080;     // Normal file 
        private const int FILE_ATTRIBUTE_DIRECTORY = 0x00010;     // Directory 
 
        private const int MAX_PATH = 260; 
 
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
		private struct SHFILEINFO 
		{ 
			public IntPtr hIcon;  
			public int    iIcon;  
			public int    dwAttributes;  
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)] 
			public string szDisplayName; 
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)] 
			public string szTypeName;  
		} 
 
        private const int SW_SHOWNORMAL = 1; 
 
        [DllImport("shell32.dll", CharSet = CharSet.Auto)] 
        private static extern IntPtr ShellExecute(int hwnd, string lpOperation, string lpFile,  
            string lpParameters, string lpDirectory, int nShowCmd); 
 
        [DllImport("shell32.dll", CharSet = CharSet.Auto)] 
        private static extern IntPtr SHGetFileInfo(string pszPath, int dwFileAttributes, 
            out SHFILEINFO psfi, int cbFileInfo, int uFlags); 
 
        #endregion 
    } 
}