Icons werden Falsch in TreeView geladen

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

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von Matix Media.

    Icons werden Falsch in TreeView geladen

    Hallo liebe Menschen,

    ich habe mal weider ein Problem und zwar werden die Icons die ich mit hilfe einer sub in eine ImageLost Packe in der TreeView Falsch angezeigt oder sie werden von der Sub Falsch geladen.

    VB.NET-Quellcode

    1. Async Sub getDriver()
    2. tvFolders.Nodes.Clear()
    3. ilAutoIcoTreeView.Images.Clear()
    4. For Each Drive In System.Environment.GetLogicalDrives()
    5. Dim ico As Icon = Await GetFIcon(Drive.ToString)
    6. ilAutoIcoTreeView.Images.Add(ico.ToBitmap)
    7. With tvFolders.Nodes.Add(Drive.ToString)
    8. .ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    9. End With
    10. 'tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    11. Next


    VB.NET-Quellcode

    1. Async Function GetFIcon(ByVal sFilePath As String) As Task(Of System.Drawing.Icon)
    2. Dim hImgSmall As IntPtr 'The handle to the system image list.
    3. Dim hImgLarge As IntPtr 'The handle to the system image list.
    4. 'The file name to get the icon from.
    5. Dim shinfo As SHFILEINFO
    6. shinfo = New SHFILEINFO()
    7. shinfo.szDisplayName = New String(Chr(0), 260)
    8. shinfo.szTypeName = New String(Chr(0), 80)
    9. Try
    10. hImgSmall = SHGetFileInfo(sFilePath, 0, shinfo,
    11. Marshal.SizeOf(shinfo),
    12. SHGFI_ICON Or SHGFI_LARGEICON)
    13. Catch ex As Exception
    14. End Try
    15. 'Use this to get the small icon.
    16. 'Use this to get the large icon.
    17. 'hImgLarge = SHGetFileInfo(fName, 0,
    18. 'ref shinfo, (uint)Marshal.SizeOf(shinfo),
    19. 'SHGFI_ICON | SHGFI_LARGEICON);
    20. 'The icon is returned in the hIcon member of the
    21. 'shinfo struct.
    22. Dim myIcon As System.Drawing.Icon
    23. myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon)
    24. Return myIcon
    25. nIndex = nIndex + 1
    26. End Function
    Bilder
    • u12.PNG

      4,13 kB, 137×183, 1.453 mal angesehen
    Grüße, Matix
    Mal wieder viel zu wenig Informationen und null Eigeninitiative zu sehen...

    Matix Media schrieb:

    sie werden von der Sub Falsch geladen
    bedeutet was?

    Und was soll an den Methoden asynchron laufen? Die laufen ganz normal synchron, schließlich wird nirgends in Deiner GetFIcon-Methode ein Task gestartet oder auf einen Task gewartet. Also kannst Du das weglassen.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Ich dachte wenn ich die Function Async Aufrufe muss ich auch die Function selber auf Async stellen.

    Ich habe ein Bild in den Anhang gehängt wie es aussieht, aber es soll halt so nicht aussehen sondern mit den richtigen Icons.

    Ich weiß leider nicht welche Informationen ich dir genau liefern soll, aber wenn du mir sagst welche du brauchst stelle ich Sie dir gerne bereit.

    LG, Max
    Grüße, Matix

    Matix Media schrieb:

    Ich dachte wenn ich die Function Async Aufrufe muss ich auch die Function selber auf Async stellen.
    Nein, die Funktion wird async markiert, wenn Du darin etwas awaitest.

    Matix Media schrieb:

    With tvFolders.Nodes.Add(Drive.ToString)
    .ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    End With
    Ich denke hier wird das Problem liegen, je nachdem, was in der ImageList an Items liegt. Setze am besten mal einen Haltepunkt, debugge und prüfe die einzelnen Indizes sowie Einträge der ImageList nach jedem Schritt.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Danke für die schnelle Antwort! Eine Frage noch. Wie setzte ich einen Haltepunkt und wie überprüfe ich die einzelnen Indizes sowie Einträge?

    Edit:

    Aber seit ich die Function Async gemacht habe lagt das Program nicht mehr.
    Grüße, Matix

    Matix Media schrieb:

    Wie setzte ich einen Haltepunkt und wie überprüfe ich die einzelnen Indizes sowie Einträge?
    Du kannst links an der Seite pro Zeile jeweils einen Haltepunkt setzen, indem Du da in der Leiste einfach reinklickst. Dann kommt da so ein roter Punkt (Haltepunkt) und beim Debuggen hält das Programm da an und Du kannst mit dem Cursor über Deine Variablen hovern und die Werte betrachten.

    Matix Media schrieb:

    Aber seit ich die Function Async gemacht habe lagt das Program nicht mehr.
    Rein angesichts der Tatsache wie async await funktioniert, kann das eigentlich nicht sein, da dort wie gesagt nirgends ein Task gestartet wird, auf den Du wartest. Und eine async-markierte Methode, die kein await aufruft, läuft synchron durch. Da müsste die IDE auch meckern. Zumal der Code eh nicht so laufzeitintensiv sein sollte.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Wo denn? Ich sehe da in GetFIcon keinen await-Aufruf.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Stimmt da nicht, aber in der Datei Anzeige xD

    Edit:

    Im Post hatte ich Vergessen diesen Abschnitt zu Zeigen:

    VB.NET-Quellcode

    1. BeginInvoke(Sub() tvFolders.Nodes.Add("Desktop"))
    2. Dim ico_d As Icon = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.Desktop)
    3. BeginInvoke(Sub() ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap))
    4. BeginInvoke(Sub() tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1)
    5. BeginInvoke(Sub() tvFolders.Nodes.Add("Dokumente"))
    6. ico_d = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.MyDocuments)
    7. BeginInvoke(Sub() ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap))
    8. BeginInvoke(Sub() tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1)
    9. BeginInvoke(Sub() tvFolders.Nodes.Add("Musik"))
    10. ico_d = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.MyMusic)
    11. BeginInvoke(Sub() ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap))
    12. BeginInvoke(Sub() tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1)
    13. BeginInvoke(Sub() tvFolders.Nodes.Add("Bilder"))
    14. ico_d = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.MyPictures)
    15. BeginInvoke(Sub() ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap))
    16. BeginInvoke(Sub() tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1)
    17. BeginInvoke(Sub() tvFolders.Nodes.Add("Videos"))
    18. ico_d = Await GetFIcon(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos))
    19. BeginInvoke(Sub() ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap))
    20. BeginInvoke(Sub() tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1)
    21. BeginInvoke(Sub() tvFolders.Nodes.Add("Downloads"))
    22. ico_d = Await GetFIcon(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)) & "\Downloads")
    23. BeginInvoke(Sub() ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap))
    24. BeginInvoke(Sub() tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1)​
    Bilder
    • u10.PNG

      234,36 kB, 1.920×1.080, 132 mal angesehen
    Grüße, Matix
    Ja also läuft die Methode ganz normal synchron. async startet nicht automatisch einen neuen Thread. Es ist, wie gesagt, nur ein Modifier, der sagt, dass Du in dieser Methode etwas awaitest.
    codingame.com/playgrounds/4240…/structure-of-async-await

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Indem Du einen Task startest und zurückgibst (dann fällt der async-Modifier weg): return Task.Run(() => ...);. Dieses Task kann man dann awaiten. - Wird aber für die Laufzeit hier vollkommen überflüssig sein.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

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

    Matix Media schrieb:

    Geht das auch bei Functions?
    Ja, dafür kannst Du den generischen Task(Of T) bzw. Task<T> nutzen.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Matix Media schrieb:

    Im Post hatte ich Vergessen diesen Abschnitt zu Zeigen:

    Und hier liegt das Problem, das kannst du so nicht machen. Mit BeginInvoke sagst du der Form, dass sie diese Arbeit machen soll wenn sie Zeit hat, aber zwischendurch setzt du den Wert von ico_d immer wieder neu. Die Zeitlich abfolge passt hier nicht. Lass die Form die ganze Arbeit machen oder speicher die Icons separat.
    So mal ganz nebenbei, normalerweise, sofern man mit Async/Await richtig umgeht, benötigt man keine Invoke()/BeginInvoke() aufrufe mehr.
    Nach dem Await befindet man sich immer im aufrufenden Thread. Sofern man also Threads und Tasks nicht wild mischt(also man benutzt ausschließlich Tasks), ist der Code der nach Await ausgeführt wird IMMER im GUI Thread.
    @Matix Media Deine vielen BeginInvoke()-Zeilen kannst Du zu einem einzigen BeginInvoke() zusammenfassen, das ist dann auch viel schneller:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. BeginInvoke(Sub()
    2. tvFolders.Nodes.Add("Desktop")
    3. Dim ico_d As Icon = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.Desktop)
    4. ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap)
    5. tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    6. tvFolders.Nodes.Add("Dokumente")
    7. ico_d = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.MyDocuments)
    8. ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap)
    9. tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    10. tvFolders.Nodes.Add("Musik")
    11. ico_d = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.MyMusic)
    12. ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap)
    13. tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    14. tvFolders.Nodes.Add("Bilder")
    15. ico_d = Await GetFIcon(My.Computer.FileSystem.SpecialDirectories.MyPictures)
    16. ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap)
    17. tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    18. tvFolders.Nodes.Add("Videos")
    19. ico_d = Await GetFIcon(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos))
    20. ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap)
    21. tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    22. tvFolders.Nodes.Add("Downloads")
    23. ico_d = Await GetFIcon(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)) & "\Downloads")
    24. ilAutoIcoTreeView.Images.Add(ico_d.ToBitmap)
    25. tvFolders.Nodes(tvFolders.Nodes.Count - 1).ImageIndex = ilAutoIcoTreeView.Images.Count - 1
    26. End Sub)
    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!
    Vorschlag:
    Entferne das komplette Threading-Gerümpel: Async, Await, Thread(Of Krimskrams), Invoke, BeginInvoke - alles restlos abbauen.
    Dann bring die Anwendung erstmal dahin, dass sie richtig funktioniert, und dann (ja, das auch noch!) räum den Code erstmal auf.
    Danach gemeinsam sich um Threading kümmern - falls bei aufgeräumter Anwendung ühaupt noch nötig.
    Ond zwar um Threading richtig angewendet.

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