ListIconGadget Spaltenüberschrift zentrieren

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: ListIconGadget Spaltenüberschrift zentrieren

Beitrag von Shardik »

Lord hat geschrieben:Ich sehe da keinen zentrierten Text im ColumnHeader.
"Select *NMCustomDraw\dwDrawStage" hat nie den Wert "#CDDS_ITEMPREPAINT".
Deine Analyse ist leider korrekt. Bei Kompilierung mit 64 Bit wird zwar ein Header-Handle in *NMHeader\hdr\hwndFrom erkannt und in Case #CDDS_PREPAINT wird #CDRF_NOTIFYITEMDRAW zurückgegeben, aber Case #CDDS_ITEMPREPAINT wird dann in einem zweiten Durchgang nicht mehr aufgerufen, sodass keine Zentrierung erfolgt. Eine Überprüfung der in PB definierten Strukturen NMHDR, NMHEADER und NMCUSTOMDRAW ergab keinen Anhaltspunkt für einen Fehler...

Auf Windows 10 V1809 x64 mit PB 5.46 x86 im ASCII- und Unicode-Modus und mit PB 5.71 x86 funktioniert mein Beispiel mit WindowCallback hingegen einwandfrei.
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: ListIconGadget Spaltenüberschrift zentrieren

Beitrag von Shardik »

Shardik hat geschrieben:Bei Kompilierung mit 64 Bit wird zwar ein Header-Handle in *NMHeader\hdr\hwndFrom erkannt und in Case #CDDS_PREPAINT wird #CDRF_NOTIFYITEMDRAW zurückgegeben, aber Case #CDDS_ITEMPREPAINT wird dann in einem zweiten Durchgang nicht mehr aufgerufen, sodass keine Zentrierung erfolgt.
Leider scheint dieses Problem an einem Bug in Windows x64 zu liegen, wenn man einen Window Callback verwendet. Bei dem von mir schon gezeigten Subclassing des ListIconGadget tritt dieser Fehler bei 64-Bit Kompilierung dagegen nicht auf.

Ich musste daher in einem WindowCallback den Alternativweg einschlagen, statt nur den Text in einer Titelzelle zu zentrieren, die ganze Spalte zu zentrieren und alle Zelleinträge (mit Ausnahme der Titelzelle) linksbündig auszugeben. Leider bietet das Win32 ListView Control keine native Möglichkeit, nur den Text einer Titelzelle oder einer einzelnen Zelle zu zentrieren.

Ich habe das folgende WindowCallback-Beispiel erfolgreich auf folgenden Windows-Versionen getestet:
  • Windows XP SP1 mit PB 5.71 x86
  • Windows 7 SP1 x64 mit PB 5.71 x86 und x64
  • Windows 8.1 x64 mit PB 5.71 x86 und x64
  • Windows 10 x64 V1809 mit PB 5.46 x86 und x64 im ASCII- und Unicode-Modus und PB 5.71 x86 und x64

Code: Alles auswählen

EnableExplicit

#ColumnOfCenteredHeader = 1

Define HeaderItem.HDITEM
Define HeaderHandle.I

Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
  Protected Brush.I
  Protected CellText.S
  Protected Column.I
  Protected LVHitTestInfo.LVHITTESTINFO
  Protected *NMLVCustomDraw.NMLVCUSTOMDRAW
  Protected *NMHdr.NMHDR
  Protected Rectangle.RECT
  Protected Result.I = #PB_ProcessPureBasicEvents
  Protected Row.I

  If Msg = #WM_NOTIFY
    *NMHdr = LParam
    
    If *NMHdr\hwndFrom = GadgetID(0)
      If *NMHdr\code = #NM_CUSTOMDRAW
        *NMLVCustomDraw = LParam
        Column = *NMLVCustomDraw\iSubItem
        
        Select *NMLVCustomDraw\nmcd\dwDrawStage
          Case #CDDS_PREPAINT
            If Column = #ColumnOfCenteredHeader And Column <> 0
              Result = #CDRF_NOTIFYITEMDRAW
            EndIf
          Case #CDDS_ITEMPREPAINT
            Result = #CDRF_NOTIFYSUBITEMDRAW
          Case #CDDS_SUBITEMPREPAINT
            Row = *NMLVCustomDraw\nmcd\dwItemSpec
            CellText = GetGadgetItemText(0, Row, Column)
            LVHitTestInfo\iItem = Row
            LVHitTestInfo\iSubItem = Column
            Rectangle\top = Column
            SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, LVHITTESTINFO\iItem,
              Rectangle)
            Rectangle\right = Rectangle\left + SendMessage_(GadgetID(0),
              #LVM_GETSTRINGWIDTH, 0, @CellText) + 8

            If Column = 0
              ; ----- Detect if row is selected and highlight cell if yes

              If GetGadgetItemState(0, Row)
                Brush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
              Else
                Brush = CreateSolidBrush_(#White)
              EndIf

              FillRect_(*NMLVCustomDraw\nmcd\hdc, @Rectangle, Brush)
              DeleteObject_(Brush)
            EndIf

            ; ----- Draw left justified text into cell

            Rectangle\left + 5
            DrawText_(*NMLVCustomDraw\nmcd\hdc, @CellText, Len(CellText),
              Rectangle, #DT_LEFT | #DT_VCENTER | #DT_SINGLELINE)
            Result = #CDRF_SKIPDEFAULT
        EndSelect
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn Result
EndProcedure

OpenWindow(0, 200, 100, 400, 100,
  "ListIconGadget mit zentriertem Titeltext in 2.Spalte")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20,
  "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0,
  #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

; ----- Center text in specified header and column
HeaderHandle = SendMessage_(GadgetID(0), #LVM_GETHEADER, 0, 0)
HeaderItem\mask = #HDI_FORMAT
HeaderItem\fmt = #HDF_STRING | #HDF_CENTER
SendMessage_(HeaderHandle, #HDM_SETITEM , #ColumnOfCenteredHeader, @HeaderItem)

; ----- Initialize window callback
SetWindowCallback(@WindowCallback(), 0)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Benutzeravatar
Velindos
Beiträge: 598
Registriert: 15.11.2010 10:56

Re: ListIconGadget Spaltenüberschrift zentrieren

Beitrag von Velindos »

Hallo,
habe deinen Vorschlag "Dankend" aufgenommen und versucht ihn zu integrieren!

Nun, wenn ich auf Globale mit "#PB_Any" umstelle, gibt es Probleme, siehe Code!

Code: Alles auswählen

EnableExplicit
Enumeration
  ;   Work_L_ListIcon
EndEnumeration
Global MyWindow
Global Work_L_ListIcon
#ColumnOfCenteredHeader = 1

Define HeaderItem.HDITEM
Define HeaderHandle.I

Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
  Protected Brush.I
  Protected CellText.S
  Protected Column.I
  Protected LVHitTestInfo.LVHITTESTINFO
  Protected *NMLVCustomDraw.NMLVCUSTOMDRAW
  Protected *NMHdr.NMHDR
  Protected Rectangle.RECT
  Protected Result.I = #PB_ProcessPureBasicEvents
  Protected Row.I
  
  If Msg = #WM_NOTIFY
    *NMHdr = LParam
    
    If *NMHdr\hwndFrom = GadgetID(Work_L_ListIcon)
      If *NMHdr\code = #NM_CUSTOMDRAW
        *NMLVCustomDraw = LParam
        Column = *NMLVCustomDraw\iSubItem
        
        Select *NMLVCustomDraw\nmcd\dwDrawStage
          Case #CDDS_PREPAINT
            If Column = #ColumnOfCenteredHeader And Column <> 0
              Result = #CDRF_NOTIFYITEMDRAW
            EndIf
          Case #CDDS_ITEMPREPAINT
            Result = #CDRF_NOTIFYSUBITEMDRAW
          Case #CDDS_SUBITEMPREPAINT
            Row = *NMLVCustomDraw\nmcd\dwItemSpec
            CellText = GetGadgetItemText(Work_L_ListIcon, Row, Column)
            LVHitTestInfo\iItem = Row
            LVHitTestInfo\iSubItem = Column
            Rectangle\top = Column
            SendMessage_(GadgetID(Work_L_ListIcon), #LVM_GETSUBITEMRECT, LVHITTESTINFO\iItem,
                         Rectangle)
            Rectangle\right = Rectangle\left + SendMessage_(GadgetID(Work_L_ListIcon),
                                                            #LVM_GETSTRINGWIDTH, 0, @CellText) + 8
            
            If Column = 0
              ; ----- Detect if row is selected and highlight cell if yes
              
              If GetGadgetItemState(Work_L_ListIcon, Row)
                Brush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
              Else
                Brush = CreateSolidBrush_(#White)
              EndIf
              
              FillRect_(*NMLVCustomDraw\nmcd\hdc, @Rectangle, Brush)
              DeleteObject_(Brush)
            EndIf
            
            ; ----- Draw left justified text into cell
            
            Rectangle\left + 5
            DrawText_(*NMLVCustomDraw\nmcd\hdc, @CellText, Len(CellText),
                      Rectangle, #DT_LEFT | #DT_VCENTER | #DT_SINGLELINE)
            Result = #CDRF_SKIPDEFAULT
        EndSelect
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn Result
EndProcedure

MyWindow = OpenWindow(#PB_Any, 200, 100, 400, 100,
                      "ListIconGadget mit zentriertem Titeltext in 2.Spalte")
Work_L_ListIcon = ListIconGadget(#PB_Any, 10, 10, WindowWidth(MyWindow) - 20, WindowHeight(MyWindow) - 20,
                                 "Name", 110, #PB_ListIcon_GridLines)
AddGadgetColumn(Work_L_ListIcon, 1, "Address", GadgetWidth(Work_L_ListIcon) - GetGadgetItemAttribute(Work_L_ListIcon, 0,  #PB_ListIcon_ColumnWidth) - 4)
AddGadgetItem(Work_L_ListIcon, -1, "Harry Rannit" + #LF$ +
                                   "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(Work_L_ListIcon, -1, "Ginger Brokeit" + #LF$ +
                                   "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(Work_L_ListIcon, -1, "Didi Foundit" + #LF$ +
                                   "321 Logo Drive, Mouse House, Downtown")
SetGadgetColor(Work_L_ListIcon,#PB_Gadget_FrontColor, $808000)
SetGadgetColor(Work_L_ListIcon, #PB_Gadget_BackColor, $DBFAFA) 

; ----- Center text in specified header and column

HeaderHandle = SendMessage_(GadgetID(Work_L_ListIcon), #LVM_GETHEADER, 0, 0)
HeaderItem\mask = #HDI_FORMAT
HeaderItem\fmt = #HDF_STRING | #HDF_CENTER
SendMessage_(HeaderHandle, #HDM_SETITEM , #ColumnOfCenteredHeader, @HeaderItem)

; ----- Initialize window callback
SetWindowCallback(@WindowCallback(), Work_L_ListIcon)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Wenn ich die Constanten verwende und meinen Code gebe und übers Listicon fahre wird die Zeile mit weiss hinterlegt...

Gruss ... Velindos!
Windows 7/8/8.1/10 (32/64-Bit) |Ubuntu 10.4 (64-Bit) |Purebasic 5.71 LTS (32/64-Bit)
Benutzeravatar
HeX0R
Beiträge: 2954
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: ListIconGadget Spaltenüberschrift zentrieren

Beitrag von HeX0R »

SetWindowCallback(@WindowCallback(), MyWindow)
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: ListIconGadget Spaltenüberschrift zentrieren

Beitrag von Shardik »

Zusätzlich solltest Du im WindowCallback die Hintergrundfarbe anpassen von

Code: Alles auswählen

                Brush = CreateSolidBrush_(#White)
nach

Code: Alles auswählen

                Brush = CreateSolidBrush_($DBFAFA)
Benutzeravatar
Velindos
Beiträge: 598
Registriert: 15.11.2010 10:56

Re: ListIconGadget Spaltenüberschrift zentrieren

Beitrag von Velindos »

Hallo Leute,
und schon läuft er! DANKE!

Gruss ... Velindos!
Windows 7/8/8.1/10 (32/64-Bit) |Ubuntu 10.4 (64-Bit) |Purebasic 5.71 LTS (32/64-Bit)
Antworten