Index des Icon Dialogs

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Dksksm.

    Index des Icon Dialogs

    Hallo Leute,
    ich versuche gerade unter Windows 10 den Icon Dialog von Windows zu verwenden. Der Aufruf klapp auch, nur gibt mir der Dialog nicht immer den Richtigen Index des Icons zurück.
    Ist unter Windows 10 noch etwas zu beachten oder mache ich etwas falsch.

    Hie mal mein Code:

    VB.NET-Quellcode

    1. Declare Unicode Function PickIconDlg Lib "Shell32" Alias "PickIconDlg" (ByVal hwndOwner As IntPtr, ByVal lpstrFile As System.Text.StringBuilder, ByVal nMaxFile As Integer, ByRef lpdwIconIndex As Integer) As Integer
    2. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    3. Dim iconfile As String = Environment.GetFolderPath(Environment.SpecialFolder.System) + "\shell32.dll"
    4. Dim sb As New System.Text.StringBuilder(iconfile, 500)
    5. Dim iconindex As Integer
    6. Dim retval As Integer
    7. retval = PickIconDlg(Me.Handle, sb, sb.Capacity, iconindex)
    8. MessageBox.Show(iconindex.ToString)
    9. End Sub

    Toolmaster schrieb:

    nur gibt mir der Dialog nicht immer den Richtigen Index des Icons zurück.
    Nenn mal bitte ein konkretes Beispiel. Ich konnte keine Abweichungen bisher feststellen.

    btw: Wenn Funktionsname=Alias, dann kann man das Alias auch weglassen. Alias wurde gemacht, damit man die Funktion im eigenen Code (anders) nennen kann, wie man will, aber der Compiler trotzdem weiß, wie sie in der DLL heißt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @Toolmaster Ich kann Dein Problem nicht nachvollziehen.
    Mit Hilfe von PInvoke pinvoke.net/default.aspx/shell32.ExtractIcon
    hab ich mal dieses Beispiel implementiert. Mit dem Dialog hole ich den Index zum Icon, mit ExtractIconEx das Icon selbst, hier das große Icon.
    Dieses wird dann korrekt in einer PictureBox angezeigt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. <DllImport("shell32.dll", CharSet:=CharSet.Auto)> _
    4. Shared Function PickIconDlg(ByVal owner As IntPtr, ByVal fileName As System.Text.StringBuilder, ByVal maxFile As Integer, ByRef iconIndex As Integer) As Integer
    5. End Function
    6. <DllImport("shell32.dll", CharSet:=CharSet.Auto)> _
    7. Shared Function ExtractIconEx(ByVal szFileName As String, _
    8. ByVal nIconIndex As Integer, _
    9. ByVal phiconLarge() As IntPtr, _
    10. ByVal phiconSmall() As IntPtr, _
    11. ByVal nIcons As Integer) As Integer
    12. End Function
    13. <DllImport("user32.dll", EntryPoint:="DestroyIcon", SetLastError:=True)> _
    14. Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Integer
    15. End Function
    16. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    17. Dim iconfile As String = Environment.GetFolderPath(Environment.SpecialFolder.System) & "\shell32.dll"
    18. Dim sb As New System.Text.StringBuilder(iconfile, 500)
    19. Dim iconindex As Integer
    20. Dim retval As Integer
    21. retval = PickIconDlg(Me.Handle, sb, sb.Capacity, iconindex)
    22. If (retval = 1) Then
    23. Me.Label1.Text = iconindex.ToString
    24. Dim icon = ExtractIconFromExe(iconfile, iconindex, True)
    25. Me.PictureBox1.Image = icon.ToBitmap()
    26. End If
    27. End Sub
    28. Public Function ExtractIconFromExe(ByVal fileName As String, ByVal iconindex As Integer, ByVal large As Boolean) As Icon
    29. Dim readIconCount As Integer = 0
    30. Dim hDummy As IntPtr() = New IntPtr(0) {IntPtr.Zero}
    31. Dim hIconEx As IntPtr() = New IntPtr(0) {IntPtr.Zero}
    32. Try
    33. If (large) Then
    34. readIconCount = ExtractIconEx(fileName, iconindex, hIconEx, hDummy, 1)
    35. Else
    36. readIconCount = ExtractIconEx(fileName, iconindex, hDummy, hIconEx, 1)
    37. End If
    38. If (readIconCount > 0 AndAlso Not hIconEx(0).Equals(IntPtr.Zero)) Then
    39. ' GET FIRST EXTRACTED ICON
    40. Dim extractedIcon As Icon = CType(Icon.FromHandle(hIconEx(0)).Clone(), Drawing.Icon)
    41. Return extractedIcon
    42. Else ' NO ICONS READ
    43. Return Nothing
    44. End If
    45. Catch ex As Exception
    46. ' EXTRACT ICON ERROR
    47. ' BUBBLE UP
    48. Throw New ApplicationException("Could not extract icon", ex)
    49. Finally
    50. 'RELEASE RESOURCES
    51. For Each ptr As IntPtr In hIconEx
    52. If (Not ptr.Equals(IntPtr.Zero)) Then
    53. DestroyIcon(ptr)
    54. End If
    55. Next ptr
    56. For Each ptr As IntPtr In hDummy
    57. If Not (ptr.Equals(IntPtr.Zero)) Then
    58. DestroyIcon(ptr)
    59. End If
    60. Next ptr
    61. End Try
    62. End Function
    63. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ZB. dieses Icon hat laut Dialog den Index 89. Aber versuche jetzt dieses Icon einer Verknüpfung mit diesem Index zu zuweisen. Der richtige Inex währe 179.

    In der Picturebox wird es mir auch richtig angezeigt nur eben brauche ich den Index für verknüpfungen.


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Toolmaster“ ()

    Toolmaster schrieb:

    nur eben brauche ich den Index für verknüpfungen
    Ich hab mal die Bilder zu allen genannten Indizes geladen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. Dim iconfile As String = Environment.GetFolderPath(Environment.SpecialFolder.System) & "\shell32.dll"
    3. Dim iconindex = 83
    4. Dim icon = ExtractIconFromExe(iconfile, iconindex, True)
    5. Me.PictureBox1.Image = icon.ToBitmap()
    6. End Sub
    7. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    8. Dim iconfile As String = Environment.GetFolderPath(Environment.SpecialFolder.System) & "\shell32.dll"
    9. Dim iconindex = 179
    10. Dim icon = ExtractIconFromExe(iconfile, iconindex, True)
    11. Me.PictureBox2.Image = icon.ToBitmap()
    12. End Sub
    13. Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    14. Dim iconfile As String = Environment.GetFolderPath(Environment.SpecialFolder.System) & "\shell32.dll"
    15. Dim iconindex = 13
    16. Dim icon = ExtractIconFromExe(iconfile, iconindex, True)
    17. Me.PictureBox3.Image = icon.ToBitmap()
    18. End Sub

    Das von Dir gewünschte Bild ist nicht dabei. :/
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bin mit Win10 unterwegs. Klappt bei mir.
    Bilder
    • CorrectIcon.png

      4,93 kB, 522×249, 88 mal angesehen
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dksksm schrieb:

    offensichtlich auch Windows 7
    Jou, Icon 89 ist W7 anders als W10 und es ist das gewünschte.
    Die anderen drei sind identisch.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @VaporiZed So sieht es bei mir zuhause (Win10) auch aus. Das Programm, welches ich auf der Arbeit erstellt habe macht hier zuhause auf dem Windows 10 System genau das selbe, nur zeigt es hier halt wie @RodFromGermany auch schrieb, ein anderes Icon an. Nämlich das was bei @VaporiZed auch auf dem Bild zu sehen ist.
    Wir @RodFromGermany auch schreibt, ist das Icon mit dem Index 179 auf beiden Systemen identisch. Das Icon mit Index 89 weicht optisch ab.
    Dennoch kann ich ganz sauber nach dem Zufügen des COM Verweises für "Windows Script Host Object Model" und dem Import der IWshRuntimeLibrary z.B. völlig korrekte Desktop Verknüpfungen erzeugen.

    Somit weiß ich immer noch nicht, was @Toolmaster nun eigentlich für ein Problem hat.