|
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Threading
Imports ExpTreeLib.ShellDll
Public Class SystemImageListManager
#Region " ImageList Related Constants"
' For ImageList manipulation
Private Const LVM_FIRST = &H1000
Private Const LVM_SETIMAGELIST = (LVM_FIRST + 3)
Private Const LVSIL_NORMAL = 0
Private Const LVSIL_SMALL = 1
Private Const LVSIL_STATE = 2
Private Const TV_FIRST = &H1100
Private Const TVM_SETIMAGELIST = (TV_FIRST + 9)
Private Const TVSIL_NORMAL = 0
Private Const TVSIL_STATE = 2
#End Region
#Region " Private Fields"
Private Shared m_Initialized As Boolean = False
Private Shared m_smImgList As IntPtr = IntPtr.Zero 'Handle to System Small ImageList
Private Shared m_lgImgList As IntPtr = IntPtr.Zero 'Handle to System Large ImageList
Private Shared m_Table As New Hashtable(128)
Private Shared m_Mutex As New Mutex()
#End Region
#Region " New"
Private Shared Sub Initializer()
If m_Initialized Then
Exit Sub
End If
Dim dwFlag As Integer = SHGFI.USEFILEATTRIBUTES Or _
SHGFI.SYSICONINDEX Or _
SHGFI.SMALLICON
Dim shfi As New SHFILEINFO()
m_smImgList = SHGetFileInfo(".txt", _
FILE_ATTRIBUTE_NORMAL, _
shfi, _
cbFileInfo, _
dwFlag)
Debug.Assert((Not m_smImgList.Equals(IntPtr.Zero)), "Failed to create Image Small ImageList")
If m_smImgList.Equals(IntPtr.Zero) Then
Throw New Exception("Failed to create Small ImageList")
End If
dwFlag = SHGFI.USEFILEATTRIBUTES Or _
SHGFI.SYSICONINDEX Or _
SHGFI.LARGEICON
m_lgImgList = SHGetFileInfo(".txt", _
FILE_ATTRIBUTE_NORMAL, _
shfi, _
cbFileInfo, _
dwFlag)
Debug.Assert((Not m_lgImgList.Equals(IntPtr.Zero)), "Failed to create Image Small ImageList")
If m_lgImgList.Equals(IntPtr.Zero) Then
Throw New Exception("Failed to create Large ImageList")
End If
m_Initialized = True
End Sub
#End Region
#Region " Public Properties"
Public Shared ReadOnly Property hSmallImageList() As IntPtr
Get
Return m_smImgList
End Get
End Property
Public Shared ReadOnly Property hLargeImageList() As IntPtr
Get
Return m_lgImgList
End Get
End Property
#End Region
#Region " Public Methods"
#Region " GetIconIndex"
Private Shared mCnt As Integer
Private Shared bCnt As Integer
Public Shared Function GetIconIndex(ByRef item As CShItem, Optional ByVal GetOpenIcon As Boolean = False) As Integer
Initializer()
Dim HasOverlay As Boolean = False 'true if it's an overlay
Dim rVal As Integer 'The returned Index
Dim dwflag As Integer = SHGFI.SYSICONINDEX Or _
SHGFI.PIDL Or SHGFI.ICON
Dim dwAttr As Integer = 0
'build Key into HashTable for this Item
Dim Key As Integer = IIf(Not GetOpenIcon, item.IconIndexNormal * 256, _
item.IconIndexOpen * 256)
With item
If .IsLink Then
Key = Key Or 1
dwflag = dwflag Or SHGFI.LINKOVERLAY
HasOverlay = True
End If
If .IsShared Then
Key = Key Or 2
dwflag = dwflag Or SHGFI.ADDOVERLAYS
HasOverlay = True
End If
If m_Table.ContainsKey(Key) Then
rVal = (m_Table(Key))
mCnt += 1
ElseIf Not HasOverlay Then 'for non-overlay icons, we already have
rVal = Key \ 256 ' the right index -- put in table
m_Table(Key) = rVal
bCnt += 1
Else 'don't have iconindex for an overlay, get it.
'This is the tricky part -- add overlaid Icon to systemimagelist
Dim shfi As New SHFILEINFO()
Dim HR As IntPtr
If .IsFileSystem And Not .IsDisk And Not .IsFolder Then
dwflag = dwflag Or SHGFI.USEFILEATTRIBUTES
dwAttr = FILE_ATTRIBUTE_NORMAL
End If
HR = SHGetFileInfo(.PIDL, dwAttr, shfi, cbFileInfo, dwflag)
m_Mutex.WaitOne()
rVal = ImageList_ReplaceIcon(m_smImgList, -1, shfi.hIcon)
Debug.Assert(rVal > -1, "Failed to add overlaid small icon")
Dim rVal2 As Integer
rVal2 = ImageList_ReplaceIcon(m_lgImgList, -1, shfi.hIcon)
Debug.Assert(rVal2 > -1, "Failed to add overlaid large icon")
Debug.Assert(rVal = rVal2, "Small & Large IconIndices are Different")
m_Mutex.ReleaseMutex()
'Debug.WriteLine(.DisplayName & ": iInx = " & rVal)
'.DebugDump()
DestroyIcon(shfi.hIcon)
If rVal < 0 OrElse rVal <> rVal2 Then
Throw New ApplicationException("Failed to add Icon for " & item.DisplayName)
End If
m_Table(Key) = rVal
End If
End With
'Debug.WriteLine("mCnt = " & mCnt & " bCnt = " & bCnt & " TableCount = " & m_Table.Count)
Return rVal
End Function
#End Region
#Region " GetDeskTopIconIndex"
' No longer used. Retained for information purposes
' <summary>
' public int GetDeskTopIconIndex()
' Returns the Icon Index for the Desktop. This is not
' available using the normal methods and the image
' itself is not placed into the ImageList unless this
' call is made.
' </summary>
' <returns>Returns the Icon Index for the Desktop
' </returns>
'Public Shared Function GetDeskTopIconIndex() As Integer
' Dim ppidl As IntPtr
' Dim hDum As Integer = 0
' Dim rVal As Integer
' rVal = SHGetSpecialFolderLocation(hDum, CSIDL.DESKTOP, ppidl)
' If rVal = 0 Then
' Dim dwFlags As Integer = SHGFI.SYSICONINDEX _
' Or SHGFI.PIDL
' Dim dwAttr As Integer = 0
' Dim shfi As SHFILEINFO = New SHFILEINFO()
' Dim resp As IntPtr
' resp = SHGetFileInfo(ppidl, _
' dwAttr, _
' shfi, _
' cbFileInfo, _
' dwFlags)
' Marshal.FreeCoTaskMem(ppidl) ' free the pointer
' If resp.Equals(IntPtr.Zero) Then
' Debug.Assert(Not resp.Equals(IntPtr.Zero), "Failed to get icon index")
' rVal = -1 'Failed to get IconIndex
' Else
' rVal = shfi.iIcon 'got it, return it
' End If
' Else 'failed to get DesktopLocation
' rVal = -1
' End If
' If rVal > -1 Then
' Return rVal
' Else
' Throw New ApplicationException("Failed to get Desktop Icon Index")
' Return -1
' End If
'End Function
#End Region
#Region " SetListViewImageList"
' <summary>
' Associates a SysImageList with a ListView control
' </summary>
' <param name="listView">ListView control to associate ImageList with</param>
' <param name="forLargeIcons">True=Set Large Icon List
' False=Set Small Icon List</param>
' <param name="forStateImages">Whether to add ImageList as StateImageList</param>
Public Shared Sub SetListViewImageList( _
ByVal listView As ListView, _
ByVal forLargeIcons As Boolean, _
ByVal forStateImages As Boolean)
Initializer()
Dim wParam As Integer = LVSIL_NORMAL
Dim HImageList As IntPtr = m_lgImgList
If Not forLargeIcons Then
wParam = LVSIL_SMALL
HImageList = m_smImgList
End If
If forStateImages Then
wParam = LVSIL_STATE
End If
SendMessage(listView.Handle, _
LVM_SETIMAGELIST, _
wParam, _
HImageList)
End Sub
#End Region
#Region " SetTreeViewImageList"
'/// <summary>
'/// Associates a SysImageList with a TreeView control
'/// </summary>
'/// <param name="treeView">TreeView control to associated ImageList with</param>
'/// <param name="forStateImages">Whether to add ImageList as StateImageList</param>
Public Shared Sub SetTreeViewImageList( _
ByVal treeView As TreeView, _
ByVal forStateImages As Boolean)
Initializer()
Dim wParam As Integer = LVSIL_NORMAL
If forStateImages Then
wParam = LVSIL_STATE
End If
Dim HR As Integer
HR = SendMessage(treeView.Handle, _
TVM_SETIMAGELIST, _
wParam, _
m_smImgList)
End Sub
#End Region
#End Region
End Class
|
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.
After 30+ years working in the IT field, mostly managing SysAdmins, I have retired. One of my hobbies returns me to programming, basically just to keep my hand in.