ListIconGadget wird AuswahlGadget

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.
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

ListIconGadget wird AuswahlGadget

Beitrag von hjbremer »

Anstatt mehrere Listviewgadgets nebeneinander hier ein AuswahlGadget

Da es auch für Version PB 4.4 laufen mußte, habe ich ein statisches Array in der Structure benutzt

IncludeDatei:

Code: Alles auswählen

;AuswahlGadget - PB 4.41 (x86) Windows Vista - Dez.2012 - by HJBremer

#awg_maxcols = 100         ;irgendein sinnvoller Wert für Array in der Structure

;flags bei Aufruf          ;z.B. #awg_withspaces | #awg_hidewithesc
#awg_withspaces = 1        ;wenn gesetzt, Auswahl mit Spaces zwischen den Werten
#awg_hidewithesc = 2       ;Gadget verschwindet mit Esc (Hidegadget wird aufgerufen)

Structure AuswahlGadget
   pbnr.i                  ;PB Gadgetnr
   flag.i                  ;für GetText
   cols.i                  ;Anzahl Cols beginnend ab null
   lvptr.i                 ;pointer Rücksprung vom Callback
   mousecolor.i               ;Highlight Mouse
   clickcolor.i               ;Frontcolor für angeclickt
   auswahl.s                  ;Text der angeclickten Spalten für GetText
   colclick.i[#awg_maxcols + 1]  ;enthält angeclicktes item einer Spalte
   StructureUnion                ;um lParam in Hi + Loword zu zerlegen für Mouseposi
      lparam.i                   ; lParam vom Callback
      points.points              ; aufgeteiltes lParam in x + y
   EndStructureUnion   
EndStructure

EnableExplicit

Procedure.s AuswahlGadgetGetText(pbnr)
   
   Protected *awg.AuswahlGadget = GetWindowLongPtr_(GadgetID(pbnr), #GWL_USERDATA)   
   Protected j, item
   
   With *awg
      \auswahl = ""
      For j = 1 To \cols         ;alle Spalten abfragen
         item = \colclick[j]
         If item >= 0
            \auswahl + GetGadgetItemText(pbnr, item, j) 
            If \flag: \auswahl + " ": EndIf
         EndIf   
      Next      
   EndWith
   
   ProcedureReturn *awg\auswahl
   
EndProcedure

Procedure.i AuswahlGadgetAutoSize(pbnr)
   
   Protected *awg.AuswahlGadget = GetWindowLongPtr_(GadgetID(pbnr), #GWL_USERDATA)      
   Protected j, rect.rect
   Protected br = GetSystemMetrics_(#SM_CYEDGE) * 2   ;Rahmenbreite, meistens 2 * 2 = 4
     
   With *awg 
      
      HideGadget(pbnr, 1)
   
      For j = 1 To \cols   
         SendMessage_(GadgetID(pbnr), #LVM_SETCOLUMNWIDTH, j, #LVSCW_AUTOSIZE)
      Next
      
      rect\top = \cols           
      rect\left = #LVIR_LABEL
      SendMessage_(GadgetID(pbnr), #LVM_GETSUBITEMRECT, 0, rect) 
                  
      br + rect\right
      
      ;wenn Scrollbalken vorhanden, Breite addieren
      If GetWindowLongPtr_(GadgetID(pbnr), #GWL_STYLE) & #WS_VSCROLL
         br + GetSystemMetrics_(#SM_CXVSCROLL)
      EndIf
      
      ResizeGadget(pbnr, #PB_Ignore, #PB_Ignore, br, #PB_Ignore)
      
      HideGadget(pbnr, 0)
      
   EndWith
   
EndProcedure

Procedure.i AuswahlGadgetCenterCols(pbnr)
   
   Protected *awg.AuswahlGadget = GetWindowLongPtr_(GadgetID(pbnr), #GWL_USERDATA)   
   Protected j, lv.LV_COLUMN 

   lv\mask = #LVCF_FMT 
   lv\fmt  = #LVCFMT_CENTER 
   
   For j = 1 To *awg\cols
      SendMessage_(GadgetID(pbnr), #LVM_SETCOLUMN, j, lv) 
   Next
   
EndProcedure  

Procedure.i AuswahlGadgetReset(pbnr)
   ;löscht alle Clicks
   
   Protected *awg.AuswahlGadget = GetWindowLongPtr_(GadgetID(pbnr), #GWL_USERDATA)
   Protected j
   
   With *awg      
      For j = 1 To \cols
         SetGadgetItemColor(\pbnr, \colclick[j], #PB_Gadget_FrontColor, -1, j)
         \colclick[j] = -1
      Next            
   EndWith
   
EndProcedure

Procedure.i AuswahlGadgetRelease(pbnr)   
   ;zerstört das Gadget
   
   Protected *awg.AuswahlGadget = GetWindowLongPtr_(GadgetID(pbnr), #GWL_USERDATA)
   
   With *awg      
      SetWindowLongPtr_(GadgetID(pbnr), #GWL_WNDPROC, \lvptr)  ;Callback aufheben
      FreeGadget(pbnr)
      FreeMemory(*awg)            
   EndWith
   
EndProcedure

Procedure.i AuswahlGadgetCallBack(hwnd, msg, wParam, lParam) 
   ;hwnd ist hier gleich der ID vom Gadget
   
   Protected *awg.AuswahlGadget = GetWindowLongPtr_(hwnd, #GWL_USERDATA)   
   Protected j, item, subitem, itemhh, rect.rect   
   Static olditem, oldsubitem
   
   With *awg

      If msg = #WM_MOUSEMOVE
         
         ;nur zur Info. 
         ;#LVN_HOTTRACK gibt es nur im ParentCallback und liefert auch nur dann
         ;den itemwert, wenn der Style #PB_ListIcon_FullRowSelect angegeben wurde
         ;Beides ist hier unerwünscht, darum Berechnung von item und subitem wie folgt.
      
         ;Mouseposi
         \lparam = lparam    ;Hi+Loword stehen in \points\x + y
         
         ;subitem
         For j = 1 To \cols            
            rect\top = j               ;subitem angeben, Col 0 wird nicht benutzt
            rect\left = #LVIR_LABEL
            SendMessage_(hwnd, #LVM_GETSUBITEMRECT, 0, rect) 
            If rect\right > \points\x             
               subitem = j: Break
            EndIf                  
         Next
         
         itemhh = rect\bottom - rect\top    ;:Debugr(rect) 
         
         ;item
         item = SendMessage_(hwnd, #LVM_GETTOPINDEX, 0, 0) + (\points\y / itemhh)
         
         ;subitem color
         If olditem <> item Or oldsubitem <> subitem
            SetGadgetItemColor(\pbnr, olditem, #PB_Gadget_BackColor, -1, oldsubitem)
            SetGadgetItemColor(\pbnr, item, #PB_Gadget_BackColor, \mousecolor, subitem)
            olditem = item
            oldsubitem = subitem
         EndIf
         
      ElseIf msg = #WM_NCMOUSEMOVE ;msg = #WM_NCMOUSELEAVE
         ;Wenn Maus Gadget verlässt, soll Backcolor wieder hergestellt werden
         ;aber bei schnellen Mausbewegungen geht diese Message verloren.
         SetGadgetItemColor(\pbnr, olditem, #PB_Gadget_BackColor, -1, oldsubitem)

      ElseIf msg = #WM_RBUTTONDOWN
         ;alle Spaltenclicks entfernen, wie AuswahlGadgetReset() 
         For j = 1 To \cols
            SetGadgetItemColor(\pbnr, \colclick[j], #PB_Gadget_FrontColor, -1, j)
            \colclick[j] = -1
         Next   
         
      ElseIf msg = #WM_LBUTTONDOWN
         
         ;olditem ist Static und ist gleich der aktuellen Cursorposition, siehe WM_MOUSEMOVE subitem Color
         
         ;in einer Spalte vorherige Farbe zurücksetzen
         SetGadgetItemColor(\pbnr, \colclick[oldsubitem], #PB_Gadget_FrontColor, -1, oldsubitem)
         
         ;neue Farbe setzen
         SetGadgetItemColor(\pbnr, olditem, #PB_Gadget_FrontColor, \clickcolor, oldsubitem)
         
         ;merken wo neue Farbe gesetzt
         \colclick[oldsubitem] = olditem
         
      ElseIf msg = #WM_CHAR
         If \flag & 2
            If wparam = 27
               HideGadget(\pbnr, 1)
            EndIf
         EndIf

      ElseIf msg = #LVM_INSERTCOLUMN  ;4123
         ;diese Message gibt es nur beim Erstellen der Liste
         ;jeder Aufruf von AddGadgetColumn(pbnr, ... ) erzeugt diese Message
         ;dies ermöglicht das Ermitteln der Spaltenanzahl an dieser Stelle !
         
         ;ermittelt Anzahl Columns und setzt colclick auf -1 
         \cols = SendMessage_(SendMessage_(hwnd, #LVM_GETHEADER, 0, 0), #HDM_GETITEMCOUNT, 0, 0)
         If \cols > #awg_maxcols
            MessageRequester("", "zu viele Spalten, max " + Str(#awg_maxcols))
            End
         EndIf
         \colclick[\cols] = -1 
         
      Else         
         ;debugmsg(msg)
      EndIf      
      
      ProcedureReturn CallWindowProc_(\lvptr, hwnd, msg, wParam, lParam) 
      
   EndWith
EndProcedure 

Procedure.i AuswahlGadget(pbnr, sp, ze, br, hh, flag = 0)
   
   Protected *awg.AuswahlGadget = AllocateMemory(SizeOf(AuswahlGadget))   
   Protected j, id, returnvalue, rect.rect 
   
   Protected flags = #PB_ListIcon_GridLines|#LVS_NOCOLUMNHEADER
      
   With *awg
      
      If pbnr = #PB_Any
         pbnr = ListIconGadget(#PB_Any, sp, ze, br, hh, "", 0, flags)
         returnvalue = pbnr
      Else
         returnvalue = ListIconGadget(pbnr, sp, ze, br, hh, "", 0, flags)
      EndIf
      
      \pbnr = pbnr      
      \flag = flag       
      \mousecolor = #Yellow   ;Backcolor Subitem MouseHighlight
      \clickcolor = $0300D3   ;Frontcolor Subitem angeclickt
      
      ;meine Default Colors
      SetGadgetColor(pbnr, #PB_Gadget_BackColor, $FFF8F9)
      SetGadgetColor(pbnr, #PB_Gadget_FrontColor, $9D0016)
      
      ;Original WindowProcPointer holen
      \lvptr = GetWindowLongPtr_(GadgetID(pbnr), #GWL_WNDPROC)
      
      ;GadgetMemory und eigene WindowProc setzen
      SetWindowLongPtr_(GadgetID(pbnr), #GWL_USERDATA, *awg)
      SetWindowLongPtr_(GadgetID(pbnr), #GWL_WNDPROC, @AuswahlGadgetCallBack())
            
   EndWith
   
   ProcedureReturn returnvalue
   
EndProcedure

DisableExplicit
Testdatei:

Code: Alles auswählen

XIncludeFile("AuswahlListe.pbi")   ;Name anpassen

Enumeration
   #window   
   #font0
   #font1
   #ipliste3
   #textgadget
   #buttonrelease
EndEnumeration

Procedure.i FillAuswahlGadget(pbnr)
   
   Protected j, z1
   
   For j = 1 To 7
      AddGadgetColumn(pbnr, j, "", 0)
   Next
   
   For j = 0 To 27      
      AddGadgetItem(pbnr, -1, "")      
   Next
   
   SetGadgetItemText(pbnr, 0, "S.", 1)
   SetGadgetItemText(pbnr, 1, "A.", 1)
   SetGadgetItemText(pbnr, 2, "AO.", 1)
   
   z1 = 135   
   For j = 0 To 16 
      SetGadgetItemText(pbnr, j, Str(z1), 2)
      z1 + 10      
   Next
   
   z1 = 25
   For j = 0 To 11
      SetGadgetItemText(pbnr, j, Str(z1), 3)
      z1 + 5
   Next
   
   z1 = 13
   For j = 0 To 7
      SetGadgetItemText(pbnr, j, Str(z1), 4)
      z1 + 1
   Next
   
   Restore reifenidx
   j = 0
   z1 = 1
   While z1
      Read.i z1
      If z1
         SetGadgetItemText(pbnr, j, " " + Str(z1), 5)
         j + 1
      EndIf
   Wend
   
   z1 = 81
   For j = 0 To 9
      SetGadgetItemText(pbnr, j, Chr(z1), 6)
      z1 + 1
   Next
   
   SetGadgetItemText(pbnr, 0, " MO", 7)
   SetGadgetItemText(pbnr, 1, " NO", 7)
   SetGadgetItemText(pbnr, 2, " RF", 7)
   SetGadgetItemText(pbnr, 3, " 6PR", 7)
   SetGadgetItemText(pbnr, 4, " 8PR", 7)
   
   DataSection
      reifenidx:
      Data.i 71,72,73,75,77,79,80,81,82,83,84,85,86,87,88,89,91,94,95,96,97,98,99
      Data.i 100,102,103,109,112
      Data.i 0
   EndDataSection
   
EndProcedure

Procedure.i Mainwindow()
   
   LoadFont(#font0, "Arial", 9)  
   LoadFont(#font1, "Arial", 12)  
   
   Protected j, event
   
   Protected winbr = 700
   Protected winhh = 550
   Protected flags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget
   
   OpenWindow(#window, 150, 150, winbr, winhh, "", flags)
   
   AuswahlGadget(#ipliste3, 200, 5, 0, winhh-30)
   SetGadgetFont(#ipliste3, FontID(#font1))
   
   FillAuswahlGadget(#ipliste3)
   
   AuswahlGadgetAutoSize(#ipliste3)
   AuswahlGadgetCenterCols(#ipliste3)
   
   TextGadget(#textgadget, 200, winhh-20, 180, 20, "", #PB_Text_Center)
   
   ;ButtonGadget(#buttonrelease, 10, 10, 80, 20, "Release") 
      
   SetActiveGadget(#ipliste3)
   
   ;Start   
   
   Repeat: event = WaitWindowEvent()
      
      If event = #PB_Event_Gadget   
         
         Select EventGadget()
               
            Case #ipliste3
               ;Eventtype() abfragen vermeidet doppelte Ausführung
               If EventType() = #PB_EventType_LeftClick
                  txt$ = AuswahlGadgetGetText(#ipliste3)                  
                  SetGadgetText(#textgadget, txt$)
               EndIf
               
            Case #buttonrelease
               AuswahlGadgetRelease(#ipliste3)
               
         EndSelect
         
      EndIf
      
   Until event = #PB_Event_CloseWindow 
   
EndProcedure

Mainwindow()
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer