Format der in den Dateien enthaltenen Datei-Icons

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

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Dideldum.

    Format der in den Dateien enthaltenen Datei-Icons

    Hi Ihr,

    ich hatte echt Probleme, die ich nicht nachvollziehen kann.

    Hintergrund:
    Ich habe eine DatagridView in welcher wie schon beschrieben, die Inhalte der in dem Treeview ausgewählten Ordner angezeigt werden.
    In der ersten Spalte dieser DGV zeige ich das Datei-Symbol an, welches ich aus der Dateiinfo auslese.
    Leider dauert eben dieses Auslesen und extrahieren der Datei-Symbole ein halbe Ewigkeit.
    Bei 1000 enthaltenen Dateien dauert es 30Sekunden, die DGV zu befüllen (ohne Symbole gerade mal 5 Sekunden).

    Nun dachte ich, ich mache es ganz schlau und lese die Symbole beim ersten Einlesen der Objektliste gaaaaaanz langsam in eine Liste "iconDictionary" mit Inhalt "Dateipfad,Bitmap" ein.
    Wird der Ordner aber erneut geöffnet, werden die Datei-Symbole dann retzfatz aus der Liste gelesen, was extrem schneller abläuft (bei 1000 Einträgen 5 sek.).

    Das habe ich dann auch so zusammengeschwartet - und dann aber beim Einlesen der Liste laufend GDI+-Fehler bekommen.
    Diesen Fehler habe ich (hoffentlich) erledigt, indem ich das Bitmap aus der Liste "clone" und den Clone in meine DGV einbinde.

    VB.NET-Quellcode

    1. Try
    2. dgv_Files.RowTemplate.Height = DesignArray(My.Settings.Oberfläche_Design * 10 + 5).Schriftart.Height + 6
    3. Dim DateiListe As New List(Of String)
    4. FindAllFiles(OrdnerPfad, "*.*", DateiListe)
    5. ' Icons in IconDictionary einlesen, falls nicht vorhanden
    6. For Each datei As String In DateiListe
    7. If My.Settings.Listen_Objektliste_AnzeigeSymbole AndAlso Not iconDictionary.ContainsKey(datei) Then
    8. Dim icon As Bitmap = ExtractIconFromFile(datei)
    9. If icon IsNot Nothing Then
    10. iconDictionary(datei) = icon
    11. End If
    12. End If
    13. Next
    14. Dim LeerIcon = New Bitmap(CInt(dgv_Files.Font.Size + 10), CInt(dgv_Files.Font.Size + 10))
    15. Dim resizedIcon As Bitmap = LeerIcon
    16. For Each datei As String In DateiListe
    17. resizedIcon = LeerIcon
    18. dArt = IsRegisteredExtension(datei)
    19. If IO.Path.GetFileName(datei).ToLower <> ObjektEinstellungenXML.ToLower Then
    20. If datei.Length < 261 Then
    21. Dim fileDetail As FileInfo = My.Computer.FileSystem.GetFileInfo(datei)
    22. If My.Settings.Listen_Objektliste_AnzeigeSymbole Then
    23. Dim icon As Bitmap = Nothing
    24. If dArt > 8 Then
    25. icon = My.Resources.Schlüssel.ToBitmap()
    26. ElseIf iconDictionary.ContainsKey(datei) Then
    27. Dim iconFromDict As Bitmap = iconDictionary(datei)
    28. If iconFromDict IsNot Nothing Then
    29. icon = New Bitmap(iconFromDict.Width, iconFromDict.Height)
    30. Using g As Graphics = Graphics.FromImage(icon)
    31. g.DrawImage(iconFromDict, New Rectangle(0, 0, icon.Width, icon.Height))
    32. End Using
    33. Else
    34. icon = LeerIcon
    35. End If
    36. Else
    37. icon = LeerIcon
    38. End If
    39. If icon IsNot Nothing Then
    40. resizedIcon = New Bitmap(icon, CInt(dgv_Files.Font.Size + 10), CInt(dgv_Files.Font.Size + 10))
    41. icon.Dispose()
    42. End If
    43. End If
    44. dgv_Files.Rows.Add(resizedIcon,
    45. IO.Path.GetFileName(datei),
    46. DateiEndungTypBezeichnung(LCase(IO.Path.GetExtension(datei))),
    47. fileDetail.Length,
    48. fileDetail.LastWriteTime,
    49. fileDetail.LastAccessTime,
    50. fileDetail.CreationTime)
    51. Else
    52. Dim form_exclamation As New ICE_Eingabe
    53. form_exclamation.Initialisiere(False, My.Resources.ICE_Common_ICEFehler, String.Format(My.Resources.ICE_Common_Fehler_Pfadlänge, datei), MessageBoxButtons.OK, 4,, False)
    54. End If
    55. End If
    56. Next
    57. Catch ex As System.Exception
    58. Me.Cursor = Cursors.Default
    59. Dim form_exclamation As New ICE_Eingabe
    60. form_exclamation.Initialisiere(False, My.Resources.ICE_Common_ICEFehler, String.Format(My.Resources.ICE_Common_FehlerInModul, "create_DGV_Files", ex.Message), MessageBoxButtons.OK, 4,, False)
    61. End Try


    Gibt es keine elegantere und vor allem schnellere Lösung, um

    VB.NET-Quellcode

    1. icon = iconDictionary(datei)

    direkt zu erzeugen, als den Umweg über den g-Clone?
    Bei dieser direkten Zuweisung ist bei wiederholtem Aufruf (ordner und Objektliste neu einlesen) immer der "Allgemeine GDI+"-Fehler aufgetreten.

    Mit dem Clonen

    VB.NET-Quellcode

    1. Dim iconFromDict As Bitmap = iconDictionary(datei)
    2. If iconFromDict IsNot Nothing Then
    3. icon = New Bitmap(iconFromDict.Width, iconFromDict.Height)
    4. Using g As Graphics = Graphics.FromImage(icon)
    5. g.DrawImage(iconFromDict, New Rectangle(0, 0, icon.Width, icon.Height))
    6. End Using
    7. Else
    8. icon = LeerIcon
    9. End If

    scheint es stabil zu laufen.

    Aber hübsch und nachvollziehbar ist was anderes.
    Ich denke, da ist irgendwas am Format der Bitmap aus der Liste in iconDictionary faul.

    Hat mir da vielleicht jemand einen Tip, warum die einfache Zuweisung mit der Zeit Amok läuft und ob ich das auch schneller und schöner zurechtschnipseln kann?

    Beste Grüsse :)
    @Dideldum Hmm, TreeView mit Ordner und DGV mit Dateien und Icons usw. Klingt so als würdest sowas wie den Explorer nachprogrammieren wollen. Wenn ja, dann schau Dir mal das COM Interface IExplorerBrowser an -> learn.microsoft.com/en-us/wind…idl_core-iexplorerbrowser
    Mfg -Franky-
    Hi @-Franky-,

    danke Dir für den Tip. :)

    ja, da hast recht. ;)
    Mein Proggi ist wie der Win-Explorer aufgebaut, nur, dass dieses einen Text-, einen RTF-, einen Pic-Editor und dazu einen Windows-, einen PDF-, einen Html-Viewer und einen Shortcut-Viewer beinhaltet und zusätzlich über einen integrierten Browser verfügt.
    Diese werden je nach ausgewähltem Objekt in der rechten Seite eingeblendet.
    Das muss ich mir mal ansehen, was hinter dem IExplorerbrowser steckt und ob sich dieser ggf. in mein Projekt einbinden lassen würde.

    Schönen Rest-Abend wünsche ^^
    Bilder
    • programm_text-editor.jpg

      429,45 kB, 1.920×1.200, 82 mal angesehen
    Hi. Handelt es sich um reale Ordner/Dateien auf der HD? Wenn ich mir Dein Bild anschaue, könnte ich mir für das TreeView auch das COM-Interface INameSpaceTreeControl vorstellen da Du hier nur einen bestimmten Pfad mit Ordnern darstellst und nicht das komplette linke Fenster des Explorer. Bei der Ansicht der Dateien, würde ich dann IExplorerBrowser::FillFromObject <- IShellItem (Ordner) vom INameSpaceTreeControl nehmen. Der zeigt dann nur das rechte Fenster des Explorer mit den Dateien, inkl. Icons und Spalten an. Selbst welche Spalten angezeigt werden sollen kannst Du vorgeben.

    Es ist nur eine Idee wie man es auch machen könnte und du siehst ja selbst wie schnell der Explorer Ordner und Dateien darstellt.

    Ansonsten gibt es mehrere Möglichkeiten an das Icon einer Datei zu kommen. Am schnellsten dürfte folgendes sein. Du greifst auf die SystemImageList zu. Die initialisierst einmalig bei Start deiner App. Dann musst nur noch den Index zum Icon aus der SystemImageList von der Datei ermitteln und das Icon aus der SystemImageList holen. Angenommen ein DOCX hat den Index 100, dann merkst Dir den Index für DOCX. Bei der nächsten Datei, die auch wieder ein DOCX ist, weist Du schon das die Datei den Index 100 hat und musst nicht nochmal den Index von der Datei ermitteln.
    Mfg -Franky-

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

    Danke Dir @-Franky-, :)

    das hört sich ja super interessant an, das mit dem "FillFromObject <- IShellItem (Ordner)" und dem "INameSpaceTreeControl ". ^^
    In meinem Büchern finde ich leider überhaupt nichts dazu.
    Gibt es vielleicht irgendwo einen Anwendungsbeispiel-Code und/oder Anleitungen zur Verwendung (am liebsten in deutscher Sprache) für diese Interfaces?

    Grob umrissen ist mein Proggi so aufgebaut, dass der User einen beliebigen Pfad als Stammverzeichnis definieren kann.
    Dann kann er z.B. in meinem Proggi jedem Objekt in diesem Stammverzeichnis Stichworte vergeben, komfortabel nach diesen suchen lassen und sich eine Liste mit den gefundenen Objekten anzeigen lassen.
    Auch kann der User z.B. zu jedem Objekt ein Alarm-Datum/Uhrzeit definieren, an dem dann das Objekt angezeigt wird.
    Weiter kann der Benutzer bestimmte Dateitypen direkt im Programm bearbeiten bzw. anzeigen lassen.
    Dazu kann das Programm jedes in die Zwischenablage kopierte Objekt als Datei in einem automatisch zuweisbaren Ordner im Archiv speichern lassen und die Objektinhalte auch an passende Anwendungen senden lassen.
    Auch kann das Programm Objekte als Mail-Anlage oder Email-Body (TXT und RTF) als Mail versenden.
    Usw.

    Mit dem Programm ist es einfacher, z.B. in seinen "Eigene Dateien" Ordnung zu halten und Objekte zu finden.
    Oder Textblöcke und Bilder an Word- oder Bild-Editoren zu übergeben.

    Ich brauche folgende Möglichkeiten in dem Treeview:
    - Freie Stammordner-Auswahl
    - Umbenennen von Ordnern
    - Hinzufügen von Ordnern

    In der Datagridview:
    - Umbenennen von Dateien
    - Hinzufügen von Dateien
    - bei bestimmten Dateiendungen die Anzeige eines definierten Icons, das nicht in der Datei enthalten ist (siehe Bild - "Schlüssel"-Icons)
    - Sortiermöglichkeit nach eigenen Kriterien (z.B. Natürliche Sortierung der Spalte Objektname" - wie im Windows-Explorer)

    Dies mit FilesystemWatcher und Auto-Aktualisierung der Treeview und der Datagridview, da mein Proggi netzwerkfähig ist.

    Wäre dies alles mit den von Dir vorgeschlagenen Interfaces möglich?

    Beste Grüsse
    Bilder
    • Programmfenster.jpg

      393,84 kB, 1.920×1.200, 58 mal angesehen
    Hi. In Deinen Büchern wirst Du kaum Beispiele zu den genannten COM Interfaces finden. Eventuell noch wie man in .NET COM Interfaces instanziert. Ansonsten ist die erste Anlaufstelle die MS-DOKU und die Header-Dateien des Windows SDK. Ja, die MS-Doku kann man auch auf deutsch lesen, würde ich aber nicht empfehlen da einige Begriffe total falsch übersetzt sind. Ich bin mir aber sehr sicher das Beispiele im Internet zu finden sind. Vielleicht nicht in VB.NET, aber in anderen Sprachen wie C++, C# usw.
    Mfg -Franky-
    hi @-Franky-

    danke Dir :)

    Ja, ich habe ein paar Beispiele für den Einsatz der Interfaces gefunden - aber wie Du schreibst, leider in C und nicht in VB.net.
    Mein letzer Versuch, ein C-Script nach VB.net zu übersetzen endete allerdings in einem Desaster.
    Von C habe ich absolut keine Ahnung. ;(

    Weisst Du, ob sich meine o.g. Anforderungen generell mit dem Einsatz der Interfaces realisieren lassen?
    Nicht, dass ich mich da reinknie und dann an den Bedingungen scheitere.

    Dideldum schrieb:

    Weisst Du, ob sich meine o.g. Anforderungen generell mit dem Einsatz der Interfaces realisieren lassen?
    Zumindest mit dem IExplorerBrowser und FillFromObject bekommst Du das rechte Fenster des Explorer in Deinem Programm. Ob Du das dann so in Deinem Programm gebrauchen kannst oder sinnvoll ist, müsstest halt testen.
    Mfg -Franky-
    @-Franky-
    Danke Dir :)

    In der Objektliste fürchte ich, dass ich mit dem Interface das Standard-Datei-Symbol der Dateien nicht endungsabhängig durch eigene Symbole ersetzen kann.
    Da finde ich im Web auch nichts darüber.
    Wie ich das so recherchiert habe, ist dieses Interface eine 1:1 Kopie des rechten Explorer-Controls. Und dies mit sehr beschränkten Möglichkeiten in dessen Darstellung einzugreifen.
    Gegen die automatische Spalten-Zuordnung je nach Dateityp hätte ich auch nichts einzuwenden. ^^

    Wäre schön gewesen - die Sortierung würde damit ja schon passen, aber ich brauche halt für die im ICE verschlüsselte Objekte das Schlüsselsymbol.
    Und das, ohne in den betreffenden Dateien das originale Symbol zu ändern.
    Also fürchte ich, dass das eher nichts wird, mit dem Interface. :S

    Dideldum schrieb:

    Wie ich das so recherchiert habe, ist dieses Interface eine 1:1 Kopie des rechten Explorer-Controls.

    Das Interface IExplorerBrowser ist ein kompletter Explorer-Control. Also inkl. TreeView im linken Fenster und ListView im rechten Fenster und verhält sich auch wie der Explorer inkl. der bekannten Kontextmenüs. Man übergibt nur einen Pfad, und der Rest wird vom Control erledigt. In bestimmten Grenzen lässt sich das Control auch konfigurieren. Was man auf den ersten Blick nicht sehen kann ist, das man darüber auf weitere COM Interfaces zugreifen kann die einem weitere Möglichkeiten bieten. Was alles möglich ist, hab ich allerdings auch noch nicht ausprobiert.
    Mfg -Franky-
    Hi @-Franky-

    habe jetzt das ganze Weekend recherchiert und es scheint wohl tatsächlich so, dass bei dem IExplorerBrowser die Kontextmenus in der Treeview und Listview nicht änderbar sind und rein vom Windows-System bzw. dessen Registry-Einträgen erzeugt werden.
    Ebenso verhält es sich mit den Programm-Symbolen.

    Das sind für mein Projekt zwei KO-Kriterien. Denn ich brauche selbst definierte Kontextmenus und ebensolche Programm-Icons.

    Na immerhin dauert dank meines Icon-Caches nun das Einlesen und Anzeigen einer 2000Dateien grossen Dateiliste nur noch 4 Sekunden.
    Ich denke, da kann man auch damit leben.

    Schade, dass es mit dem IExplorerBrowser nicht klappt - die Idee war supi - nur in der Adaption happert es.

    Beste Grüsse
    Hi @Dideldum

    Dideldum schrieb:

    habe jetzt das ganze Weekend recherchiert und es scheint wohl tatsächlich so, dass bei dem IExplorerBrowser die Kontextmenus in der Treeview und Listview nicht änderbar sind... Ebenso verhält es sich mit den Programm-Symbolen.

    Ich würde das nicht zu 100% ausschließen wollen, das es doch möglich ist. Sofern man an die hWnd des TreeView oder ListView kommt, und das sollte möglich sein, kann man diese Subclassen. Hier wäre es durchaus möglich die Items zu Ownerdrawen oder an das Kontextmenü, bzw dessen hMenu, zu kommen was dazu genutzt werden kann um das Standardkontextmenü zu manipulieren.

    Für Dein Projekt wären diese Interfaces dann doch eher ungeeignet bzw müssten mit viel Code so umgebogen werden, das das für Dein Projekt passt. Der Aufwand lohnt dann nicht. Vllt. werde ich mal zwei Testprojekte hochladen der zumindest ein paar einfache Möglichkeiten zeigt wie diese Interfaces genutzt werden könnten.
    Mfg -Franky-