That's nice Sparkie.
Custom drawing the header control was always going to be a little quicker.
However, whilst I understand the need for the array to store the text for the header cells (because of the quirks with custom draw), I have nevertheless tried to remove that requirement to save the bother of updating the array everytime a column is added or deleted etc.
However, this turns out to be harder than I would like.
It would seem that in order to prevent the control from painting the text itself, we need to do all custom drawing within the #CDDS_ITEMPREPAINT message. This also requires that I need to paint more than I would like, e.g. the resizing border.
The following 'nearly' does the job, although the header cells are no longer highlighted etc. (a relatively minor problem). But see what happens when you resize a column; keep an eye on the bottom right of the header control!
I've tried returning to the #CDDS_ITEMPOSTPAINT message and tried to disguise the font etc. - No success there, although this would be the best way out!
Code: Select all
; ************************************************
; Code: Centered text in ListIconGadget Header
; Author: Sparkie (inspired by PB and srod)
; Date: December 31, 2005
; OS: Windows only
; ************************************************
; ************************************************
; Constants
; ************************************************
; //////////////////////////////////
; CustomDraw drawing stage
; //////////////////////////////////
#CDDS_ITEM = $10000
#CDDS_PREPAINT = 1
#CDDS_POSTPAINT = 2
#CDDS_ITEMPOSTPAINT = #CDDS_ITEM | #CDDS_POSTPAINT
#CDDS_ITEMPREPAINT = #CDDS_ITEM | #CDDS_PREPAINT
; //////////////////////////////////
; CustomDraw return values
; //////////////////////////////////
#CDRF_DODEFAULT = 0
#CDRF_SKIPDEFAULT = 4
#CDRF_NOTIFYITEMDRAW = $20
#CDRF_NOTIFYPOSTPAINT = $10
; //////////////////////////////////
; DrawText flags
; //////////////////////////////////
#DT_END_ELLIPSIS = $8000
; //////////////////////////////////
; ListIcon messaging
; //////////////////////////////////
#LVM_GETHEADER = #LVM_FIRST + 31
; ************************************************
; Globals, Arrays
; ************************************************
; //////////////////////////////////
; Globals
; //////////////////////////////////
Global oldListIconCallback
;Function which returns the text from the specified header item.
Procedure.s GetHeaderText(Gadget,index)
Protected temp$,lvc.LV_COLUMN
temp$=Space(255)
lvc\mask = #LVCF_TEXT
lvc\pszText = @temp$
lvc\cchTextMax = 255
SendMessage_(GadgetID(Gadget),#LVM_GETCOLUMN,index,@lvc)
ProcedureReturn PeekS(lvc\pszText)
EndProcedure
; ************************************************
; Procedures
; ************************************************
; //////////////////////////////////
; Proc for subclassed ListIconGadget
; //////////////////////////////////
Procedure SubclassedListIcon(hwnd, msg, wparam, lparam)
result = CallWindowProc_(oldListIconCallback, hwnd, msg, wparam, lparam)
Select msg
Case #WM_NOTIFY
*pnmh.NMHDR = lparam
;--> Get handle to ListIcon header control
hHeader = SendMessage_(hwnd, #LVM_GETHEADER, 0, 0)
If *pnmh\code = #NM_CUSTOMDRAW And *pnmh\hwndFrom = hHeader
*pnmcd.NMCUSTOMDRAW = lparam
;--> Determine drawing stage
Select *pnmcd\dwDrawStage
Case #CDDS_PREPAINT
result = #CDRF_NOTIFYITEMDRAW
Case #CDDS_ITEMPREPAINT
;--> Draw centered text to header
flags = #DT_CENTER | #DT_NOCLIP | #DT_SINGLELINE | #DT_VCENTER | #DT_END_ELLIPSIS
SetBkMode_(*pnmcd\hdc,#TRANSPARENT)
SetTextColor_(*pnmcd\hdc, #Black)
text$=GetHeaderText(0,*pnmcd\dwItemSpec)
DrawText_(*pnmcd\hdc, text$, Len(text$), *pnmcd\rc, flags)
;Draw border line.
pen=CreatePen_(#PS_SOLID,1,0)
hPenOld=SelectObject_(*pnmcd\hdc,pen);Replace old pen with new one.
MoveToEx_(*pnmcd\hdc,*pnmcd\rc\right,*pnmcd\rc\Top+2,0)
LineTo_(*pnmcd\hdc,*pnmcd\rc\right,*pnmcd\rc\bottom-2)
DeleteObject_(pen)
DeleteObject_(hPenOld)
result = #CDRF_SKIPDEFAULT
EndSelect
EndIf
EndSelect
ProcedureReturn result
EndProcedure
; //////////////////////////////////
; Proc for ListIcon column alignment
; //////////////////////////////////
Procedure AlignColumn(liGad, col, align)
liColumn.LV_COLUMN
liColumn\mask = #LVCF_FMT
liColumn\fmt = align
SendMessage_(liGad, #LVM_SETCOLUMN, col, liColumn)
EndProcedure
; ************************************************
; Main Window
; ************************************************
If OpenWindow(0, 100, 100, 415, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "ListIcon Header Text Centered") And CreateGadgetList(WindowID())
;--> I'll leave the header text Null and draw them in the subclass procedure
ListIconGadget(0, 5, 5, 405, 90, "Name", 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
AddGadgetColumn(0, 1, "Location", 200)
AddGadgetColumn(0, 2, "Posts", 100)
AddGadgetItem(0, -1, "PB" + Chr(10) + "4F7a" + Chr(10) + "2396")
AddGadgetItem(0, -1, "srod" + Chr(10) + "UK" + Chr(10) + "549")
AddGadgetItem(0, -1, "Sparkie" + Chr(10) + "Ohio, USA" + Chr(10) + "681")
;--> Set column alignment
AlignColumn(GadgetID(0), 0, #LVCFMT_LEFT)
AlignColumn(GadgetID(0), 1, #LVCFMT_CENTER)
AlignColumn(GadgetID(0), 2, #LVCFMT_RIGHT)
;--> Subclass ListIcon so we can customdraw the header text centered
oldListIconCallback = SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @SubclassedListIcon())
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
EndIf
End
Any ideas? I know you like a challenge as much as I!

I may look like a mule, but I'm not a complete ass.