ListIcon and image transparency

Windows specific forum
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: ListIcon and image transparency

Post by tatanas »

Thank you very much. Both of you did a great job !

Why hasn't Microsoft done anything to simplify this ? All this just to display an icon with a transparent backgound in listview...
Windows 10 Pro x64
PureBasic 6.20 x64
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: ListIcon and image transparency

Post by tatanas »

I've got a similar problem when I want to center the image/icon inside its column. The highlight of the line is erased by the redraw of the subitem image :

Code: Select all

Global ImgList, OldWndProc, ListIcon

Procedure ListIcon_SetItemImage(tempListIconGadget, index_item.w, index_subitem.w, index_image.w)
	Protected itemLV.LVITEM ; tagLVITEM
	itemLV\mask = #LVIF_IMAGE
	itemLV\iItem = index_item
	itemLV\iSubItem = index_subitem
	itemLV\iImage = index_image
	If Not SendMessage_(GadgetID(tempListIconGadget), #LVM_SETITEM, 0, @itemLV) 
		Debug "#LVM_SETITEM error"
	EndIf
EndProcedure

Procedure Add_Icon_To_ImageList(ImgList, DLL_Path.s, index)
	Protected hIcon, img_index = -1
	hIcon = ExtractIcon_(#Null, DLL_Path, index)
	If hIcon
		img_index = ImageList_AddIcon_(ImgList, hIcon)
		DestroyIcon_(hIcon)
	Else
		ProcedureReturn -1
	EndIf
	ProcedureReturn img_index
EndProcedure


Procedure WndProc(hWnd, Message, wParam, lParam)
	Protected *lparam.NMHDR, *lvcd.NMLVCUSTOMDRAW

	Select Message
		
		Case #WM_NOTIFY
			If lParam
				*lparam = lParam
				If *lparam\hwndFrom = GadgetID(ListIcon)

					Select *lparam\code
						Case #NM_CUSTOMDRAW
							*lvcd = lParam
	
							Select *lvcd\nmcd\dwDrawStage

								Case #CDDS_PREPAINT
									ProcedureReturn #CDRF_NOTIFYITEMDRAW

								Case #CDDS_ITEMPREPAINT
									ProcedureReturn #CDRF_NOTIFYSUBITEMDRAW		

								Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
										Protected hDC
										Protected ptLVITEM.LVITEM
										Protected Imgindex, hIcon
										Protected ptRECT.RECT
										Protected rectangle_width, new_x
	
										Select *lvcd\iSubItem
											Case 2

; 												ItemSelected = Bool(GetGadgetItemState(ListIcon, *lvcd\nmcd\dwItemSpec) & #PB_ListIcon_Selected)
; 												If ItemSelected And GetActiveGadget() = ListIcon
; 													BkColor = GetSysColor_(#COLOR_HIGHLIGHT)
; 												Else
; 													BkColor = GetSysColor_(#COLOR_BTNFACE)
; 												EndIf

												hDC = *lvcd\nmcd\hdc

; 												hBrush = CreateSolidBrush_(BkColor)
; 												If hBrush
; 													FillRect_(hDC, ptRECT, hBrush)
; 													DeleteObject_(hBrush)
; 												EndIf

	
												ptLVITEM\mask = #LVIF_IMAGE
												ptLVITEM\iItem = *lvcd\nmcd\dwItemSpec
												ptLVITEM\iSubItem = *lvcd\iSubItem
												SendMessage_(*lparam\hwndFrom, #LVM_GETITEMW, 0, @ptLVITEM)
												Imgindex = ptLVITEM\iImage
	
												hIcon = ImageList_GetIcon_(ImgList, Imgindex, #ILD_NORMAL)
	
												ptRECT\top = *lvcd\iSubItem
												ptRECT\left = #LVIR_BOUNDS
												SendMessage_(*lparam\hwndFrom, #LVM_GETSUBITEMRECT, *lvcd\nmcd\dwItemSpec, @ptRECT)
												rectangle_width = ptRECT\right - ptRECT\left
												new_x = ptRECT\left + (rectangle_width / 2) - 8 ; 8 = 16px / 2
	
	 											DrawIconEx_(hDC, new_x, ptRECT\top, hIcon, 16, 16, 0, #Null, #DI_NORMAL)
												DestroyIcon_(hIcon)
												ReleaseDC_(*lparam\hwndFrom, hDC)

												ProcedureReturn #CDRF_SKIPDEFAULT
										
										EndSelect
	
								Default
									ProcedureReturn #CDRF_DODEFAULT	
						EndSelect
					EndSelect
				EndIf
			EndIf

	EndSelect
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


Define Window = OpenWindow(#PB_Any, 0, 0, 464, 462, "Image transparency", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ListIcon = ListIconGadget(#PB_Any, 34, 30, 388, 402, "Col 1", 100, #PB_ListIcon_FullRowSelect); | #PB_ListIcon_AlwaysShowSelection); | #PB_ListIcon_MultiSelect)
AddGadgetColumn(ListIcon, 1, "Col 2", 100)
AddGadgetColumn(ListIcon, 2, "Col 3", 100)
; SetGadgetColor(ListIcon, #PB_Gadget_BackColor, $CCCCCC)

ImgList = ImageList_Create_(16, 16, #ILC_COLOR32 | #ILC_MASK, 0, 10)

SendMessage_(GadgetID(ListIcon), #LVM_SETIMAGELIST, #LVSIL_SMALL, ImgList)
SendMessage_(GadgetID(ListIcon), #LVM_SETEXTENDEDLISTVIEWSTYLE, #LVS_EX_SUBITEMIMAGES, #LVS_EX_SUBITEMIMAGES)

;For i = 0 To 10
For i = 0 To 50
	AddGadgetItem(ListIcon, i, "item" + i + Chr(10) + "subitem" + i)
Next
EnableGadgetDrop(ListIcon, #PB_Drop_Private, #PB_Drag_Move)

icon_index = Add_Icon_To_ImageList(ImgList, "shell32.dll", 296)
ListIcon_SetItemImage(ListIcon, 5, 2, icon_index)
ListIcon_SetItemImage(ListIcon, 6, 2, icon_index)
ListIcon_SetItemImage(ListIcon, 10, 2, icon_index)

SetWindowCallback(@WndProc())

Repeat
	e = WaitWindowEvent()
Until e = #PB_Event_CloseWindow
I guess I should apply the highlight color to the image/icon transparent background. Is it possible ?
Windows 10 Pro x64
PureBasic 6.20 x64
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: ListIcon and image transparency

Post by breeze4me »

Fill in the background color as shown below.

Code: Select all

Global ImgList, OldWndProc, ListIcon

Procedure ListIcon_SetItemImage(tempListIconGadget, index_item.w, index_subitem.w, index_image.w)
	Protected itemLV.LVITEM ; tagLVITEM
	itemLV\mask = #LVIF_IMAGE
	itemLV\iItem = index_item
	itemLV\iSubItem = index_subitem
	itemLV\iImage = index_image
	If Not SendMessage_(GadgetID(tempListIconGadget), #LVM_SETITEM, 0, @itemLV) 
		Debug "#LVM_SETITEM error"
	EndIf
EndProcedure

Procedure Add_Icon_To_ImageList(ImgList, DLL_Path.s, index)
	Protected hIcon, img_index = -1
	hIcon = ExtractIcon_(#Null, DLL_Path, index)
	If hIcon
		img_index = ImageList_AddIcon_(ImgList, hIcon)
		DestroyIcon_(hIcon)
	Else
		ProcedureReturn -1
	EndIf
	ProcedureReturn img_index
EndProcedure


Procedure WndProc(hWnd, Message, wParam, lParam)
	Protected *lparam.NMHDR, *lvcd.NMLVCUSTOMDRAW

	Select Message
		
		Case #WM_NOTIFY
			If lParam
				*lparam = lParam
				If *lparam\hwndFrom = GadgetID(ListIcon)

					Select *lparam\code
						Case #NM_CUSTOMDRAW
							*lvcd = lParam
	
							Select *lvcd\nmcd\dwDrawStage

								Case #CDDS_PREPAINT
									ProcedureReturn #CDRF_NOTIFYITEMDRAW

								Case #CDDS_ITEMPREPAINT
									ProcedureReturn #CDRF_NOTIFYSUBITEMDRAW		

								Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
										Protected hDC
										Protected ptLVITEM.LVITEM
										Protected Imgindex, hIcon
										Protected ptRECT.RECT
										Protected rectangle_width, new_x
	
										Select *lvcd\iSubItem
											Case 2

												ptLVITEM\mask = #LVIF_IMAGE
												ptLVITEM\iItem = *lvcd\nmcd\dwItemSpec
												ptLVITEM\iSubItem = *lvcd\iSubItem
												SendMessage_(*lparam\hwndFrom, #LVM_GETITEMW, 0, @ptLVITEM)
												Imgindex = ptLVITEM\iImage
	
												hIcon = ImageList_GetIcon_(ImgList, Imgindex, #ILD_NORMAL)
	
												ptRECT\top = *lvcd\iSubItem
												ptRECT\left = #LVIR_BOUNDS
												SendMessage_(*lparam\hwndFrom, #LVM_GETSUBITEMRECT, *lvcd\nmcd\dwItemSpec, @ptRECT)
												rectangle_width = ptRECT\right - ptRECT\left
												new_x = ptRECT\left + (rectangle_width / 2) - 8 ; 8 = 16px / 2
												
												
												ItemSelected = Bool(GetGadgetItemState(ListIcon, *lvcd\nmcd\dwItemSpec) & #PB_ListIcon_Selected)
												If ItemSelected And GetActiveGadget() = ListIcon
													BkColor = GetSysColor_(#COLOR_HIGHLIGHT)
												Else
													BkColor = GetSysColor_(#COLOR_WINDOW)
												EndIf
												
												hDC = *lvcd\nmcd\hdc
												
												hBrush = CreateSolidBrush_(BkColor)
												If hBrush
													FillRect_(hDC, ptRECT, hBrush)
													DeleteObject_(hBrush)
												EndIf
												
												
	 											DrawIconEx_(hDC, new_x, ptRECT\top, hIcon, 16, 16, 0, #Null, #DI_NORMAL)
												DestroyIcon_(hIcon)
												ReleaseDC_(*lparam\hwndFrom, hDC)

												ProcedureReturn #CDRF_SKIPDEFAULT
										
										EndSelect
	
								Default
									ProcedureReturn #CDRF_DODEFAULT	
						EndSelect
					EndSelect
				EndIf
			EndIf

	EndSelect
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


Define Window = OpenWindow(#PB_Any, 0, 0, 464, 462, "Image transparency", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ListIcon = ListIconGadget(#PB_Any, 34, 30, 388, 402, "Col 1", 100, #PB_ListIcon_FullRowSelect); | #PB_ListIcon_AlwaysShowSelection); | #PB_ListIcon_MultiSelect)
AddGadgetColumn(ListIcon, 1, "Col 2", 100)
AddGadgetColumn(ListIcon, 2, "Col 3", 100)
; SetGadgetColor(ListIcon, #PB_Gadget_BackColor, $CCCCCC)

ImgList = ImageList_Create_(16, 16, #ILC_COLOR32 | #ILC_MASK, 0, 10)

SendMessage_(GadgetID(ListIcon), #LVM_SETIMAGELIST, #LVSIL_SMALL, ImgList)
SendMessage_(GadgetID(ListIcon), #LVM_SETEXTENDEDLISTVIEWSTYLE, #LVS_EX_SUBITEMIMAGES, #LVS_EX_SUBITEMIMAGES)

;For i = 0 To 10
For i = 0 To 50
	AddGadgetItem(ListIcon, i, "item" + i + Chr(10) + "subitem" + i)
Next
EnableGadgetDrop(ListIcon, #PB_Drop_Private, #PB_Drag_Move)

icon_index = Add_Icon_To_ImageList(ImgList, "shell32.dll", 296)
ListIcon_SetItemImage(ListIcon, 5, 2, icon_index)
ListIcon_SetItemImage(ListIcon, 6, 2, icon_index)
ListIcon_SetItemImage(ListIcon, 10, 2, icon_index)

SetWindowCallback(@WndProc())

Repeat
	e = WaitWindowEvent()
Until e = #PB_Event_CloseWindow
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: ListIcon and image transparency

Post by tatanas »

Thank you it work fine !

But I don't undestand why ? This code doesn't work :

Code: Select all

Procedure WndProc(hWnd, Message, wParam, lParam)
	Protected *lparam.NMHDR, *lvcd.NMLVCUSTOMDRAW

	Select Message
		
		Case #WM_NOTIFY
			If lParam
				*lparam = lParam
				If *lparam\hwndFrom = GadgetID(ListIcon)

					Select *lparam\code
						Case #NM_CUSTOMDRAW
							*lvcd = lParam
	
							Select *lvcd\nmcd\dwDrawStage

								Case #CDDS_PREPAINT
									ProcedureReturn #CDRF_NOTIFYITEMDRAW

								Case #CDDS_ITEMPREPAINT
									ProcedureReturn #CDRF_NOTIFYSUBITEMDRAW		

								Case #CDDS_ITEMPREPAINT | #CDDS_SUBITEM
										Protected hDC
										Protected ptLVITEM.LVITEM
										Protected Imgindex, hIcon
										Protected ptRECT.RECT
										Protected rectangle_width, new_x
	
										Select *lvcd\iSubItem
											Case 2

												ItemSelected = Bool(GetGadgetItemState(ListIcon, *lvcd\nmcd\dwItemSpec) & #PB_ListIcon_Selected)
												If ItemSelected And GetActiveGadget() = ListIcon
													BkColor = GetSysColor_(#COLOR_HIGHLIGHT)
												Else
													BkColor = GetSysColor_(#COLOR_WINDOW)
												EndIf

												hDC = *lvcd\nmcd\hdc

												hBrush = CreateSolidBrush_(BkColor)
												If hBrush
													FillRect_(hDC, ptRECT, hBrush)
													DeleteObject_(hBrush)
												EndIf

												;----------------------------------------------------------------------------------------
												ptLVITEM\mask = #LVIF_IMAGE
												ptLVITEM\iItem = *lvcd\nmcd\dwItemSpec
												ptLVITEM\iSubItem = *lvcd\iSubItem
												SendMessage_(*lparam\hwndFrom, #LVM_GETITEMW, 0, @ptLVITEM)
												Imgindex = ptLVITEM\iImage
	
												hIcon = ImageList_GetIcon_(ImgList, Imgindex, #ILD_NORMAL)
	
												ptRECT\top = *lvcd\iSubItem
												ptRECT\left = #LVIR_BOUNDS
												SendMessage_(*lparam\hwndFrom, #LVM_GETSUBITEMRECT, *lvcd\nmcd\dwItemSpec, @ptRECT)
												rectangle_width = ptRECT\right - ptRECT\left
												new_x = ptRECT\left + (rectangle_width / 2) - 8 ; 8 = 16px / 2
												;----------------------------------------------------------------------------------------
	
	 											DrawIconEx_(hDC, new_x, ptRECT\top, hIcon, 16, 16, 0, #Null, #DI_NORMAL)
												DestroyIcon_(hIcon)
												ReleaseDC_(*lparam\hwndFrom, hDC)

												ProcedureReturn #CDRF_SKIPDEFAULT
										
										EndSelect
	
								Default
									ProcedureReturn #CDRF_DODEFAULT	
						EndSelect
					EndSelect
				EndIf
			EndIf

	EndSelect
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

The only difference is the position of the bloc between ";-------------------------------------"
Windows 10 Pro x64
PureBasic 6.20 x64
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: ListIcon and image transparency

Post by breeze4me »

FillRect_() does not paint the background color because the values of the fields in the ptRECT structure are all 0.
The structure variable is only populated after the #LVM_GETSUBITEMRECT message call below.
tatanas
Enthusiast
Enthusiast
Posts: 260
Joined: Wed Nov 06, 2019 10:28 am
Location: France

Re: ListIcon and image transparency

Post by tatanas »

I'm so stupid... I completely forgot the coordinate prequisite of FillRect :oops:
Windows 10 Pro x64
PureBasic 6.20 x64
Post Reply