2016-02-09 2 views
1

Как показать значок сетевой папки в списке? тот, у которого есть зеленая трубка под папкой, у меня есть код, который отлично работает с файлами и папками, но при посещении другого компьютера через сеть я не вижу сетевых папок, которые похожи на этот.Показать значок папки сети в списке просмотра VB.NET

enter image description here

что я должен добавить?

вот мой код: это, как отобразить значок в ListView

Dim fPath As String = Form2.TextBox1.Text 
Dim di = New DirectoryInfo(fPath) 

    ' store imagelist index for known/found file types 
    Dim exts As New Dictionary(Of String, Int32) 

    If di.Exists = True Then 
     Dim img As Image 
     Dim lvi As ListViewItem 
     For Each d In di.EnumerateDirectories("*.*", SearchOption.TopDirectoryOnly) 
      lvi = New ListViewItem(d.Name) 
      lvi.SubItems.Add("") 
      lvi.SubItems.Add(d.CreationTime.Date) 

      ListView1.Items.Add(lvi) 

      img = NativeMethods.GetShellIcon(d.FullName) 
      ImageList1.Images.Add(img) 
      lvi.ImageIndex = ImageList1.Images.Count - 1 
     Next 

это, как я получаю иконки из Shell32.

Partial Public Class NativeMethods 
Private Const MAX_PATH As Integer = 256 
Private Const NAMESIZE As Integer = 80 
Private Const SHGFI_ICON As Int32 = &H100 
<StructLayout(LayoutKind.Sequential)> 
    Private Structure SHFILEINFO 
     Public hIcon As IntPtr 
     Public iIcon As Integer 
     Public dwAttributes As Integer 
     <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> 
     Public szDisplayName As String 
     <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=NAMESIZE)> 
     Public szTypeName As String 
    End Structure 
    <DllImport("Shell32.dll")> 
    Private Shared Function SHGetFileInfo(ByVal pszPath As String, 
             ByVal dwFileAttributes As Integer, 
             ByRef psfi As SHFILEINFO, 
             ByVal cbFileInfo As Integer, 
             ByVal uFlags As Integer) As IntPtr 
    End Function 
    <DllImport("user32.dll", SetLastError:=True)> 
    Private Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Boolean 
    End Function 
    Public Shared Function GetShellIcon(ByVal path As String) As Bitmap 
     Dim shfi As SHFILEINFO = New SHFILEINFO() 
     Dim ret As IntPtr = SHGetFileInfo(path, 0, shfi, Marshal.SizeOf(shfi), SHGFI_ICON) 
     If ret <> IntPtr.Zero Then 
      Dim bmp As Bitmap = System.Drawing.Icon.FromHandle(shfi.hIcon).ToBitmap 
      DestroyIcon(shfi.hIcon) 
      Return bmp 
     Else 
      Return Nothing 
     End If 
    End Function 
End Class 

ответ

2

Вы можете получить эту иконку из Shell32 как маленького или большого изображения. Как отмечает Коди Грей в комментарии, в «imageres.dll» больше значков (200+). Для того, чтобы получить их по индексу, добавьте этот метод к вашему NativeMethods класс:

<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 

Первый аргумент является индекс значка, чтобы получить, то второй указывает, хотите ли вы большую или маленькую версию, последний необязательный флаг для извлечения из imageres.dll по сравнению с shell32.dll. Обратите внимание, что метод может привести к ошибке Nothing, если что-то пойдет не так.

Затем измените петлю папки, чтобы получить изображение трубы папки (# 275) от shell32.dll при обнаружении сетевого диска:

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 

Это использует вспомогательную функцию, чтобы определить, является ли сетевой папкой или нет , Если это так, он извлекает из библиотеки DLL определенную папку, которая является # 275. Результат:

enter image description here

То же папка изображения также в imageres.dll как # 137 (и # 68 и # 69 аналогичны с мировыми накладками). Для того, чтобы получить от этого вместо:

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

Если вы хотите, чтобы избежать Magic Numbers в коде, используйте константы или перечисление значков, используемых. Вы могли определить их все в NativeMethods классе, но это 500 пунктов, и вы можете также не вспомнить, что они означают 6 месяцев спустя:

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

Это будет отображать значки, хранящиеся в shell32.dll и их индекс к Listview набор для LargeIcon View, так что вы можете просматривать их:

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 

enter image description here

+1

Действительно, значки 'moricons.dll' очень старые, DLL не обновлялась со времени 16-разрядных Windows дней. Но вы можете найти множество новых значков, используемых современными версиями оболочки в 'imageres.dll'. –

+0

Да, я знал, что морионы были очень (очень) старыми, мне было интересно, есть ли более новая версия.Я не знал о 'imageres.dll', спасибо! – Plutonix

+1

Что касается кода для первой функции, я не уверен, почему вы беспокоитесь об исключениях, но если бы функции «FromHandle» или «ToBitmap» были выброшены, вы пропустили бы дескриптор значка. Вам нужно будет вызвать 'DestroyIcon' в блоке' finally'. –

Смежные вопросы