Seite 1 von 1

Listicon Gadget

Verfasst: 15.06.2010 16:19
von a14xerus
Ich Suche eine Möglichkeit ein ListiconGadget so wie in jedem normalen Windowsprogram üblichen Stil zu sortieren.
Sprich ein klick auf die Titel-Leiste sorgt für eine Sortierung des Inhalts.

Dabei geht es mir nichtmals vorrangig um die Sortierung, sondern um das Layout..

Also das so ein kleines Dreieck angezeigt wird in der jeweiligen Titelspalte, und das ich dieses Event halt bekomme.
Sortieren kann ich auch selber, falls es noch keine Funktion dafür gibt :)
Bild

Und wenn ihr ganz nett seit (und wisst wie es geht), könntest ihr mir noch verraten, wie man ein DropdownMenü ausgehend von einer Titel-Spalte anzeigt ;)
Das wäre aber nur 2.rangig
Bild

Re: Listicon Gadget

Verfasst: 15.06.2010 17:11
von hjbremer
folgender Apibefehl ist dafür zuständig

Code: Alles auswählen

;Pfeil im Header Windows XP
#HDF_SORTDOWN = $200 
#HDF_SORTUP = $400 

HD_ITEM.HD_ITEM
HD_ITEM\mask=#HDI_FORMAT
SendMessage_(hdid, #HDM_GETITEM, col, HD_ITEM) 

If HD_ITEM\fmt & #HDF_SORTDOWN
   HD_ITEM\fmt ! #HDF_SORTDOWN
   HD_ITEM\fmt | #HDF_SORTUP  
   richtung = #PB_Sort_Ascending
ElseIf HD_ITEM\fmt & #HDF_SORTUP
   HD_ITEM\fmt ! #HDF_SORTUP
   HD_ITEM\fmt | #HDF_SORTDOWN  
   richtung = #PB_Sort_Descending
Else
   HD_ITEM\fmt | #HDF_SORTDOWN  
   richtung = #PB_Sort_Descending
EndIf   

SendMessage_(hdid, #HDM_SETITEM, col, HD_ITEM)

Re: Listicon Gadget

Verfasst: 15.06.2010 17:20
von Kiffi
@a14xerus: Falls Du nichts gegen UserLibs hast, könnte
ich PureLVSORT von gnozal empfehlen:

http://gnozal.ucoz.com/#UserLibs

Grüße ... Kiffi

Re: Listicon Gadget

Verfasst: 15.06.2010 17:41
von a14xerus
@ kiffi: die lib kenne ich, war mir aber zuuuu .. "exotisch"
ne quatsch.. hab halt nach genau soetwas gesucht das hjbremer mit geliefert hat.
Also dieses "native" was schon in Windows eingebaut ist. Sortieren kann ich ja, da ich ja sowieso die Daten intern immer in LL verwalte.

@hjbremer
Danke ist schonmla die hälfte :)


Weiß jetzt noch jemand wie ich das Event abfange, auf welche Column geklickt wurde? (Also auf welchen Titel-eintrag)

Re: Listicon Gadget

Verfasst: 15.06.2010 18:39
von hjbremer
Das mit dem Headerclick ist im Prinzip simpel, aber auch knifflig,
denn man muß einen Click zum Sortieren von einem Click zum Verschieben der Spalten
oder Drag Drop von Spalten unterscheiden.

Zuerst der Headerclick ohne Callback

Code: Alles auswählen

Procedure.i MainListeHeaderClick()
With pv.myProgrammvariablen

Protected spalte = -1   
Protected p.POINT  
Protected HitInfo.HD_HITTESTINFO 
Protected flags, iitem

  If GetCapture_() = \headerid
     GetCursorPos_(p) 
     MapWindowPoints_(0,\headerid,p,1) ;hwndfrom muß null sein !        
     Hitinfo\pt\x = p\x 
     HitInfo\pt\y = p\y 
     SendMessage_(\headerid,#HDM_HITTEST,0,HitInfo)        
     flags = hitinfo\flags      ;:Debug "flags " + Str(flags)
     iitem = hitinfo\iitem      ;:Debug "iitem " + Str(iitem)
     If flags = #HHT_ONHEADER
        spalte = iitem  
     ElseIf flags = #HHT_ONDIVOPEN And iitem = 0
        \headernull = 1  ;es wird versucht 
     EndIf               ;die Breite von Spalte 0 zu ändern
  EndIf

EndWith
  
ProcedureReturn spalte 
EndProcedure
Und nun die Events abfangen

Code: Alles auswählen

Procedure.i WM_events(event)
Protected point.Point, j
Static spalte 

Select event
        
   ;für Mainliste per Headerclick sortieren         
   Case #WM_LBUTTONDOWN ;linke Maustaste gedrückt
      ;Rückgabe ist -1 oder Spaltennr. ab 1. Spalte null wird nicht benutzt.
      spalte = MainListeHeaderClick() 
                 
   Case #WM_MOUSEMOVE ;wenn zwischen #WM_LBUTTONDOWN + #WM_LBUTTONUP ein move, 
      spalte = -1     ;dann Aktion = Drag/Drop oder Breite ändern
       
   Case #WM_LBUTTONUP   ;nur wenn zwischen down + up kein move, dann sortieren
      If spalte > -1
         MainListeHeaderSort(spalte)
      ElseIf pv\headernull   ;wird in MainListeHeaderClick() ev. gesetzt
         pv\headernull = 0
         SetGadgetItemAttribute(#main_liste, 0, #PB_ListIcon_ColumnWidth, 0, 0)
      EndIf   
       
EndSelect

EndProcedure
in der Main Repeat Schleife sieht es etwa so aus um WM_events(event) einzubinden

Code: Alles auswählen

Repeat: event = WaitWindowEvent() ;: Debug event
   
   WM_events(event)
           
   Select event          
                  
      Case #PB_Event_Gadget, #PB_Event_Menu  
         
         wB = EventGadget()
               
         Datei_Events(wB)
         Daten_Events(wB)
         
         If wB = #menu_progende: event = #PB_Event_CloseWindow: EndIf
           
   EndSelect
   
Until event = #PB_Event_CloseWindow 
PS: mit Callback ist es einen Tick einfacher, aber der Weg ist der Gleiche

Das Problem ist ein #WM_MOUSEMOVE zwischen #WM_LBUTTONDOWN + #WM_LBUTTONUP
bei Drag und Drop, falls Drag Drop denn erlaubt wurde

Re: Listicon Gadget

Verfasst: 15.06.2010 18:44
von a14xerus
danke danke danke :)

ich bau's gleich mal ein und schmöker etwas durch den code um ihn in mich aufzusaugen wie in schwamm :D

Drag and Drop brauche ich erstmal nicht (zum glück^^;) )

Re: Listicon Gadget

Verfasst: 15.06.2010 18:53
von hjbremer
Hab vergessen zu posten wie man die Headerid bekommt, falls du es nicht wissen solltest

Code: Alles auswählen

headerid = SendMessage_(Gadgetid(lvpbnr), #LVM_GETHEADER, 0, 0) 

Re: Listicon Gadget

Verfasst: 15.06.2010 20:24
von a14xerus

Re: Listicon Gadget

Verfasst: 16.06.2010 00:09
von hjbremer
a14xerus hat geschrieben: Und wenn ihr ganz nett seit (und wisst wie es geht), könntest ihr mir noch verraten, wie man ein DropdownMenü ausgehend von einer Titel-Spalte anzeigt
Dies geht eigentlich sinnvoll nur über Subclassing des Headers. Wenn man mehrere Listicongadgets hat muß man noch hwnd des Callbacks mit den Headerids vergleichen.

ein simples Beispiel, welches bei Rightclick auf den Header ein PopUp anzeigt
je nach Spalte ein anderes.

Code: Alles auswählen

;Rightclick on LvHeader mit PopUpMenu

#window   = 0 
#listview = 0 
  
Procedure myLvHeaderCallback(hwnd, msg, wParam, lParam) 
Protected old = GetWindowLongPtr_(hwnd,#GWL_USERDATA) 
Protected hd.HD_HITTESTINFO 
    
If msg = #WM_RBUTTONDOWN 
      
   hd\pt\x = lParam & $FFFF 
   hd\pt\y = (lParam >> 16) & $FFFF 
   SendMessage_(hwnd, #HDM_HITTEST, 0, hd) 
   
   DisplayPopupMenu(hd\iItem, hwnd)

EndIf 
    
ProcedureReturn CallWindowProc_(old, hwnd, msg, wParam, lParam) 
EndProcedure 
  
Procedure SubClassHeader(pbnr) 
If IsGadget(pbnr) 
   Protected id  = SendMessage_(GadgetID(pbnr), #LVM_GETHEADER, 0, 0) 
   Protected old = SetWindowLongPtr_(id, #GWL_WNDPROC, @myLvHeaderCallback()) 
   Protected prv = SetWindowLongPtr_(id, #GWL_USERDATA, old) 
EndIf 
EndProcedure 
  
  
OpenWindow(#window, 0, 0, 300, 400, "LvTest", 1) 
 
   ListIconGadget(#listview, 0, 0, 400, 400, "col 0", 150)
   SubClassHeader(#listview) 
   AddGadgetColumn(#listview, 1, "col 1", 150) 
  
   CreatePopupMenu(0)
   MenuItem(1001, "Hallo")
   MenuItem(1002, "Du da")

   CreatePopupMenu(1)
   MenuItem(1101, "Guten Tag")
   MenuItem(1102, "Guten Abend")

Repeat: Until WaitWindowEvent() = #PB_Event_CloseWindow