ListIconGadget Sortieren

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

ListIconGadget Sortieren

Beitrag von silbersurfer »

Hallo Leute, ich bin es mal wieder,
Ich habe hier im Forum viele sort Varianten für ListGadgets gefunden, via Api.

meine Frage dazu ist, wie kann ich Dateien von dem Sortieren ausschließen (sollen nicht Sortiert werden)
Leider sehe ich den Wald vor lauter Bäumen nicht mehr

hat da jemand eine Idee ! (wenn möglich on Fly im Gadget über Struct-list habe ich schon was selber gemacht)

Code: Alles auswählen

Procedure SortListView(hWndListView.l, SortKey.l, SortType.b, SortOrder.b)
; ' -----------------------------------------------------
; ' Öffentlich aufzurufende Prozedur SortListView, die
; ' für die individuelle Sortierung einer ListView-Spalte
; ' sorgt.
; ' -----------------------------------------------------
; ' hWndListView: Fensterhandle des ListView-Steuerelements
; ' SortKey:      Spalte (nullbasiert), die sortiert werden
; '               soll (= Spaltennummer - 1).
; ' SortType:     stString, um Strings zu sortieren (Standardwert)
; '               stDate, um Datumsangaben zu sortieren
; '               stNumeric, um Zahlen zu sortieren
; ' SortOrder:    lvwAscending für aufsteigende Sortierung (Std.)
; '               lvwDescending für absteigende Sortierung
; ' -----------------------------------------------------
   
   Protected udtLVWSORT.LVWSORT
   Protected sDateFormat.s, sTemp.s, GadId.i
   
   If SortType=#SortDate
      GadId=GetDlgCtrlID_(hWndListView)
      sDateFormat=GetDateFormat(GetGadgetItemText(GadId, 0, SortKey))
      
      If sDateFormat=""
         SortType=#SortString
      Else
         sTemp=GetDateFormat(GetGadgetItemText(GadId, CountGadgetItems(GadId)-1, SortKey))
         If sTemp=""
            SortType=#SortString
         Else
            If sTemp<>sDateFormat
               If Left(sTemp, 3)="%mm" ; new format starts with %mm (.dd.yyyy) - if this US format is detected it has higher prio
                  sDateFormat=sTemp
               EndIf
            EndIf
            sTemp=GetDateFormat(GetGadgetItemText(GadId, CountGadgetItems(GadId)/2, SortKey))
            If sTemp=""
               SortType=#SortString
            Else
               If sTemp<>sDateFormat
                  If Left(sTemp, 3)="%mm" ; new format starts with %mm (.dd.yyyy) - if this US format is detected it has higher prio
                     sDateFormat=sTemp
                  EndIf
               EndIf
            EndIf   
         EndIf         
      EndIf
      udtLVWSORT\DateFormat=sDateFormat
      Debug "Final DateFormat >"+sDateFormat+"<"
   EndIf
   
   ; Übergebene Informationen in einer LVWSORT-Struktur zusammenfassen:
   udtLVWSORT\hWndListView=hWndListView
   udtLVWSORT\SortKey=SortKey
   udtLVWSORT\SortOrder=SortOrder
   udtLVWSORT\SortType=SortType   
   
   ; Eigene Sortierfunktionalität in der Funktion CompareFunc verwenden: Die Informationen der
   ; LVWSORT-Struktur wird mithilfe eines Zeigers auf die Variable udtLVWSORT beigegeben:
   SendMessage_(hWndListView, #LVM_SORTITEMSEX, @udtLVWSORT, @CompareFunc())
EndProcedure   

Code: Alles auswählen

Procedure.l CompareFunc(lParam1.l, lParam2.l, lParamSort.l)
   ; ' -----------------------------------------------------
   ; ' Vergleichsfunktion CompareFunc
   ; ' -----------------------------------------------------
   ; ' Verglichen werden jeweils zwei Elemente der zu
   ; ' sortierenden Spalte des ListView-Steuerelements,
   ; ' die über lParam1 und lParam2 angegeben werden.
   ; ' Hierbei wird über den Rückgabewert der Funktion
   ; ' bestimmt, welches der beiden Elemente als größer
   ; ' gelten soll (hier für Aufwärtssortierung):
   ; ' * Element 1 < Element 2: Rückgabewert < 0
   ; ' * Element 1 = Element 2: Rückgabewert = 0
   ; ' * Element 1 > Element 2: Rückgabewert > 0
   ; ' -----------------------------------------------------
   Protected *ListViewSort.LVWSORT
   Protected sEntry1.s
   Protected sEntry2.s
   Protected vCompare1.s ; As Variant
   Protected vCompare2.s ; As Variant
   
   ; In lParamSort von SortListView als Long-Pointer übergebene LVWSORT-Struktur abholen, um auf deren
   ; Werte zugreifen zu können:
   
   *ListViewSort=lParamSort
   
   ; Die Werte der zu vergleichenden Elemente werden mithilfe der privaten Funktion LvwGetText aus
   ; den Angaben lParam1 und lParam2 ermittelt:
   sEntry1 = LvwGetText(*ListViewSort, lParam1)
   sEntry2 = LvwGetText(*ListViewSort, lParam2)

   ; Sind die Elemente gleich, kann die Funktion sofort mit dem aktuellen Rückgabewert 0
   ; verlassen werden:
   If sEntry1 = sEntry2
      ProcedureReturn 0
   EndIf
   
   ; Für die Sortierung wird unterschieden zwischen Zahlen, Fließkommazahlen und allgemeinen Strings. Hierfür
   ; steht jeweils eine separate, private Vergleichsfunktion zur Verfügung.
   
   Select *ListViewSort\SortType
      Case #SortNumeric ; ' Spalteninhalte sind Zahlen
         ProcedureReturn CompareNumbers(sEntry1, sEntry2, *ListViewSort\SortOrder)
      Case #SortFloat ; ' Spalteninhalte sind Zahlen mit Nachkommastellen
         ProcedureReturn CompareFloat(sEntry1, sEntry2, *ListViewSort\SortOrder)
      Case #SortString;  ' Spalteninhalte sind Strings
         ProcedureReturn CompareStrings(@sEntry1, @sEntry2, *ListViewSort\SortOrder)
      Case #SortDate
         ProcedureReturn CompareDate(sEntry1, sEntry2, *ListViewSort\SortOrder, *ListViewSort\DateFormat)
   EndSelect
EndProcedure
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
DarkSoul
Beiträge: 689
Registriert: 19.10.2006 12:51

Re: ListIconGadget Sortieren

Beitrag von DarkSoul »

Ich bin Linuxuser und kann weder testen, noch kenne ich mich großartig mit WinAPI aus. Ich gehe davon aus, dass das grundsätzlich so funktioniert und CompareFunc() dein Problem ist bzw. das Sortierverhalten falsch ist. :) .

CompareFunc() ist eben nur ein Vergleich zwischen zwei Werten, damit der Sortieralgorithmus weiß, was davon größer oder kleiner ist. An den eigentlichen Sortieralgorithmus kommst du wohl nicht dran (musst du auch nicht). Die CompareFunc() ist der Teil, der die Sortierung wesentlich beeinflusst.

Die einzige Möglichkeit besteht wohl darin, einzelne Werte nach ganz oben oder ganz unten zu befördern, bestünde darin, diese als "kleiner/größer als alles andere" zu behandeln.

Da fallen mir mehrere Möglichkeiten an:

1. Übergeordnete Gruppen.

Dann sähe deine CompareFunc() etwa so aus (Pseudocode! Nicht getestet. Geht um das Prinzip^^):

Code: Alles auswählen

  If (Element1.group < Element2.group) return -1 ;übergeordnetes Kriterium / Gruppe
  if (Element1.group > Element2.group) return 1 
  if (Element1.name < Element2.name) return -1 ;untergeordnetes Kriterium
  if (Element1.name > Element2.name) return 1
  return 0 ;bleibt ja nur noch der Fall, dass die Elemente nach beiden Kriterien identisch sind. Man könnte hier noch eine weitere Feinabstufungen dranhängen. Identische Dateinamen im selben Pfad sind aber recht selten :o). Wenn dieses Return tatsächlich beim Durchsuchen deiner Festplatte jemals erreicht wird, würde ich mir Sorgen machen  :) .
Gehören die Elemente verschiedenen Gruppen an, wird erstmal grob nach Gruppen vorsortiert (Die von Gruppe A sind zwangsläufig immer "kleiner" als die von Gruppe B).
Gehören sie derselben Gruppe an, dann wird feiner sortiert (z.B. alphabetisch, nach Datum oder as auch immer).

Jetzt kannst du die Dateinamen zunächst auf zwei Gruppen aufteilen und diese über die Compare-Funktion unterschiedlich sortieren. :wink:
(Du kannst nicht einzelne Elemente aus der Sortierung ausnehmen. Entweder du sortiertst die Liste komplett nach irgendeinem Kriterium, oder du lässt es. Was du wahrscheinlich möchtest, ist, dass bestimmte Dateien besonders hervorgehoben werden bzw. ganz oben kommen).

Um die Reihenfolge umzukehren, einfach bei allen Returns das Vorzeichen tauschen.

2: Zwei Arrays

Du verteilst das "große" Array mit allen Listeneinträgen auf zwei Arrays, sortierst nur eines und fügst sie dann wieder zusammen. Würde ich nicht machen, wenn nichts gegen Variante 1 spricht....

3. Filtern

Warum einzelne Dateinamen herauspicken? Du könntest auch einen Filter einbauen, der die unerwünschten Namen ausblendet oder ausgraut. :wink:

PS: Halte solche Compare-Funktionen so kurz und performant, wie nur irgendwie möglich!
Bild
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

Re: ListIconGadget Sortieren

Beitrag von silbersurfer »

Danke DarkSoul,

werde mal versuchen deinen Tipp umzusetzen, bei meiner Liste handelt es sich um eingelesene Verzeichnisse,
wo ich gerne die Folder immer oben haben will.

gruß Silbersurfer
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
DarkSoul
Beiträge: 689
Registriert: 19.10.2006 12:51

Re: ListIconGadget Sortieren

Beitrag von DarkSoul »

Hast du dir mal das Explorergadget angesehen? :)
Bild
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

Re: ListIconGadget Sortieren

Beitrag von silbersurfer »

Ja habe ich Darksoul, aber für mein Projekt viel zu langsam darum habe ich das mit ListiconGadget selber geschrieben, Mein Projekt ist ein Datei Manager via Total Comannder.
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Antworten