will man auch die Liste selbst ändern , geschieht dies in der Regel in einem MainCallback, das Prinzip ist gleich.
für eigene Anwendungen müssen natürlich Farben, Ausrichtung etc angepasst werden.
In diesem Beispiel werden nur die Grundfunktionen gezeigt. Mehr geht immer.
Ich empfehle für jede Liste einen eigenen Callback, das macht die Wartung übersichtlicher.
Code: Alles auswählen
;Demo Header Ownerdraw !!! by HJBremer Windows 10 + PB 5.70 x86 + PB 5.72 + 6.00 Beta 5 x64
;RightClick zeigt Spaltenbreite an
;EnableExplicit
#window = 10
#liste1 = 20
#liste2 = 30
UseJPEGImageDecoder()
Global headimgid1 = LoadImage(1, #PB_Compiler_Home + "Examples\3D\Data\Textures\snow_1024.jpg")
Global headimgid2 = LoadImage(2, #PB_Compiler_Home + "Examples\3D\Data\Textures\clouds.jpg")
Global fontStd  = LoadFont(#PB_Any, "Tahoma", 11)
Global fontmini = LoadFont(#PB_Any, "Arial", 10)
Global fontBold = LoadFont(#PB_Any, "Arial", 11, #PB_Font_Bold)
Procedure.i ListIconRedraw(pbnr, flag)
   ;für Daten laden, sonst wird bei jedem AddItem neu gezeichnet und das sieht sch... aus 
   ;flag: #False oder #True (0 oder 1)
   SendMessage_(GadgetID(pbnr), #WM_SETREDRAW, flag, 0)
   If flag: InvalidateRect_(GadgetID(pbnr), 0, #True): EndIf  
EndProcedure
Procedure.i ListIconSetAlign(pbnr, col, align)
   ;Align: #LVCFMT_CENTER, #LVCFMT_LEFT, #LVCFMT_RIGHT
   Protected lv.LV_COLUMN\mask = #LVCF_FMT : lv\fmt = align 
   Select align
      Case #PB_Text_Right: lv\fmt = #LVCFMT_RIGHT
      Case #PB_Text_Center: lv\fmt = #LVCFMT_CENTER
   EndSelect 
   SendMessage_(GadgetID(pbnr), #LVM_SETCOLUMN, col, lv)    
EndProcedure
Procedure.i ListIconGetHeaderItem(header)
   ;wo ist die Maus im Header ? wird im Callback gebraucht
   Protected hdhit.HD_HITTESTINFO   
   GetCursorPos_(hdhit\pt)
   ScreenToClient_(header, hdhit\pt) 
   SendMessage_(header,#HDM_HITTEST,0, hdhit)
   ProcedureReturn hdhit\iItem 
EndProcedure
;-
Procedure.i Liste1_Callback(hwnd, msg, wParam, lParam)  
   ;hwnd ist GadgetId eines ListIcongadgets   
   ;hier wird nur der Header verarbeitet, manch anderes ist natürlich auch möglich 
   
   Static showWidthFlag 
   
   Protected *nmhdr.NMHDR, *nmcd.NMCUSTOMDRAW, hditem.HDITEM, size.SIZE
   
   Protected column, hitcol, backbrush, brush, align, text$, t1$, t2$ 
   
   Protected drawtextflags = #DT_END_ELLIPSIS|#DT_VCENTER|#DT_SINGLELINE
   
   Protected headerBackColor = $FFFFB9, headerhitcolor = $90FFAA ;$DFFFFF $C4CAA7 $90F355
   
   Protected pbnr = GetDlgCtrlID_(hwnd)         ;z.B. #liste1   
   Protected oldptr = GetProp_(hwnd, @"Liste1") ;siehe auch SetCallback
   Protected result = CallWindowProc_(oldptr, hwnd, msg, wParam, lParam)
   
   If msg = #WM_NCDESTROY : RemoveProp_(hwnd, @"Liste1") ;Liste wird zerstört, Prop löschen
   
   ElseIf msg = #WM_NOTIFY      
      *nmhdr = LParam
      
      If *nmhdr\code = #NM_CUSTOMDRAW  ;nur für Header; Customdraw für Liste im MainCallback         
         *nmcd = LParam                ;:Debug "headerhwnd = " + *nmcd\hdr\hwndFrom  
         
         With *nmcd
            
            Select \dwDrawStage
               Case #CDDS_PREPAINT: ProcedureReturn #CDRF_NOTIFYITEMDRAW                  
               Case #CDDS_ITEMPREPAINT
                  
                  column = \dwItemSpec : ;Debug "Col: "+column    ;HeaderColumn, ist besser zu lesen
                  
                  ;Background, jede Column könnte eigene Farbe haben
                  hitcol = ListIconGetHeaderItem(\hdr\hwndFrom)     ;wo ist Maus für Highlight ?                  
                  backbrush = headerBackColor 
                  If column = 5: backbrush = #Red: EndIf               ;<--- andere Farbe
                  If hitcol = column: backbrush = headerhitcolor: EndIf 
                  brush = CreateSolidBrush_(backbrush)      ;SolidBrush erstellen für Background
                  FillRect_(\hdc, \rc, brush)                  
                  DeleteObject_(brush)                      ;Brush immer löschen 
                  
                  ;Rahmen darüber, ab column 1 rc\left-1 sonst optisch dicke Trennbalken
                  If column : \rc\left-0 : EndIf
                  brush = GetStockObject_(#LTGRAY_BRUSH)    ; StockObject braucht man nicht löschen
                  FrameRect_(\hdc, \rc, brush)              ; oder #DKGRAY_BRUSH                            
                  InflateRect_(\rc,-1,-1)                   ; Rechteck kleiner für Selected + Text           
                  If \uItemState & #CDIS_SELECTED = #CDIS_SELECTED   ; wenn Maus gedrückt
                     FrameRect_(\hdc, \rc, brush)                    
                  EndIf 
                  
                  ;Textfarbe + Font + align je nach Wunsch
                  SetTextColor_(\hdc, #Black)               ;Vorgabe Textfarbe
                  SelectObject_(\hdc, FontID(fontStd))      ;Vorgabe Textfont 
                  Select column                    
                     Case 0: SetTextColor_(\hdc, #Red)  
                     Case 1: align = #DT_CENTER
                     Case 2: SelectObject_(\hdc, FontID(fontBold)) 
                     Case 3: SetTextColor_(\hdc, #Blue) 
                     Case 4: SetTextColor_(\hdc, #Blue) : align = #DT_CENTER : SelectObject_(\hdc, FontID(fontmini))
                     Case 5: SetTextColor_(\hdc, #Yellow) : align = #DT_CENTER : SelectObject_(\hdc, FontID(fontmini))
                        If hitcol = 5: SetTextColor_(\hdc, #Blue): EndIf
                  EndSelect
                  
                  ;align = #DT_CENTER  ;alle zentriert wenn gewünscht (nur Header)
                  
                  ;TextAusrichtung holen, ausser align wurde oben gesetzt 
                  If align = 0
                     hditem\mask = #HDI_FORMAT
                     SendMessage_(\hdr\hwndFrom, #HDM_GETITEM, column, hditem)
                     If hditem\fmt & #HDF_RIGHT : align = #DT_RIGHT : EndIf   ; Drawtext Konstanten haben 
                     If hditem\fmt & #HDF_CENTER : align = #DT_CENTER : EndIf ; andere Werte als Header                              
                  EndIf                     
                  
                  ;da Text durch Brush übermalt, Text holen + neu schreiben
                  text$ = GetGadgetItemText(pbnr, -1, column)  ;Text aus Header holen
                  
                  \rc\top + 1     ; oberer Rand
                  \rc\left + 7    ; linker Rand 
                  \rc\right - 7   ; rechter Rand 
                  
                  If showWidthFlag  ;Spaltenbreite anzeigen, gesetzt durch RightClick im Header
                     text$ = Str(column) + ", " + Str(SendMessage_(hwnd, #LVM_GETCOLUMNWIDTH, column, 0))
                     align = 0: \rc\left - 4: \rc\right + 6                     
                  EndIf 
                  
                  ;Text                           
                  SetBkMode_(\hdc, #TRANSPARENT)                           
                  
                  If FindString(text$, #LF$)
                     DrawText_(\hdc, @text$, Len(text$), \rc, #DT_END_ELLIPSIS|align)
                  Else 
                     If column = 2
                        t1$ = StringField(text$,1,",") + " "
                        t2$ = StringField(text$,2,",") + " "
                        DrawText_(\hdc, @t1$, Len(t1$), \rc, drawtextflags)
                        GetTextExtentPoint32_(\hdc, @t1$, Len(t1$), size)
                        \rc\left + size\cx: \rc\top - 2
                        SetBkMode_(\hdc, #OPAQUE)
                        SetBkColor_(\hdc, #Yellow)
                        SetTextColor_(\hdc, #Gray) 
                        SelectObject_(\hdc, FontID(fontStd))
                        DrawText_(\hdc, @t2$, Len(t2$), \rc, drawtextflags)
                     Else
                        DrawText_(\hdc, @text$, Len(text$), \rc, drawtextflags|align)                                 
                     EndIf   
                  EndIf                           
                  
                  ProcedureReturn #CDRF_SKIPDEFAULT
                  
            EndSelect           ;von Select \dwDrawStage 
         EndWith                ;von *nmcd
         
      ElseIf *nmhdr\code = #HDN_BEGINTRACK      : ;Debug "#HDN_BEGINTRACK"         
      ElseIf *nmhdr\code = #HDN_ENDTRACK        : ;Debug "#HDN_ENDTRACK"
         
      ElseIf *nmhdr\code = #NM_RCLICK           : ;Debug "#NM_RCLICK"  
         CompilerIf #PB_Compiler_Debugger       ; -> weglassen wenn es in die Exedatei soll          
            showWidthFlag ! 1                   ; XOR: 0 ! 1 = 1 ; 1 ! 1 = 0
            InvalidateRect_(hwnd, 0, #True)     ; erzwingt Neuzeichnen der Liste 
            If showWidthFlag = 0            
               Debug "Liste: " + pbnr
               For column = 0 To GetGadgetAttribute(pbnr, #PB_ListIcon_ColumnCount) - 1
                  Debug "Col: " + Str(column) + " = " + GetGadgetItemAttribute(pbnr, 0, #PB_ListIcon_ColumnWidth, column)
               Next
            EndIf
         CompilerEndIf
         
      ElseIf *nmhdr\code = #HDN_ITEMCLICK       : ;Debug "#HDN_ITEMCLICK"   ; hier ev. Sortieren
      ElseIf *nmhdr\code = #HDN_ITEMDBLCLICK    : ;Debug "#HDN_ITEMDBLCLICK"         
      ElseIf *nmhdr\code = #HDN_ITEMCHANGING    : ;Debug "#HDN_ITEMCHANGING"         
      ElseIf *nmhdr\code = #HDN_ITEMCHANGED     : ;Debug "#HDN_ITEMCHANGED"
      ElseIf *nmhdr\code = #NM_RELEASEDCAPTURE  : ;Debug "#NM_RELEASEDCAPTURE"
         
      ElseIf *nmhdr\code = #HDN_ENDDRAG         : ;Debug "#HDN_ENDDRAG"
      ElseIf *nmhdr\code = #HDN_BEGINDRAG       : ;Debug "#HDN_BEGINDRAG"         
      ElseIf *nmhdr\code = -316                 : ;Debug "#HDN_ITEMSTATEICONCLICK"   
      ElseIf *nmhdr\code = -530                 : ;Debug "Tooltip Info ?"         
      ElseIf *nmhdr\code = -23                  : ;unbekannt
         
      Else : Debug "sonstige hdrcodes Liste1 " + *nmhdr\code         
      EndIf  ;von *nmhdr\code = #NM_CUSTOMDRAW
      
   Else     ;: Debug msg
   EndIf    ;von Msg 
   
   ProcedureReturn result
EndProcedure
Procedure.i Liste2_Callback(hwnd, msg, wParam, lParam)  
   ;hwnd ist GadgetId eines ListIcongadgets   
   ;hier wird nur der Header verarbeitet 
   
   Protected *nmhdr.NMHDR, *nmcd.NMCUSTOMDRAW, hditem.HDITEM, size.SIZE
   
   Protected column, hitcol, backbrush, brush, align, text$, t1$, t2$ 
   
   Protected drawtextflags = #DT_END_ELLIPSIS|#DT_VCENTER|#DT_SINGLELINE
   
   Protected pbnr = GetDlgCtrlID_(hwnd)         ;z.B. #liste2   
   Protected oldptr = GetProp_(hwnd, @"Liste2") ;
   Protected result = CallWindowProc_(oldptr, hwnd, msg, wParam, lParam)
   
   If msg = #WM_NCDESTROY : RemoveProp_(hwnd, @"Liste2") ;Liste wird zerstört, Prop löschen
   
   ElseIf msg = #WM_NOTIFY      
      *nmhdr = LParam
      
      If *nmhdr\code = #NM_CUSTOMDRAW  ;nur für Header; Customdraw für Liste im MainCallback         
         *nmcd = LParam                ;:Debug "headerhwnd = " + *nmcd\hdr\hwndFrom  
         
         With *nmcd
            
            Select \dwDrawStage
               Case #CDDS_PREPAINT: ProcedureReturn #CDRF_NOTIFYITEMDRAW                  
               Case #CDDS_ITEMPREPAINT
                  
                  column = \dwItemSpec : ;Debug "Col: "+column    ;HeaderColumn, ist besser zu lesen
                  
                  ;Background, jede Column könnte eigene Farbe/Brush haben
                  hitcol = ListIconGetHeaderItem(\hdr\hwndFrom)      ;wo ist Maus für Highlight ?
 
                  backbrush = headimgid1 
                  If hitcol = column: backbrush = headimgid2: EndIf 
                  brush = CreatePatternBrush_(backbrush)    ;Brush erstellen für Background
                  FillRect_(\hdc, \rc, brush)                  
                  DeleteObject_(brush)                      ;Brush immer löschen 
                  
                  ;Rahmen darüber, ab column 1 rc\left-1 sonst optisch dicke Trennbalken
                  If column : \rc\left-1 : EndIf
                  brush = GetStockObject_(#GRAY_BRUSH)      ; StockObject braucht man nicht löschen
                  FrameRect_(\hdc, \rc, brush)              ; oder #DKGRAY_BRUSH                            
                  InflateRect_(\rc,-2,-2)                   ; Rechteck kleiner für Selected + Text           
                  If \uItemState & #CDIS_SELECTED = #CDIS_SELECTED   ; wenn Maus gedrückt
                     FrameRect_(\hdc, \rc, brush)                    
                  EndIf 
                  
                  ;Textfarbe + Font + align je nach Wunsch
                  SetTextColor_(\hdc, #Black)               ;Vorgabe Textfarbe
                  SelectObject_(\hdc, FontID(fontStd))      ;Vorgabe Textfont 
                  Select column                    
                     Case 0: SetTextColor_(\hdc, #Red) 
                     Case 1: SelectObject_(\hdc, FontID(fontBold))
                     Case 3: SetTextColor_(\hdc, #Blue)                        
                  EndSelect
                  
                  ;align = #DT_CENTER  ;alle zentriert wenn gewünscht (nur Header)
                  
                  ;TextAusrichtung holen, ausser align wurde oben gesetzt 
                  If align = 0
                     hditem\mask = #HDI_FORMAT
                     SendMessage_(\hdr\hwndFrom, #HDM_GETITEM, column, hditem)
                     If hditem\fmt & #HDF_RIGHT : align = #DT_RIGHT : EndIf   ; Drawtext Konstanten haben 
                     If hditem\fmt & #HDF_CENTER : align = #DT_CENTER : EndIf ; andere Werte als Header                              
                  EndIf                     
                  
                  ;da Text durch Brush übermalt, Text holen + neu schreiben
                  text$ = GetGadgetItemText(pbnr, -1, column)  ;Text aus Header holen
                  
                  \rc\top + 1     ; oberer Rand
                  \rc\left + 7    ; linker Rand 
                  \rc\right - 7   ; rechter Rand 
                  
                  ;Text                           
                  SetBkMode_(\hdc, #TRANSPARENT)                           
                  
                  If FindString(text$, #LF$)
                     DrawText_(\hdc, @text$, Len(text$), \rc, #DT_END_ELLIPSIS|align)
                  Else 
                     If column = 2
                        t1$ = StringField(text$,1,",") + " "
                        t2$ = StringField(text$,2,",") + " "
                        SetTextColor_(\hdc, #Blue)                        
                        DrawText_(\hdc, @t1$, Len(t1$), \rc, drawtextflags)
                        GetTextExtentPoint32_(\hdc, @t1$, Len(t1$), size)
                        \rc\left + size\cx: \rc\top - 2
                        SetTextColor_(\hdc, #Magenta)
                        DrawText_(\hdc, @t2$, Len(t2$), \rc, drawtextflags)
                     Else
                        DrawText_(\hdc, @text$, Len(text$), \rc, drawtextflags|align)                                 
                     EndIf   
                  EndIf                           
                  
                  ProcedureReturn #CDRF_SKIPDEFAULT
                  
            EndSelect           ;von Select \dwDrawStage 
         EndWith                ;von *nmcd
         
      ElseIf *nmhdr\code = #NM_RCLICK           ;: Debug "#NM_RCLICK"
      ElseIf *nmhdr\code = #HDN_ITEMCLICK       : ;Debug "#HDN_ITEMCLICK"   ; hier ev. Sortieren
         
      Else : ;Debug "sonstige hdrcodes " + *nmhdr\code         
      EndIf  ;von *nmhdr\code = #NM_CUSTOMDRAW 
   EndIf     ;von Msg 
   
   ProcedureReturn result
EndProcedure
Procedure.i Listen_SetCallback(pbnr)   
   
   Protected oldpointer, pbid = GadgetID(pbnr)
   Protected headerfont, header = SendMessage_(pbid, #LVM_GETHEADER, 0, 0)
   SetWindowTheme_(pbid, @"Explorer", 0)       ;sieht besser aus   
   
   SetGadgetFont(pbnr, FontID(fontStd))        ;muß vor Set Headerfont stehen !!!!
   SetGadgetColor(pbnr, #PB_Gadget_BackColor, $D5FFFF)  ;$FDE6BD, $DFFFFF
   
   Select pbnr
      Case #liste1: 
         headerfont = LoadFont(#PB_Any, "Arial", 20)
         oldpointer = SetWindowLongPtr_(pbid, #GWL_WNDPROC,  @Liste1_Callback())
         SetProp_(pbid, @"Liste1", oldpointer) ;subclassing ListIconGadget
         
      Case #liste2: 
         headerfont = LoadFont(#PB_Any, "Arial", 14)
         oldpointer = SetWindowLongPtr_(pbid, #GWL_WNDPROC,  @Liste2_Callback())
         SetProp_(pbid, @"Liste2", oldpointer)
         SetGadgetColor(pbnr, #PB_Gadget_LineColor, #Gray) 
   
   EndSelect
   
   ;Font bestimmt die Höhe des Headers, im ListIconCallback muß man dann Font ändern !!!
   ;via Setfont ist sehr viel einfacher, als mit HDLayout
   
   SendMessage_(header, #WM_SETFONT, FontID(headerfont), #True): FreeFont(headerfont)
   
EndProcedure
Define j, nr = 1000
Define listiconflag = #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_HeaderDragDrop
OpenWindow(#window, 300, 50, 800, 700, "ListIconGadget header callback")
ListIconGadget(#liste1, 10, 10, 780, 400, "Check", 60, listiconflag)
AddGadgetColumn(#liste1, 1, "Name", 110)
AddGadgetColumn(#liste1, 2, "Addresse, Straße", 300)
AddGadgetColumn(#liste1, 3, "Zahl", 55)
AddGadgetColumn(#liste1, 4, "Nummer", 70)
AddGadgetColumn(#liste1, 5, "Preis kg" + #LF$ + "Euro", 70)
AddGadgetColumn(#liste1, 6, "Menge", 83)
ListIconSetAlign(#liste1, 3, #PB_Text_Right) 
ListIconSetAlign(#liste1, 4, #PB_Text_Center)
ListIconSetAlign(#liste1, 5, #PB_Text_Right)
ListIconSetAlign(#liste1, 6, #PB_Text_Center)
Listen_SetCallback(#liste1)
;Daten laden 
ListIconRedraw(#liste1, 0)    
For j = 1 To 40
   nr + 1:AddGadgetItem(#liste1, -1, "Test" + #LF$ + "Harry Rannit" + #LF$ + "12 Parliament Way, Battle  " + #LF$ + Str(nr) + #LF$ + Str(j) + #LF$ + "333,44")
   nr + 1:AddGadgetItem(#liste1, -1, "Test" + #LF$ + "Ginger Broke" + #LF$ + "130 PureBasic Road, BigTown" + #LF$ + Str(nr) + #LF$ + Str(j) + #LF$ + "33,44" + #LF$ + Str(j))
Next
ListIconRedraw(#liste1, 1)
;Liste 2 ohne ReDraw 
ListIconGadget(#liste2, 10, 420, 450, 220, "Nummer", 80, listiconflag)
AddGadgetColumn(#liste2, 1, "Ort", 115)
AddGadgetColumn(#liste2, 2, "Name, Vorname", 150)
AddGadgetColumn(#liste2, 3, "Telefon", 83)
ListIconSetAlign(#liste2, 0, #PB_Text_Center) 
ListIconSetAlign(#liste2, 3, #PB_Text_Right) 
Listen_SetCallback(#liste2)
For j = 1 To 20 ;zum Testen 200
   AddGadgetItem(#liste2, -1, "22255" + #LF$ + "Hamburg" + #LF$ + "Maier, Otto" + #LF$ + "445588")
   AddGadgetItem(#liste2, -1, "24534" + #LF$ + "Neumünster" + #LF$ + "Meier, Bernd" + #LF$ + "33444") 
Next
Repeat
   Define Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow



 
 


