MultiLines Header ListIcon

Share your advanced PureBasic knowledge/code with the community.
tatanas
Enthusiast
Enthusiast
Posts: 186
Joined: Wed Nov 06, 2019 10:28 am
Location: France

MultiLines Header ListIcon

Post by tatanas »

Hi,

I was looking for a way to get multiple lines in a ListiconGadget header. I found a code on AutoIt forum and adapted it.
Here is an example :

Code: Select all

Global oldListIconCallback, hHeader
Global g_hHdrFont

Global ColumnHeaderTitle_LeftMargin = 4
Global ColumnHeaderTitle_TopMargin = 2
Global ColumnHeaderTitle_Height_Offset = 14
Global Column_Count = 4
Global Dim array_ColumnHeaderTitle.s(Column_Count - 1)


array_ColumnHeaderTitle(0) = "Title line 1" + Chr(10) + "Title line 2"
array_ColumnHeaderTitle(1) = "Title line 1"
array_ColumnHeaderTitle(2) = "Title line 1" + Chr(10) + "Title line 2" + Chr(10) + "Title line 3"
array_ColumnHeaderTitle(3) = "Title line 1" + Chr(10) + "Title line 2"


Procedure Header_SetItemHeightByFont(hHeader, iHeight, FontName.s = "Arial", bRestoreTheme = #True)

	; Remove Header theme
	SetWindowTheme_(hHeader, @null.w, @null.w)

	Protected hDC = GetDC_(hHeader)
	Protected hFont = SendMessage_(hHeader, #WM_GETFONT, 0, 0)
	Protected hObject = SelectObject_(hDC, hFont)

	Protected lvLogFont.LOGFONT
	GetObject_(hFont, SizeOf(lvLogFont), @lvLogFont)
	Protected hHdrfont = CreateFontIndirect_(lvLogFont) ; Original Header font

	SelectObject_(hDC, hObject)
	ReleaseDC_(hHeader, hDC)

	; Set height of Header items by applying text font with suitable height
	hFont = CreateFont_(iHeight, 0, 0, 0, #FW_NORMAL, #False, #False, #False, #DEFAULT_CHARSET, #OUT_DEFAULT_PRECIS, #CLIP_DEFAULT_PRECIS, #DEFAULT_QUALITY, 0, FontName)
	SendMessage_(hHeader, #WM_SETFONT, hFont, #True)
	DeleteObject_(hFont)

	; Return original Header font
	ProcedureReturn hHdrfont
EndProcedure


Procedure SubclassedListIcon(hWnd, uMsg, wParam, lParam)
	Protected result = CallWindowProc_(oldListIconCallback, hWnd, uMsg, wParam, lParam)
	Protected lines.i, field.s, i

	Select uMsg
		Case #WM_NOTIFY
			Protected *pnmh.NMHDR = lparam
			;--> Get handle to ListIcon header control

			If *pnmh\hwndFrom = hHeader
				If *pnmh\code = #NM_CUSTOMDRAW
					Protected *pnmcd.NMCUSTOMDRAW = lparam
	
					;--> Determine drawing stage
					Select *pnmcd\dwDrawStage
						Case #CDDS_PREPAINT ; Before the paint cycle begins
							result = #CDRF_NOTIFYITEMDRAW  ; Notify parent window of any item related drawing operations
						Case #CDDS_ITEMPREPAINT ; Before an item is drawn: Default painting (frames and background)
							result = #CDRF_NOTIFYPOSTPAINT ; Notify parent window of any post item related drawing operations
	
						Case #CDDS_ITEMPOSTPAINT ; After an item is drawn: Custom painting (item texts)
							Protected iIndex = *pnmcd\dwItemSpec ; Item index
							Protected hDC = *pnmcd\hdc ; Device context
							SelectObject_(hDC, g_hHdrFont) ; Set text font
							SetBkMode_(hDC, #TRANSPARENT)	; Transparent background

							*pnmcd\rc\left  = *pnmcd\rc\left + ColumnHeaderTitle_LeftMargin ; Left margin
							*pnmcd\rc\top 	 = *pnmcd\rc\top  + ColumnHeaderTitle_TopMargin ; Top margin

							lines = CountString(array_ColumnHeaderTitle(iIndex), Chr(10)) + 1

							For i = 1 To lines
								field = StringField(array_ColumnHeaderTitle(iIndex), i, Chr(10))
								DrawText_(hDC, @field, Len(field), *pnmcd\rc, #DT_WORD_ELLIPSIS)
								*pnmcd\rc\top 	  = *pnmcd\rc\top 	+ ColumnHeaderTitle_Height_Offset ; Line top
								*pnmcd\rc\bottom = *pnmcd\rc\bottom + ColumnHeaderTitle_Height_Offset ; Line height
							Next

							ProcedureReturn #CDRF_NEWFONT ; CDRF_NEWFONT must be returned after changing font or colors
	
					EndSelect
				EndIf
			EndIf
	EndSelect
	
	ProcedureReturn result
EndProcedure


If OpenWindow(0, 100, 100, 415, 300, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ListIconGadget(0, 5, 5, 405, 200, "", 80, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_GridLines)
		
	hHeader = SendMessage_(GadgetID(0), #LVM_GETHEADER, 0, 0)
	
	Define iHeaderHeight = 50 ; Header height 50 pixels
	; Set height of Header items by applying a text font with a suitable height
	g_hHdrFont = Header_SetItemHeightByFont(hHeader, iHeaderHeight)

	; Add columns
	For a = 1 To Column_Count - 1
		AddGadgetColumn(0, a, "", 80)
	Next 

	; Add some data
	For b = 0 To 6 ; Add 7 rows
		AddGadgetItem(0, -1, "")
	Next

	For i = 0 To 6
		For j = 0 To Column_Count - 1
			SetGadgetItemText(0,i,Str(i+j),j)
		Next
	Next
	
	; Subclass ListIcon so we can customdraw the header text
	oldListIconCallback = SetWindowLongPtr_(GadgetID(0), #GWL_WNDPROC, @SubclassedListIcon())
  
	
	Repeat
	Until WaitWindowEvent() = #PB_Event_CloseWindow
	
EndIf 

Feel free to improve it.
Last edited by tatanas on Mon Dec 11, 2023 10:58 am, edited 1 time in total.
Windows 10 Pro x64
PureBasic 6.03 x64
User avatar
jacdelad
Addict
Addict
Posts: 1385
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: MultiLines Header ListIcon

Post by jacdelad »

Totally wrong subforum, but surely a great example. :D
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
User avatar
idle
Addict
Addict
Posts: 4962
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: MultiLines Header ListIcon

Post by idle »

Moved to Tips and Tricks
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5338
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: MultiLines Header ListIcon

Post by Kwai chang caine »

Useful working code here
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
Axolotl
Enthusiast
Enthusiast
Posts: 414
Joined: Wed Dec 31, 2008 3:36 pm

Re: MultiLines Header ListIcon

Post by Axolotl »

Thanks for sharing.

Please consider that SetWindowLong function has been superseded by the SetWindowLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Windows, use the SetWindowLongPtr function.

Or take a look at Subclassing Controls with ComCtl32.dll version 6 (win only)
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
ozzie
Enthusiast
Enthusiast
Posts: 429
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

Re: MultiLines Header ListIcon

Post by ozzie »

Thanks, Axolotl, for the info about SetWindowLong being superseded.
tatanas
Enthusiast
Enthusiast
Posts: 186
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: MultiLines Header ListIcon

Post by tatanas »

Thanks for the advice. I edited the code with SetWindowLongPtr_().
Windows 10 Pro x64
PureBasic 6.03 x64
User avatar
Shardik
Addict
Addict
Posts: 1979
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: MultiLines Header ListIcon

Post by Shardik »

You may also take a look into these code examples from netmaestro and srod from 2009.
Post Reply