Show network folder icon in listview VB.NET

自作多情 提交于 2019-12-02 04:09:28

You can get that icon from Shell32 as a small or large image. As Cody Gray points out in a comment, there are more icons (200+) in "imageres.dll". To get these by index, add this method to your NativeMethods class:

<DllImport("shell32.dll", CharSet:=CharSet.Auto)>
Private Shared Function ExtractIconEx(szFileName As String,
                            nIconIndex As Integer,
                            ByRef phiconLarge As IntPtr,
                            ByRef phiconSmall As IntPtr,
                            nIcons As UInteger) As UInteger
End Function

Private Shared ImgResFile As String = "imageres.dll"
Private Shared ShellFile As String = "shell32.dll"

Friend Shared Function GetShellIconByIndex(ndx As Int32,
                         largeIcon As Boolean = False,
                         Optional FromShell As Boolean = True) As Bitmap
    Dim largeIco As IntPtr
    Dim smallIco As IntPtr
    Dim thisIco As IntPtr
    Dim ico As Icon
    Dim bmp As Bitmap = Nothing

    Dim targtFile = If(FromShell, ShellFile, ImgResFile)
    ExtractIconEx(targtFile, ndx, largeIco, smallIco, 1)

    Try
        If largeIcon Then
            ico = Icon.FromHandle(largeIco)
            thisIco = largeIco
        Else
            ico = Icon.FromHandle(smallIco)
            thisIco = smallIco
        End If
        bmp = ico.ToBitmap()
    Catch ex As Exception           ' swallow exception to return nothing
        ' really stupid index values can throw ArgumentException
        ' when the result is IntPtr.Zero
        ' Rather than test it, catch it an any other(s)
    Finally
        DestroyIcon(thisIco)
    End Try

    Return bmp
End Function

The first argument is the index of the icon to get, the second indicates whether you want the large or small version, the last is an optional flag to fetch from imageres.dll versus shell32.dll. Note that the method can result Nothing if something goes wrong.

Then modify your folders loop to get the pipe-folder image (#275) from shell32.dll when you detect a network drive:

For Each d In di.EnumerateDirectories("*.*", SearchOption.TopDirectoryOnly)
    ...
    If IsNetworkFolder(d) Then
        ' get #275 as small image from Shell 
        img = NativeMethods.GetShellIconByIndex(275, False)
        If img Is Nothing Then
            ' ToDo: perhaps load a default image from Resources?
        End If
    Else
        img = NativeMethods.GetShellIcon(d.FullName)
        If img Is Nothing Then
            img = IconFromFile(d.FullName)
        End If
    End If
    '... add code 
Next

Private Function IsNetworkFolder(di As DirectoryInfo) As Boolean
    Dim drv As New DriveInfo(di.Root.Name)
    Return (drv.DriveType = DriveType.Network)
End Function

This uses a helper function to determine whether the folder is networked or not. If it is, it fetches that specific folder icon, which is #275, from the DLL. Result:

That same folder image is also in imageres.dll as #137 (and #68 and #69 are similar with world overlays). To get from that instead:

'  137 is the index, false for large icon, false to use imageres instead: 
img = NativeMethods.GetShellIconByIndex(137, False, False)

If you want to avoid Magic Numbers in your code, use constants or an enum of the icons used. You could define them all in the NativeMethods class, but that is 500 items and you may well not recall what they mean 6 months later:

Private Enum ShellIcons
    NetworkFolder1 = 275
    NetworkFolder2 = 103
    SharedFolder = 158
    AddNetworkFolder = 278
End Enum
...
img = NativeMethods.GetShellIconByIndex(ShellIcons.NetworkFolder1, False)

This will display the icons stored in shell32.dll and their index to a Listview set to LargeIcon View so you can browse them:

Dim ndx As Int32 = 0
Dim img As Image = Nothing
Dim lvi As ListViewItem

Do
    ' change second Bool to False to get the ones in imageres.dll
    img = NativeMethods.GetShellIconByIndex(ndx, True, True)

    If img IsNot Nothing Then
        lvi = New ListViewItem(ndx.ToString)

        ImageList1.Images.Add(img)
        lvi.ImageIndex = ImageList1.Images.Count - 1
        myLV.Items.Add(lvi)
        ndx += 1
    Else
        Exit Do
    End If
Loop Until img Is Nothing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!