listIconGadget Windows - Style "Sortier-Pfeile"

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
a14xerus
Beiträge: 1440
Registriert: 14.12.2005 15:51
Wohnort: Aachen

listIconGadget Windows - Style "Sortier-Pfeile"

Beitrag von a14xerus »

Hier eine kleine Include zum (verwalten und) sortieren mehrerer ListiconGadgets.
Die Include übernimmt nur die Verwaltung. Das sortieren und neufüllen des Gadgeds müsst ihr leider selber machen ;)

Die Include ist ein Produkt meinerseits entstanden durch Code von hjbremer aus diesem Thread:
http://www.purebasic.fr/german/viewtopi ... 16&t=22671

___________________________________________________________________


Ihr müsst nur bei jedem Eventschleifendurchlauf diese Procedure aufrufen:

ListHeader_SortObserve(gadget,event,*callback,ignoreDragDrop=#False)
  • gadget ist die Gadgetnummer des ListiconGadgets, welches überwacht werden soll.
  • event ist das Ergebnis von WindowEvent() oder WaitWindowEvent()
  • *callback ist ein Zeiger auf die Funktion die einen Parameter erwartet, in der Ihr dann den Inhalt des Gadgets sortieren könnt.
    Der übergebene Parameter sieht wie folgt aus:
    parameter.ListHeader_Struct
    • \gadget nochmal die Gadgetnummer
    • \column die Spalte die sortiert wird
    • \direction die Richtung in die sortiert wird (#PB_Sort_Ascending und #PB_Sort_Descending)
  • wenn ignoreDragDrop = #False ist, so wird ein Klick auf den Header nur gewertet, wenn sich die Maus zwischen drücken und loslassen nicht bewegt. Ist es gleich #True, so wird beim loslassen der Maus die Spalte gewertet, auf der die Maus beim drücken war.
Wird als *callback eine 0 übergeben, erfolgt eine Debugerausgabe.

Und hier die Include:

Code: Alles auswählen

; ListHeader_Sort.pbi
; Code edited by Alexander Nähring
; Original by hjbremer
; hjbremer: http://www.purebasic.fr/german/viewtopic.php?f=16&t=22671
; this Include: http://www.purebasic.fr/german/viewtopic.php?p=274926
EnableExplicit

Structure ListHeader_Struct
  gadget.i
  column.i
  direction.i
EndStructure

Procedure ListHeader_ClearArrow(gadget,column)
  #HDF_SORTDOWN = $200 
  #HDF_SORTUP = $400 
  Protected hdid
  hdid = SendMessage_(GadgetID(gadget), #LVM_GETHEADER, 0, 0)
  Protected HD_ITEM.HD_ITEM
  HD_ITEM\mask=#HDI_FORMAT
  SendMessage_(hdid, #HDM_GETITEM, column, HD_ITEM) 
  If HD_ITEM\fmt & #HDF_SORTDOWN
    HD_ITEM\fmt ! #HDF_SORTDOWN
  ElseIf HD_ITEM\fmt & #HDF_SORTUP
    HD_ITEM\fmt ! #HDF_SORTUP
  EndIf   
  SendMessage_(hdid, #HDM_SETITEM, column, HD_ITEM)
EndProcedure

Procedure ListHeader_SwitchArrow(gadget,column,ClearOtherArrows=#true)
  #HDF_SORTDOWN = $200 
  #HDF_SORTUP = $400 
  Protected hdid
  Protected direction
  
  hdid = SendMessage_(GadgetID(gadget), #LVM_GETHEADER, 0, 0)
  
  Protected HD_ITEM.HD_ITEM
  HD_ITEM\mask=#HDI_FORMAT
  SendMessage_(hdid, #HDM_GETITEM, column, HD_ITEM) 
  
  If HD_ITEM\fmt & #HDF_SORTDOWN
    HD_ITEM\fmt ! #HDF_SORTDOWN
    HD_ITEM\fmt | #HDF_SORTUP  
    direction = #PB_Sort_Ascending
  ElseIf HD_ITEM\fmt & #HDF_SORTUP
    HD_ITEM\fmt ! #HDF_SORTUP
    HD_ITEM\fmt | #HDF_SORTDOWN  
    direction = #PB_Sort_Descending
  Else
    HD_ITEM\fmt | #HDF_SORTDOWN  
    direction = #PB_Sort_Descending
  EndIf   
  
  SendMessage_(hdid, #HDM_SETITEM, column, HD_ITEM)
  
  Static NewList ListHeader_Arrows.ListHeader_Struct()
  
  ;add this column arrow state to LL
  With ListHeader_Arrows()
    Protected tmp
    tmp = #False
    ForEach ListHeader_Arrows()
      If \gadget = gadget
        If \column = column
          tmp = #true
          Break
        EndIf
      EndIf
    Next
    If Not tmp
      AddElement(ListHeader_Arrows())
      \gadget = gadget
      \column = column
      \direction = direction
    EndIf
    
    
    If ClearOtherArrows
      ForEach ListHeader_Arrows()
        If \gadget = gadget
          If \column <> column
            ListHeader_ClearArrow(\gadget,\column)
          EndIf
        EndIf
      Next
    EndIf
  EndWith 
  
  ProcedureReturn direction
EndProcedure

Procedure ListHeader_GetClickColumn(headerid)
  ;Protected pv.Headervars
  Protected column = -1   
  Protected p.POINT  
  Protected HitInfo.HD_HITTESTINFO 
  Protected flags, iitem
  
  Protected headernull.i
  
  ;With pv.Headervars
  If GetCapture_() = headerid
    GetCursorPos_(p) 
    MapWindowPoints_(0,headerid,p,1) ;hwndfrom muß null sein !        
    HitInfo\pt\x = p\x 
    SendMessage_(headerid,#HDM_HITTEST,0,HitInfo)        
    flags = HitInfo\flags      ;:Debug "flags " + Str(flags)
    iitem = HitInfo\iitem      ;:Debug "iitem " + Str(iitem)
    If flags = #HHT_ONHEADER
      column = iitem  
    ElseIf flags = #HHT_ONDIVOPEN And iitem = 0
      headernull = 1  ;es wird versucht 
    EndIf               ;die Breite von Spalte 0 zu ändern
  EndIf
  ;EndWith
  
  HitInfo\pt\y = p\y 
  ProcedureReturn column
EndProcedure

Procedure.i ListHeader_SortObserve(gadget,event,*callback,ignoreDragDrop=#False)
  Protected point.POINT, j
  Static NewMap ListHeader_GadgetColumnMap.i()
  Static headerid
  headerid = SendMessage_(GadgetID(gadget), #LVM_GETHEADER, 0, 0)
  
  Select event     
    Case #WM_LBUTTONDOWN
      ListHeader_GadgetColumnMap(Str(gadget)) = ListHeader_GetClickColumn(headerid) 
      
    Case #WM_MOUSEMOVE 
      If Not ignoreDragDrop
        ListHeader_GadgetColumnMap(Str(gadget)) = -1
      EndIf 
      
    Case #WM_LBUTTONUP
      If ListHeader_GadgetColumnMap(Str(gadget)) > -1
        Protected direction
        direction = ListHeader_SwitchArrow(gadget,ListHeader_GadgetColumnMap(Str(gadget)))
        
        If *callback
          Protected parameter.ListHeader_Struct
          parameter\gadget = gadget
          parameter\column = ListHeader_GadgetColumnMap(Str(gadget))
          parameter\direction = direction
          CallFunctionFast(*callback,parameter)
        Else
          Debug "No Callback for Sorting Column "+Str(ListHeader_GadgetColumnMap(Str(gadget)))+" on Gadget #"+Str(gadget)
        EndIf 
      EndIf   
      
  EndSelect
  
EndProcedure
Dazu noch ein Testprogramm:

Code: Alles auswählen

; gPreferences[460-5-1-1-1050-170-0-12-12]
;###################################################################
;###################################################################
EnableExplicit

Enumeration
  #W_Main
  
  #G_List
  #G_List2
EndEnumeration


;XIncludeFile "all.declare"

XIncludeFile "ListHeader_sort.pbi"


Procedure init()
  
  
EndProcedure

Procedure Window()
  If OpenWindow(#W_Main, 0, 0, 800, 460, "", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
    
    ListIconGadget(#G_List, 5, 5, 730, 225, "title 1", 100, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
    AddGadgetColumn(#G_List,1,"title 2",100)
    AddGadgetColumn(#G_List,2,"title 3",100)
    ListIconGadget(#G_List2, 5, 235, 730, 210, "title 1", 100, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
    AddGadgetColumn(#G_List2,1,"title 2",100)
    AddGadgetColumn(#G_List2,2,"title 3",100)
  EndIf
EndProcedure

Procedure close()
  End
EndProcedure

Procedure loop()
  Protected event.l, gadget.l
  Repeat
    event = WaitWindowEvent(50)
    ListHeader_SortObserve(#G_List,event,0,#true)
    ListHeader_SortObserve(#G_List2,event,0,#true)
    Select event
      Case #WM_PAINT
        Continue
      Case #WM_CLOSE
        close()
      Case #PB_Event_Gadget
        gadget = EventGadget()
        Select gadget
            
        EndSelect
    EndSelect
  ForEver
EndProcedure

Procedure main()
  init()
  Window()
  loop()
EndProcedure


main()
Und hier nochmal alles zusammen im Paket mit Include, Testprogramm und Exe:
http://hosting.alexander-n.de/=MTIzLjEyNzY2MjYxNTQ=
Benutzeravatar
Blackskyliner
Beiträge: 532
Registriert: 28.07.2005 00:54
Wohnort: /home/Blackskyliner/

Re: listIconGadget Windows - Style "Sortier-Pfeile"

Beitrag von Blackskyliner »

Statt CallFunctionFast, bitte Prototypen nutzen, das erstere ist nur noch wegen Kompatibilität dabei...
Aber ansonsten :allright:

MFG
Blackskyliner
Keine meiner Antworten ist endgültig, es kann passieren, dass ich den so eben geposteten Beitrag noch mehrmals ändere, um Doppelposts zu umgehen.
_________________
Purebasic Windows 7 x64 & Linux (Ubuntu 10.04LTS) 4.50[x64|x86] Nutzer
_________________
Projekte: YAED - Yet another Event Dispatcher
Benutzeravatar
dige
Beiträge: 1241
Registriert: 08.09.2004 08:53

Re: listIconGadget Windows - Style "Sortier-Pfeile"

Beitrag von dige »

Wenn man das Sortieren selbst übernimmt, muss man auch das Updaten
des Controls übernehmen - und das ist deutlich langsamer als die Win API.
Bei mehr als 1.000 Elementen ... (also zumindest der ClearGadgetItemList(),
AddGadgetItem() und Disable Redraw Weg)
"Papa, ich laufe schneller - dann ist es nicht so weit."
Antworten