Page 1 of 1

How can I place 32x32 icons in one column?

Posted: Mon Mar 09, 2026 8:22 pm
by AZJIO

Code: Select all

#LIG = 0

Define hIcon
Define p.POINT
If OpenWindow(0, 100, 100, 400, 600, "example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ListIconGadget(#LIG, 5, 5, 390, 590, "Name", 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
	AddGadgetColumn(#LIG, 1, "Address", 250)
	ExtractIconEx_("Shell32.dll", 3, @hIcon, 0, 1)        ; 32
	SetGadgetAttribute(#LIG, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
	For i = 0 To 11
		AddGadgetItem(#LIG, i, "fuf " + Str(i), hIcon)
		p\x = 5
		p\y = i * 34
		SendMessage_(GadgetID(#LIG), #LVM_SETITEMPOSITION32, i, @p)
		; SendMessage_(GadgetID(#LIG), #LVM_SETITEMPOSITION, i, p\x | (p\y << 32))
	Next
	Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
	DestroyIcon_(hIcon)
EndIf

Re: How can I place 32x32 icons in one column?

Posted: Mon Mar 09, 2026 9:27 pm
by Olli
1)
The external function does not send a direct pointor.
It sends a pointor into a table of icon handles.

2)
I am not sure that the external function accepts a 0 value
when the coder needs no small icon, so I also add a void pointor.

Code: Select all

#LIG = 0

Define void
Define iconTable
Define hIcon
Define p.POINT
If OpenWindow(0, 100, 100, 400, 600, "example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ListIconGadget(#LIG, 5, 5, 390, 590, "Name", 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
	AddGadgetColumn(#LIG, 1, "Address", 250)
	ExtractIconEx_("Shell32.dll", 3, @iconTable, @void, 1)        ; 32
	hIcon = peekI(iconTable)
	SetGadgetAttribute(#LIG, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
	For i = 0 To 11
		AddGadgetItem(#LIG, i, "fuf " + Str(i), hIcon)
		p\x = 5
		p\y = i * 34
		SendMessage_(GadgetID(#LIG), #LVM_SETITEMPOSITION32, i, @p)
	Next
	Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
	DestroyIcon_(hIcon)
EndIf

Re: How can I place 32x32 icons in one column?

Posted: Mon Mar 09, 2026 9:31 pm
by RASHAD

Code: Select all

#LIG = 0

Define hIcon
Define p.POINT
If OpenWindow(0, 100, 100, 400, 600, "example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ListIconGadget(#LIG, 5, 5, 84, 590, "Name", 64, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
	AddGadgetColumn(#LIG, 1, "Address", 250)
	ExtractIconEx_("Shell32.dll", 3, @hIcon, 0, 1)        ; 32
	SetGadgetAttribute(#LIG, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
	For i = 0 To 11
		AddGadgetItem(#LIG, i, "fuf " + Str(i), hIcon)
		p\x = 5
		p\y = i * 34
		SendMessage_(GadgetID(#LIG), #LVM_SETITEMPOSITION32, i, @p)
		; SendMessage_(GadgetID(#LIG), #LVM_SETITEMPOSITION, i, p\x | (p\y << 32))
	Next
	Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
	DestroyIcon_(hIcon)
EndIf

Re: How can I place 32x32 icons in one column?

Posted: Mon Mar 09, 2026 10:07 pm
by Olli
@RASHAD

Glad to read you. Hope you are fine.
I am interested by your suggest. Mainly, you test a lot before posting a code.

After a check on the microSoft documentation ExtractIconExA, I see my 2nd remark is false (no need a void pointor).

But my 1st remark seems to be right, except if the microSoft documentation is false.

Code: Select all

ExtractIconEx_(... , @hicon, ...)
Debug hIcon ; <-- should not be a handle ?
What is your observation ? (= could you confirm you are right ?)

Regards

Re: How can I place 32x32 icons in one column?

Posted: Mon Mar 09, 2026 10:35 pm
by Michael Vogel
Don't think it works with 'standard' flags - so custom drawing has do be done (once again)... :cry:

Code: Select all

#LST_Ownerdraw = 1

Structure LBITEMEX
	Icon.i
	Title.i
	Text.i
EndStructure

Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
	
	Select uMsg
	Case #WM_DRAWITEM
		Protected *lpdis.DRAWITEMSTRUCT = lParam
		Protected *lbex.LBITEMEX = GetGadgetItemData(#LST_Ownerdraw,*lpdis\itemID)
		Protected hbrFace, hdcMem, lplf.LOGFONT, hfntPrevious, hfntTitle

		; Draw item rectangle (normal/highlighted)
		If *lpdis\itemState & #ODS_SELECTED
			hbrFace = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
			FillRect_(*lpdis\hdc,*lpdis\rcItem,hbrFace)
			DrawFocusRect_(*lpdis\hdc,*lpdis\rcItem)
			SetTextColor_(*lpdis\hdc,GetSysColor_(#COLOR_HIGHLIGHTTEXT))
		Else
			hbrFace = CreateSolidBrush_(GetSysColor_(#COLOR_WINDOW))
			FillRect_(*lpdis\hdc,*lpdis\rcItem,hbrFace)
			SetTextColor_(*lpdis\hdc,GetSysColor_(#COLOR_WINDOWTEXT))
		EndIf

		DeleteObject_(hbrFace)

		; Draw the icon
		DrawIcon_(*lpdis\hdc,8,*lpdis\rcItem\top + 8,*lbex\Icon)

		; Create large font
		GetObject_(SendMessage_(*lpdis\hWndItem,#WM_GETFONT,0,0),SizeOf(LOGFONT),lplf)
		lplf\lfHeight = -MulDiv_(12,GetDeviceCaps_(*lpdis\hdc,#LOGPIXELSY),72)
		hfntTitle = CreateFontIndirect_(lplf)

		; Draw the title / text
		SetBkMode_(*lpdis\hdc,#TRANSPARENT)
		hfntPrevious = SelectObject_(*lpdis\hdc,hfntTitle)
		TextOut_(*lpdis\hdc,60,*lpdis\rcItem\top + 2,*lbex\title,lstrlen_(*lbex\title))
		SelectObject_(*lpdis\hdc,hfntPrevious)
		TextOut_(*lpdis\hdc,60,*lpdis\rcItem\top + 28,*lbex\text,lstrlen_(*lbex\text))
		DeleteObject_(hfntTitle)

		ProcedureReturn #True
	EndSelect

	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure AddLBItemEx(Gadget,Position,Icon,Title$,Text$)

	Protected *lbex.LBITEMEX = AllocateMemory(SizeOf(LBITEMEX)), Index
	*lbex\Icon = Icon
	CompilerIf #PB_Compiler_Unicode
		*lbex\Title = AllocateMemory(Len(Title$) * 2 + 2)
		*lbex\Text = AllocateMemory(Len(Text$) * 2 + 2)
	CompilerElse
		*lbex\Title = AllocateMemory(Len(Title$) + 1)
		*lbex\Text = AllocateMemory(Len(Text$) + 1)
	CompilerEndIf
	PokeS(*lbex\Title,Title$)
	PokeS(*lbex\Text,Text$)
	Index = SendMessage_(GadgetID(Gadget),#LB_ADDSTRING,0,"")
	SetGadgetItemData(Gadget,Index,*lbex)

EndProcedure

OpenWindow(0,0,0,360,300,"°v°",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListViewGadget(#LST_Ownerdraw,0,0,360,300,#LBS_OWNERDRAWFIXED)

SendMessage_(GadgetID(#LST_Ownerdraw),#LB_SETITEMHEIGHT,0,60)

SetWindowCallback(@WindowCallback())

;LoadImage(0,"..\Data\1.ico")
CreateImage(0,32,32,32,#Red)

NewIcon.ICONINFO
NewIcon\fIcon = #True
NewIcon\hbmMask = ImageID(0)
NewIcon\hbmColor = ImageID(0)

Icon=CreateIconIndirect_(@NewIcon)

AddLBItemEx(#LST_Ownerdraw,-1,icon,"Item Caption #1","This is the subtext for the item")
AddLBItemEx(#LST_Ownerdraw,-1,icon,"Item Caption #2","This is the subtext for the item")
AddLBItemEx(#LST_Ownerdraw,-1,icon,"Item Caption #3","This is the subtext for the item")

SetActiveGadget(#LST_Ownerdraw)
SetGadgetState(#LST_Ownerdraw,0)

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow

Re: How can I place 32x32 icons in one column?

Posted: Mon Mar 09, 2026 11:02 pm
by RASHAD
In case of ListIcon with List Display Mode and any size of icons

Code: Select all

OpenWindow(0,0,0,320,240,"64x64 Icons",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListIconGadget(0,0,0,400,600,"",250,#PB_ListIcon_NoHeaders)

For i=1 To 4
  AddGadgetItem(0,-1,"  ListIcon Item #" + Str(i))
Next

hList = ImageList_Create_(64,64,#ILC_COLOR32| #ILC_MASK, 0, 100)

ImageList_AddIcon_(hList,LoadIcon_(0,#IDI_ERROR))
ImageList_AddIcon_(hList,LoadIcon_(0,#IDI_EXCLAMATION))
ImageList_AddIcon_(hList,LoadIcon_(0,#IDI_QUESTION))
ImageList_AddIcon_(hList,LoadIcon_(0,#IDI_INFORMATION))

SendMessage_(GadgetID(0), #LVM_SETIMAGELIST, #LVSIL_SMALL, hList)

lvi.LV_ITEM
lvi\mask = #LVIF_IMAGE
For i = 0 To 3
  lvi\iItem = i : lvi\iImage = i
  SendMessage_(GadgetID(0),#LVM_SETITEM,0,lvi)
Next

Repeat
  Select WaitWindowEvent(1)
    Case #PB_Event_CloseWindow
      Quit = 1
  EndSelect
Until Quit = 1

Re: How can I place 32x32 icons in one column?

Posted: Tue Mar 10, 2026 12:21 am
by AZJIO
I've made my own versions and they're similar to yours. Maybe I should have waited a bit. :D

Code: Select all

Global ListIcon_ID, hImgList
Define hIcon1, hIcon2, hIcon3
Define Size = 32
; Добавляем иконки прог
ExtractIconEx_("Shell32.dll", 161, @hIcon1, 0, 1)
ExtractIconEx_("Shell32.dll", 0, @hIcon2, 0, 1)
ExtractIconEx_("Shell32.dll", 3, @hIcon3, 0, 1)


Procedure AddItem(idxLV, idxImage, text$, pos = -1)
	Protected item.LVITEM
	item\mask = #LVIF_TEXT | #LVIF_PARAM | #LVIF_IMAGE
	item\iItem = idxLV
	item\iImage = idxImage
	item\pszText = @text$
	SendMessage_(GadgetID(ListIcon_ID), #LVM_INSERTITEMW, pos, @item)
	ProcedureReturn 0
EndProcedure


If OpenWindow(0, 0, 0, 400, 350, "Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ListIcon_ID = ListIconGadget(#PB_Any, 5, 5, 390, 340, "Файлы", 200, #PB_ListIcon_FullRowSelect | #LVS_NOCOLUMNHEADER)
	hImgList = ImageList_Create_(Size, Size, #ILC_COLOR32 | #ILC_MASK, 1, 1)
	; Подготовим тестовую иконку (квадрат) нужного размера
	ImageList_AddIcon_(hImgList, hIcon1)
	ImageList_AddIcon_(hImgList, hIcon2)
	ImageList_AddIcon_(hImgList, hIcon3)
	; Иконки уже в ImageList, оригинал можно удалить
	DestroyIcon_(hIcon1)
	DestroyIcon_(hIcon2)
	DestroyIcon_(hIcon3)
	SendMessage_(GadgetID(ListIcon_ID), #LVM_SETIMAGELIST, #LVSIL_SMALL, hImgList)
	; 4. Добавляем данные
	For i = 0 To 2
		AddItem(i, i, "Program: " + Str(i))
	Next
	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

I've redone the second example from this example.

Code: Select all

Global hIcon = 0
Global hIcon2 = 0
ExtractIconEx_("Shell32.dll", 161, @hIcon, 0, 1)
ExtractIconEx_("Shell32.dll", 0, @hIcon2, 0, 1)
; ExtractIconEx_("C:\ProgramData\PureBasic\Examples\Sources\Data\CdPlayer.ico", 0, 0, @hIcon, 1)
; Debug hIcon

Global g_tRect.RECT
With g_tRect
	\left = 0
	\top = 0
	\right = 32
	\bottom = 32
EndWith

Global hDC

#LV0 = 0


Global BackColor = $00FF00
Global ForeColor = $FF0000
Global BackColorHeader = $eeffee
Global ForeColorHeader = $2277ff
Global BorderColor = $0
Global HightLightBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
; Global HightLightBrush = CreateSolidBrush_($ff3926)
Global BackColorBrush = CreateSolidBrush_(BackColor)
Global BackColorBrushHeader = CreateSolidBrush_(BackColorHeader)


; ---------------------------------------------------------------------------------------------------------------------

Procedure GetCharWidth(gad, c$)
	ProcedureReturn SendMessage_(gad, #LVM_GETSTRINGWIDTH, 0, @c$)
EndProcedure

; это подкрашивает пункты в ListView
Procedure Callback_Win(hwnd, msg, wParam, lParam)
	Protected Result, *nmhdr.NMHDR, *lvCD.NMLVCUSTOMDRAW, subItemRect.RECT
	Protected thisRow, thisCol
	Protected text$
	Protected *NMITEM.NMITEMACTIVATE
; 	Protected nNotifyCode

	Result = #PB_ProcessPureBasicEvents
	;;Dim LVColor(0)

	Select msg

		Case #WM_NCDESTROY ; удаление кистей, после закрытия программы
			DeleteObject_(HightLightBrush)
			DeleteObject_(BackColorBrush)
			DeleteObject_(BackColorBrushHeader)

		Case #WM_NOTIFY
			; стандартные структуры ListView для перерисовки
			*nmhdr.NMHDR = lParam
			*lvCD.NMLVCUSTOMDRAW = lParam
			*NMITEM.NMITEMACTIVATE = lParam

; 			если гаджет #LV0 и он пользовательская рисовка, то
			If *lvCD\nmcd\hdr\hwndFrom = GadgetID(#LV0) And *lvCD\nmcd\hdr\code = #NM_CUSTOMDRAW
				Select *lvCD\nmcd\dwDrawStage
					Case #CDDS_PREPAINT
						Result = #CDRF_NOTIFYITEMDRAW
					Case #CDDS_ITEMPREPAINT
						Result = #CDRF_NOTIFYSUBITEMDRAW;
					Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM ; перерисовка пункта
						thisRow = *lvCD\nmcd\dwItemSpec ; строку
						thisCol = *lvCD\iSubItem ; колонка
						If thisCol =0 ; если колонка 0, то
							; Определяет прямоугольник для текста
							subItemRect.RECT\left = #LVIR_BOUNDS ; #LVIR_ICON, #LVIR_LABEL
							subItemRect.RECT\top = *lvCD\iSubItem ; iSubItem
							; Определяет прямоугольник подпункт
							SendMessage_(GadgetID(#LV0), #LVM_GETSUBITEMRECT, thisRow, @subItemRect) ; в итоге переписываем структуру прямоугольника

; 							subItemRect.RECT\left + 160
							text$ = GetGadgetItemText(#LV0, thisRow, thisCol) ; получаем текст пункта по строке и колонке

							If GetGadgetState(#LV0) = thisRow ; если индекс выделенного элемента равен пункту, то
								; выделенный пункт, перекрашиваем его фон
								FillRect_(*lvCD\nmcd\hdc, subItemRect, HightLightBrush)
								SetTextColor_(*lvCD\nmcd\hdc, $00FFFF) ;
							Else
								; не выделенный пункт, перекрашиваем его другим фоном
								FillRect_(*lvCD\nmcd\hdc, subItemRect, BackColorBrushHeader)
								SetTextColor_(*lvCD\nmcd\hdc, ForeColor) ;
							EndIf
							CopyStructure(@subItemRect, @g_tRect, RECT)
							InflateRect_(subItemRect, -46, 0) ; изменяет левую границу прямоугольника на 8 пиксел (уже другое)
							SetBkColor_(*lvCD\nmcd\hdc, BackColorHeader)  ; фон всегда одинаковый, он вообще не нужен
							DrawText_(*lvCD\nmcd\hdc, text$, -1, subItemRect, #DT_END_ELLIPSIS | #DT_VCENTER | #DT_SINGLELINE) ; рисуем текст
							With g_tRect
								\left + 0
								\right = \left + 12
								\top + 1
								\bottom = \top + 12
							EndWith
							If thisRow % 2
								DrawIconEx_(*lvCD\nmcd\hdc, g_tRect\left, g_tRect\top, hIcon, 32, 32, 0, 0, #DI_NORMAL)
							Else
								DrawIconEx_(*lvCD\nmcd\hdc, g_tRect\left, g_tRect\top, hIcon2, 32, 32, 0, 0, #DI_NORMAL)
							EndIf

							Result = #CDRF_SKIPDEFAULT
						Else
							Result = #CDRF_DODEFAULT
						EndIf
				EndSelect
			EndIf
	EndSelect
	ProcedureReturn Result
EndProcedure


;- ╔═ GUI ═╗
If OpenWindow(0, 0, 0, 420, 400, "Пример...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	
	
	If LoadFont(0, "Segoe UI", 15)
		SetGadgetFont(#PB_Default, FontID(0)) ; Установить загруженный шрифт Arial 16 как новый стандарт
	EndIf

	ListIconGadget(#LV0, 10, 10, 400, 380, "Col0", 250, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect | #PB_ListIcon_NoHeaders)


	For a = 1 To 6
		AddGadgetItem(#LV0, -1, "Программа " + Str(a) )
	Next
	SetGadgetColor(#LV0, #PB_Gadget_BackColor, BackColorHeader)
	SetWindowCallback(@Callback_Win())



	;- Loop
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_CloseWindow
; 				for ExtractIconEx
				DestroyIcon_(hIcon)
				DestroyIcon_(hIcon2)
				CloseWindow(0)
				End
		EndSelect
	ForEver
EndIf