Imports System Imports System.Drawing Imports System.Collections Imports System.ComponentModel Imports System.Data Imports System.Runtime.InteropServices Namespace Etier.IconHelper ''' <summary> ''' Provides static methods to read system icons for both folders and files. ''' </summary> ''' <example> ''' <code>IconReader.GetFileIcon("c://general.xls");</code> ''' </example> Public Class IconReader ''' <summary> ''' Options to specify the size of icons to return. ''' </summary> Public Enum IconSize ''' <summary> ''' Specify large icon - 32 pixels by 32 pixels. ''' </summary> Large = 0 ''' <summary> ''' Specify small icon - 16 pixels by 16 pixels. ''' </summary> Small = 1 End Enum ''' <summary> ''' Options to specify whether folders should be in the open or closed state. ''' </summary> Public Enum FolderType ''' <summary> ''' Specify open folder. ''' </summary> Open = 0 ''' <summary> ''' Specify closed folder. ''' </summary> Closed = 1 End Enum ''' <summary> ''' Returns an icon for a given file - indicated by the name parameter. ''' </summary> ''' <param name="name">Pathname for file.</param> ''' <param name="size">Large or small</param> ''' <param name="linkOverlay">Whether to include the link icon</param> ''' <returns>System.Drawing.Icon</returns> Public Shared Function GetFileIcon(ByVal name As String, ByVal size As IconSize, ByVal linkOverlay As Boolean) As System.Drawing.Icon Dim shfi As New Shell32.SHFILEINFO() Dim flags As UInteger = Shell32.SHGFI_ICON Or Shell32.SHGFI_USEFILEATTRIBUTES If True = linkOverlay Then flags += Shell32.SHGFI_LINKOVERLAY End If ' Check the size specified for return. If IconSize.Small = size Then flags += Shell32.SHGFI_SMALLICON Else flags += Shell32.SHGFI_LARGEICON End If Shell32.SHGetFileInfo(name, Shell32.FILE_ATTRIBUTE_NORMAL, shfi, CInt(System.Runtime.InteropServices.Marshal.SizeOf(shfi)), flags) ' Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly Dim icon As System.Drawing.Icon = DirectCast(System.Drawing.Icon.FromHandle(shfi.hIcon).Clone(), System.Drawing.Icon) User32.DestroyIcon(shfi.hIcon) ' Cleanup Return icon End Function ''' <summary> ''' Used to access system folder icons. ''' </summary> ''' <param name="size">Specify large or small icons.</param> ''' <param name="folderType">Specify open or closed FolderType.</param> ''' <returns>System.Drawing.Icon</returns> Public Shared Function GetFolderIcon(ByVal size As IconSize, ByVal folderType As FolderType) As System.Drawing.Icon ' Need to add size check, although errors generated at present! Dim flags As UInteger = Shell32.SHGFI_ICON Or Shell32.SHGFI_USEFILEATTRIBUTES If FolderType.Open = folderType Then flags += Shell32.SHGFI_OPENICON End If If IconSize.Small = size Then flags += Shell32.SHGFI_SMALLICON Else flags += Shell32.SHGFI_LARGEICON End If ' Get the folder icon Dim shfi As New Shell32.SHFILEINFO() Shell32.SHGetFileInfo(Nothing, Shell32.FILE_ATTRIBUTE_DIRECTORY, shfi, CInt(System.Runtime.InteropServices.Marshal.SizeOf(shfi)), flags) System.Drawing.Icon.FromHandle(shfi.hIcon) ' Load the icon from an HICON handle ' Now clone the icon, so that it can be successfully stored in an ImageList Dim icon As System.Drawing.Icon = DirectCast(System.Drawing.Icon.FromHandle(shfi.hIcon).Clone(), System.Drawing.Icon) User32.DestroyIcon(shfi.hIcon) ' Cleanup Return icon End Function End Class ' This code has been left largely untouched from that in the CRC example. The main changes have been moving ' the icon reading code over to the IconReader type. ''' <summary> ''' Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code ''' courtesy of MSDN Cold Rooster Consulting case study. ''' </summary> ''' Public Class Shell32 Public Const MAX_PATH As Integer = 256 <StructLayout(LayoutKind.Sequential)> _ Public Structure SHITEMID Public cb As UShort <MarshalAs(UnmanagedType.LPArray)> _ Public abID As Byte() End Structure <StructLayout(LayoutKind.Sequential)> _ Public Structure ITEMIDLIST Public mkid As SHITEMID End Structure <StructLayout(LayoutKind.Sequential)> _ Public Structure BROWSEINFO Public hwndOwner As IntPtr Public pidlRoot As IntPtr Public pszDisplayName As IntPtr <MarshalAs(UnmanagedType.LPTStr)> _ Public lpszTitle As String Public ulFlags As UInteger Public lpfn As IntPtr Public lParam As Integer Public iImage As IntPtr End Structure ' Browsing for directory. Public Const BIF_RETURNONLYFSDIRS As UInteger = 1 Public Const BIF_DONTGOBELOWDOMAIN As UInteger = 2 Public Const BIF_STATUSTEXT As UInteger = 4 Public Const BIF_RETURNFSANCESTORS As UInteger = 8 Public Const BIF_EDITBOX As UInteger = 16 Public Const BIF_VALIDATE As UInteger = 32 Public Const BIF_NEWDIALOGSTYLE As UInteger = 64 Public Const BIF_USENEWUI As UInteger = (BIF_NEWDIALOGSTYLE Or BIF_EDITBOX) Public Const BIF_BROWSEINCLUDEURLS As UInteger = 128 Public Const BIF_BROWSEFORCOMPUTER As UInteger = 4096 Public Const BIF_BROWSEFORPRINTER As UInteger = 8192 Public Const BIF_BROWSEINCLUDEFILES As UInteger = 16384 Public Const BIF_SHAREABLE As UInteger = 32768 <StructLayout(LayoutKind.Sequential)> _ Public Structure SHFILEINFO Public Const NAMESIZE As Integer = 80 Public hIcon As IntPtr Public iIcon As Integer Public dwAttributes As UInteger <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> _ Public szDisplayName As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=NAMESIZE)> _ Public szTypeName As String End Structure Public Const SHGFI_ICON As UInteger = 256 ' get icon Public Const SHGFI_DISPLAYNAME As UInteger = 512 ' get display name Public Const SHGFI_TYPENAME As UInteger = 1024 ' get type name Public Const SHGFI_ATTRIBUTES As UInteger = 2048 ' get attributes Public Const SHGFI_ICONLOCATION As UInteger = 4096 ' get icon location Public Const SHGFI_EXETYPE As UInteger = 8192 ' return exe type Public Const SHGFI_SYSICONINDEX As UInteger = 16384 ' get system icon index Public Const SHGFI_LINKOVERLAY As UInteger = 32768 ' put a link overlay on icon Public Const SHGFI_SELECTED As UInteger = 65536 ' show icon in selected state Public Const SHGFI_ATTR_SPECIFIED As UInteger = 131072 ' get only specified attributes Public Const SHGFI_LARGEICON As UInteger = 0 ' get large icon Public Const SHGFI_SMALLICON As UInteger = 1 ' get small icon Public Const SHGFI_OPENICON As UInteger = 2 ' get open icon Public Const SHGFI_SHELLICONSIZE As UInteger = 4 ' get shell size icon Public Const SHGFI_PIDL As UInteger = 8 ' pszPath is a pidl Public Const SHGFI_USEFILEATTRIBUTES As UInteger = 16 ' use passed dwFileAttribute Public Const SHGFI_ADDOVERLAYS As UInteger = 32 ' apply the appropriate overlays Public Const SHGFI_OVERLAYINDEX As UInteger = 64 ' Get the index of the overlay Public Const FILE_ATTRIBUTE_DIRECTORY As UInteger = 16 Public Const FILE_ATTRIBUTE_NORMAL As UInteger = 128 <DllImport("Shell32.dll")> _ Public Shared Function SHGetFileInfo(ByVal pszPath As String, ByVal dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, ByVal cbFileInfo As UInteger, ByVal uFlags As UInteger) As IntPtr End Function End Class ''' <summary> ''' Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example. ''' </summary> Public Class User32 ''' <summary> ''' Provides access to function required to delete handle. This method is used internally ''' and is not required to be called separately. ''' </summary> ''' <param name="hIcon">Pointer to icon handle.</param> ''' <returns>N/A</returns> <DllImport("User32.dll")> _ Public Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Integer End Function End Class End Namespace Namespace Etier.IconHelper ''' <summary> ''' Maintains a list of currently added file extensions ''' </summary> Public Class IconListManager Private _extensionList As New Hashtable() Private _imageLists As System.Collections.ArrayList = New ArrayList() 'will hold ImageList objects Private _iconSize As IconHelper.IconReader.IconSize Private ManageBothSizes As Boolean = False 'flag, used to determine whether to create two ImageLists. ''' <summary> ''' Creates an instance of <c>IconListManager</c> that will add icons to a single <c>ImageList</c> using the ''' specified <c>IconSize</c>. ''' </summary> ''' <param name="imageList"><c>ImageList</c> to add icons to.</param> ''' <param name="iconSize">Size to use (either 32 or 16 pixels).</param> Public Sub New(ByVal imageList As System.Windows.Forms.ImageList, ByVal iconSize As IconReader.IconSize) ' Initialise the members of the class that will hold the image list we're ' targeting, as well as the icon size (32 or 16) _imageLists.Add(imageList) _iconSize = iconSize End Sub ''' <summary> ''' Creates an instance of IconListManager that will add icons to two <c>ImageList</c> types. The two ''' image lists are intended to be one for large icons, and the other for small icons. ''' </summary> ''' <param name="smallImageList">The <c>ImageList</c> that will hold small icons.</param> ''' <param name="largeImageList">The <c>ImageList</c> that will hold large icons.</param> Public Sub New(ByVal smallImageList As System.Windows.Forms.ImageList, ByVal largeImageList As System.Windows.Forms.ImageList) 'add both our image lists _imageLists.Add(smallImageList) _imageLists.Add(largeImageList) 'set flag ManageBothSizes = True End Sub ''' <summary> ''' Used internally, adds the extension to the hashtable, so that its value can then be returned. ''' </summary> ''' <param name="Extension"><c>String</c> of the file's extension.</param> ''' <param name="ImageListPosition">Position of the extension in the <c>ImageList</c>.</param> Private Sub AddExtension(ByVal Extension As String, ByVal ImageListPosition As Integer) _extensionList.Add(Extension, ImageListPosition) End Sub ''' <summary> ''' Called publicly to add a file's icon to the ImageList. ''' </summary> ''' <param name="filePath">Full path to the file.</param> ''' <returns>Integer of the icon's position in the ImageList</returns> Public Function AddFileIcon(ByVal filePath As String) As Integer ' Check if the file exists, otherwise, throw exception. If Not System.IO.File.Exists(filePath) Then Throw New System.IO.FileNotFoundException("File does not exist") End If ' Split it down so we can get the extension Dim splitPath As String() = filePath.Split(New Char() {"."c}) Dim extension As String = DirectCast(splitPath.GetValue(splitPath.GetUpperBound(0)), String) 'Check that we haven't already got the extension, if we have, then 'return back its index If _extensionList.ContainsKey(extension.ToUpper()) Then 'return existing index Return CInt(_extensionList(extension.ToUpper())) Else ' It's not already been added, so add it and record its position. Dim pos As Integer = DirectCast(_imageLists(0), ImageList).Images.Count 'store current count -- new item's index If ManageBothSizes = True Then 'managing two lists, so add it to small first, then large DirectCast(_imageLists(0), ImageList).Images.Add(IconReader.GetFileIcon(filePath, IconReader.IconSize.Small, False)) DirectCast(_imageLists(1), ImageList).Images.Add(IconReader.GetFileIcon(filePath, IconReader.IconSize.Large, False)) Else 'only doing one size, so use IconSize as specified in _iconSize. 'add to image list DirectCast(_imageLists(0), ImageList).Images.Add(IconReader.GetFileIcon(filePath, _iconSize, False)) End If AddExtension(extension.ToUpper(), pos) ' add to hash table Return pos End If End Function ''' <summary> ''' Clears any <c>ImageLists</c> that <c>IconListManager</c> is managing. ''' </summary> Public Sub ClearLists() For Each imageList As ImageList In _imageLists 'clear current imagelist. imageList.Images.Clear() Next _extensionList.Clear() 'empty hashtable of entries too. End Sub End Class End Namespace