Habe Edels Beispiel mal etwas aufgepeppt. Es ist immer noch ein Beispiel, da Save + Load fehlen, aber doch etwas flexibler.
Code: Alles auswählen
;Bitte beachten: Ab PB 5.30 (x86)
DeclareModule LvCheckbox
   
   ; Alle Elemente in diesem Abschnitt sind für den Zugriff von außerhalb verfügbar
   
   EnableExplicit
   
   #PB_EventType_ChangeCheckBox = #PB_Event_FirstCustomValue + 100
   
   Declare.i LvCheckbox_SetColumn(gadget, col, datacol = #PB_Any)
   
   Declare.i LvCheckBox_GetState(gadget, row, col)
   
   Declare.i LvCheckbox_Callback(hWnd, msg, wParam, lParam)
   
EndDeclareModule
Module LvCheckbox
   
   ; TODO Colors in extra Prozedur
   ; TODO Save + load ?
   ; TODO Multiselect checked abfragen
   
   ;Allgemein
   ; Verschieben von Spalten wird nicht unterstützt.
   ; Anhängen von Spalten ist gestattet, 
   ; da es egal ist welche Spalte den Status der Checkboxen aufnimmt.
   ; Warum gibt es eine Statusspalte ? Wegen Save/Load !
   ; Warum braucht man einen MainCallback ? Weil #WM_DRAWITEM nur ans Parentwindow gesendet wird
   ; und darum Subclassing des ListIcongadgets so einfach nicht geht.
   
   EnableExplicit
   
   Structure checkboxdata
      datacolumn.i         ;Spalte welche den Status der Checkbox(en) enthält
      colornormal.i        ;Text normal
      colorchecked.i       ;Text wenn Checkbox hat Haken
      colorselected.i      ;Text wenn Checkbox hat Haken und Zeile select
      colorbackbrush.i     ;Hintergrund wenn Zeile select
      Array checkbox.i(0)  ;Internes Feld, Index gleich Spalte und ist 1 = hat Checkbox 
   EndStructure
   
   Procedure.i CheckBox_State(gadget, row, col)
      Protected t$, state
      Protected *ckb.checkboxdata = GetWindowLongPtr_(GadgetID(gadget), #GWL_USERDATA) 
      
      If *ckb\checkbox(col)
         t$ = GetGadgetItemText(gadget, row, *ckb\datacolumn)
         
         If Mid(t$, col+1, 1) = "1"
            state = #True
         Else
            state = #False
         EndIf
         
      EndIf   
      
      ProcedureReturn state
   EndProcedure
   
   Procedure.i LvCheckBox_GetState(gadget, row, col)
      
      Protected state, boxdata$
      
      Protected *ckb.checkboxdata = GetWindowLongPtr_(GadgetID(gadget), #GWL_USERDATA) 
      If *ckb
         If row > -1
            boxdata$ = GetGadgetItemText(gadget, row, *ckb\datacolumn)
            If Mid(boxdata$, col + 1, 1) = "1"
               state = 1
            EndIf 
         EndIf
      EndIf
      
      ProcedureReturn state
      
   EndProcedure
   
   Procedure.i CheckBox_SetState(gadget, row, col, state)
      Protected t$, l$, r$
      
      Protected *ckb.checkboxdata = GetWindowLongPtr_(GadgetID(gadget), #GWL_USERDATA) 
      
      Protected datalg = ArraySize(*ckb\checkbox()) + 1
      
      
      If *ckb\checkbox(col)
         t$ = GetGadgetItemText(gadget, row, *ckb\datacolumn)
         t$ = LSet(t$, datalg, "-")
         
         l$ = Left(t$, col)
         r$ = Mid(t$, col+2)
         
         If state = 1
            t$ = l$ + "1" + r$ 
         Else
            t$ = l$ + "0" + r$
         EndIf
         SetGadgetItemText(gadget, row, t$, *ckb\datacolumn)        
      EndIf
      
   EndProcedure
   
   Procedure.i LvCheckbox_SetColumn(gadget, col, datacol = #PB_Any)
      
      Protected *ckb.checkboxdata = GetWindowLongPtr_(GadgetID(gadget), #GWL_USERDATA)
      
      ;internes Mem
      If *ckb = #False
         *ckb = AllocateStructure(checkboxdata)
         SetWindowLongPtr_(GadgetID(gadget), #GWL_USERDATA, *ckb)
      EndIf
      
      ;weils einfacher ist, Array immer Redim
      Protected header = SendMessage_(GadgetID(gadget), #LVM_GETHEADER, 0, 0)
      Protected colanz = SendMessage_(header, #HDM_GETITEMCOUNT, 0, 0) - 1          
      ReDim *ckb\checkbox(colanz)
      
      ;diese Column bekommt eine Checkbox
      *ckb\checkbox(col) = #True 
      
      ;in diese Col kommt der DataString
      If datacol = #PB_Any  
         *ckb\datacolumn = colanz   ;letzte Column
      Else
         *ckb\datacolumn = datacol  ;User definierte Col
      EndIf
      
      ;könnte auch in einer extra Prozedur stehen
      *ckb\colornormal = #Black
      *ckb\colorchecked = #Blue
      *ckb\colorselected = $C20000
      *ckb\colorbackbrush = $FFBFBF
      
   EndProcedure
      
   Procedure.i LvCheckbox_Callback(hWnd, msg, wParam, lParam)
      
      ;Variablen allgemein
      Protected pbnr       ;Gadgetnr
      Protected pbid       ;GadgetID()
      Protected item       ;Row
      Protected subitem    ;Column     
      Protected rc.RECT    ;Rechteck einer Zelle  
      Protected *ckb.checkboxdata   ;Userdaten für die Checkboxen
      
      ;Variablen #WM_NOTIFY
      Protected *nmia.NMITEMACTIVATE
      
      ;Variablen #WM_DRAWITEM 
      Protected text.s      
      Protected head
      Protected cols
      Protected backbrush   
      Protected cc.RECT
      Protected *draw.DRAWITEMSTRUCT 
      
      Select msg 
                        
         Case #WM_NOTIFY         
            ;- WM_notify
            
            *nmia = lParam           
            
            ; Click in das Listview ?
            If *nmia\hdr\code = #NM_CLICK
               
               pbnr = *nmia\hdr\idFrom
               pbid = *nmia\hdr\hwndFrom
               item = *nmia\iItem
               subitem = *nmia\iSubItem
               
               If IsGadget(pbnr)
                  If GadgetType(pbnr) = #PB_GadgetType_ListIcon
                     ;Userdata holen
                     *ckb = GetWindowLongPtr_(pbid, #GWL_USERDATA) 
                     If *ckb            
                        ;hat Subitem eine Checkbox ?
                        If *ckb\checkbox(subitem) = #True               
                           rc\top = subitem 
                           rc\left = #LVIR_BOUNDS
                           SendMessage_(pbid, #LVM_GETSUBITEMRECT, item, rc)               
                           rc\left  + 4
                           rc\right = rc\left + 14               
                           ; Click in die Checkbox?
                           If PtInRect_(rc, PeekQ(*nmia\ptAction))   
                              ;CheckBox_State speichern                     
                              If CheckBox_State(pbnr, item, subitem) = 0
                                 ;auf 1 setzen
                                 CheckBox_SetState(pbnr, item, subitem, 1)
                              Else
                                 CheckBox_SetState(pbnr, item, subitem, 0)                        
                              EndIf                     
                              ;Neuzeichnen erzwingen
                              InvalidateRect_(pbid, 0, 0)
                              ;Event abschicken
                              PostEvent(#PB_Event_Gadget, #PB_Ignore, pbnr, #PB_EventType_ChangeCheckBox, subitem)
                           EndIf
                        EndIf
                     EndIf
                  EndIf                  
               EndIf 
               
            EndIf
            
            
         Case #WM_DRAWITEM
            ;- #WM_DRAWITEM
                        
            *draw = lParam         
            
            If *draw\CtlType = #ODT_LISTVIEW 
               
               pbnr = *draw\CtlID
               pbid = *draw\hwndItem
               item  = *draw\itemID
               subitem = 0
               
               If IsGadget(pbnr)
                  If GadgetType(pbnr) = #PB_GadgetType_ListIcon
                     
                     ;Userdata holen
                     *ckb = GetWindowLongPtr_(pbid, #GWL_USERDATA) 
                     If *ckb               
                        
                        backbrush = CreateSolidBrush_(*ckb\colorbackbrush)  
                        
                        head = SendMessage_(pbid, #LVM_GETHEADER, 0, 0)
                        cols = SendMessage_(head, #HDM_GETITEMCOUNT, 0, 0) ; Spaltenanzahl
                        
                        ; alle Spalten durchlaufen         
                        For subitem = 0 To cols - 1 
                           
                           ;Rect für Subitem bis Ende der Zeile ermitteln
                           rc\top = subitem
                           rc\left = #LVIR_BOUNDS
                           SendMessage_(pbid, #LVM_GETSUBITEMRECT, item, rc)
                           
                           ; Ist die Zeile selektiert? dann blauer Balken (backbrush)  
                           If *draw\itemState & #ODS_SELECTED
                              FillRect_(*draw\hdc, rc, backbrush)         
                           EndIf                        
                           
                           ;Right begrenzen für aktuelles Subitem
                           rc\right = rc\left + GetGadgetItemAttribute(*draw\CtlID, *draw\itemID, #PB_ListIcon_ColumnWidth, subitem)           
                           
                           ;Text holen
                           text = GetGadgetItemText(pbnr, item, subitem)
                           
                           ; ein wenig Luft in der Spalte, jeweils für Text und Checkbox
                           rc\left  + 4
                           rc\right - 4               
                           CopyRect_(cc, rc)
                           
                           ;für Checkbox muß \right kleiner sein
                           cc\right = cc\left + 16               
                           
                           SetTextColor_(*draw\hdc, *ckb\colornormal)
                           
                           If *ckb\checkbox(subitem) = #True ; nur die definierten Spalten bekommen eine Checkbox !      
                              
                              ; CheckBox_State abfragen und Checkbox zeichnen                  
                              If CheckBox_State(*draw\CtlID, *draw\itemID, subitem) = #True
                                 If *draw\itemState & #ODS_SELECTED
                                    SetTextColor_(*draw\hdc, *ckb\colorselected)
                                 Else
                                    SetTextColor_(*draw\hdc, *ckb\colorchecked)
                                 EndIf              
                                 DrawFrameControl_(*draw\hDC, cc, #DFC_BUTTON, #DFCS_BUTTONCHECK | #DFCS_CHECKED)
                              Else
                                 DrawFrameControl_(*draw\hDC, cc, #DFC_BUTTON, #DFCS_BUTTONCHECK)   
                              EndIf                              
                              
                              ; Text verschieben
                              rc\left + 20
                              
                              ; Text zeichnen
                              DrawText_(*draw\hDC, text, -1, rc, #DT_SINGLELINE | #DT_VCENTER)             
                              
                           Else
                              ; Text ohne Checkbox zeichnen
                              DrawText_(*draw\hDC, text, -1, rc, #DT_SINGLELINE | #DT_VCENTER)             
                           EndIf            
                           
                        Next               
                        DeleteObject_(backbrush)
                     EndIf
                     
                  EndIf
               EndIf
               
            EndIf
            
      EndSelect   
      
   EndProcedure
   
EndModule
UseModule LvCheckbox
Enumeration Window
   #window
EndEnumeration
Enumeration Gadget
   #list
   #list2
   #button0
   #button1
   #button2
   #button3
   #button4
EndEnumeration
Procedure.i MainCallback(hWnd, msg, wParam, lParam)
   
   LvCheckbox_Callback(hWnd, msg, wParam, lParam)
   
   ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure Main()   
   Protected j, event, rowlv1, rowlv2
   
   If OpenWindow(#window, #PB_Ignore, #PB_Ignore, 999, 400, "")
      
      SetWindowCallback(@MainCallback())  
      
      ButtonGadget(#button0,  11, 350, 89, 22, "Col 0")
      ButtonGadget(#button1, 111, 350, 89, 22, "Col 1")
      ButtonGadget(#button2, 211, 350, 89, 22, "Col 2")
      ButtonGadget(#button3, 311, 350, 89, 22, "Col 3")
      ButtonGadget(#button4, 411, 350, 89, 22, "Col 4")
      
      ListIconGadget(#list, 5, 10, 650, 300, "Col0", 111, #LVS_OWNERDRAWFIXED|#PB_ListIcon_GridLines|#PB_ListIcon_MultiSelect )
      AddGadgetColumn(#list, 1, "Col1", 111)
      AddGadgetColumn(#list, 2, "Col2", 111)
      AddGadgetColumn(#list, 3, "Col3", 111)
      AddGadgetColumn(#list, 4, "Col4", 111)
      AddGadgetColumn(#list, 5, "Data", 70)
      
      LvCheckbox_SetColumn(#list, 1)
      LvCheckbox_SetColumn(#list, 2)
      LvCheckbox_SetColumn(#list, 4)   ;oder LvCheckbox_SetColumn(#list, 4, 5) 5 steht für DataColumn
      
      For j = 0 To 23
         AddGadgetItem(#list, -1, "Col0" + #LF$ + "Col1" + #LF$ + "Col2" + #LF$ + "Col3" + #LF$ + "Col4" + #LF$ + "00101")
         AddGadgetItem(#list, -1, "Col0" + #LF$ + "Col1" + #LF$ + "Col2" + #LF$ + "Col3" + #LF$ + "Col4" + #LF$ + "01100")
         AddGadgetItem(#list, -1, "Col0" + #LF$ + "Col1" + #LF$ + "Col2" + #LF$ + "Col3" + #LF$ + "Col4" + #LF$ + "01001")
      Next
      
      ListIconGadget(#list2, 680, 10, 300, 300, "Col0", 66, #LVS_OWNERDRAWFIXED|#LVS_NOCOLUMNHEADER|#PB_ListIcon_GridLines|#PB_ListIcon_MultiSelect )
      AddGadgetColumn(#list2, 1, "Col1", 95)
      AddGadgetColumn(#list2, 2, "Col2", 115)
      AddGadgetColumn(#list2, 3, "Data", 0)
      
      LvCheckbox_SetColumn(#list2, 1)      
      LvCheckbox_SetColumn(#list2, 2)
      
      For j = 0 To 23
         AddGadgetItem(#list2, -1, "Hans" + #LF$ + "Eier" + #LF$ + "Bananen" + #LF$ + "001")
         AddGadgetItem(#list2, -1, "Otto" + #LF$ + "Grünkohl" + #LF$ + "Äpfel" + #LF$ + "011")
         AddGadgetItem(#list2, -1, "Werner" + #LF$ + "Käse" + #LF$ + "Birnen" + #LF$ + "010")
      Next
      
      Repeat
         event = WaitWindowEvent()
         
         If event = #PB_Event_Gadget
            
            rowlv1 = GetGadgetState(#list)
            rowlv2 = GetGadgetState(#list2)
                        
            Select EventGadget()
               Case #list                  
                  If EventType() = #PB_EventType_ChangeCheckBox
                     Debug "State ist jetzt " + LvCheckBox_GetState(#list, rowlv1, EventData())
                  EndIf
                  
               Case #list2                  
                  If EventType() = #PB_EventType_ChangeCheckBox
                     Debug "State ist jetzt " + LvCheckBox_GetState(#list2, rowlv2, EventData())
                  EndIf
                  
               Case #button0
                  Debug LvCheckBox_GetState(#list, rowlv1, 0)
               Case #button1
                  Debug LvCheckBox_GetState(#list, rowlv1, 1)
               Case #button2
                  Debug LvCheckBox_GetState(#list, rowlv1, 2)
               Case #button3
                  Debug LvCheckBox_GetState(#list, rowlv1, 3)
               Case #button4
                  Debug LvCheckBox_GetState(#list, rowlv1, 4)
                  
            EndSelect
            
         EndIf
         
      Until event = #PB_Event_CloseWindow
      
   EndIf
   
EndProcedure  
Main()