Page 1 of 1

[Windows] Coloring Comboboxes with images

Posted: Tue Mar 03, 2026 4:49 pm
by Michael Vogel
I found some solutions in the forum showing how to color combobox gadgets, but none of these work with standard images. Complete custom drawing could be done but gets quite complicate when display scaling and some other aspects need to be taken into account.
Is there a (relatively simple) method to get colors also when using the #PB_ComboBox_Image flag?

Maybe there will be a possibility somewhen to get more and more gadget types colored by using the SetGadgetColor function, this would be wonderful.

Code: Select all

#DrawOpaque=$FF<<24

CreateImage(0,32,32,32)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0,0,32,32,#White)
Circle(15,15,15,#DrawOpaque|#Red)
StopDrawing()

If OpenWindow(0, 0, 0, 270, 180, "Combo Box Gadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ComboBoxGadget(0, 10, 10, 250, 40, #PB_ComboBox_Editable)
	ComboBoxGadget(1, 10, 60, 250, 40, #PB_ComboBox_Image)
	ComboBoxGadget(2, 10,110, 250, 40,#PB_ComboBox_Editable|#PB_ComboBox_Image)

	For a = 0 To 8
		For n=0 To 2
			AddGadgetItem(n,a,"ComboBox "+Str(n)+", item " + Str(a+1),ImageID(0)*Bool(a&1))
		Next n
	Next a

	For a = 0 To 2
		SetGadgetState(a, 0)
		SetGadgetColor(a,#PB_Gadget_FrontColor,#Blue)
		SetGadgetColor(a,#PB_Gadget_BackColor,#Yellow)
	Next a

	Repeat
		; ?
	Until WaitWindowEvent() = #PB_Event_CloseWindow
	
EndIf

Re: [Windows] Coloring Comboboxes with images

Posted: Tue Mar 03, 2026 5:26 pm
by RASHAD
Hi

Code: Select all


Global Text$,Brush,Brush_2,Brush_3
Text$ = Space(#MAX_PATH)
Global Dim icons(5)

i.ICONINFO
i\fIcon=1
CreateImage(0,24,16)
StartDrawing(ImageOutput(0))
Box(0,0,24,16,#White)
Box(4,4,16,8,#Black)
StopDrawing()
i\hbmMask=ImageID(0)
i\hbmColor=ImageID(0)
icons(1)=CreateIconIndirect_(@i)
FreeImage(0)

CreateImage(0,24,16)
StartDrawing(ImageOutput(0))
Box(0,0,24,16,#Blue)
Box(4,4,16,8,#Yellow)
StopDrawing()

i\hbmMask=ImageID(0)
i\hbmColor=ImageID(0)
icons(2)=CreateIconIndirect_(@i)
FreeImage(0)

CreateImage(0,24,16)
StartDrawing(ImageOutput(0))
Box(0,0,24,16,#Red)
Box(4,4,16,8,#Yellow)
StopDrawing()

i\hbmMask=ImageID(0)
i\hbmColor=ImageID(0)
icons(3)=CreateIconIndirect_(@i)
FreeImage(0)

LoadFont(0,"Georgia",12,#PB_Font_Italic)
LoadFont(1,"Broadway",12,#PB_Font_Bold )

Brush = CreateSolidBrush_($FADC72)
Brush_2 = CreateSolidBrush_($99FEFA)
Brush_3 = CreateSolidBrush_($B2FED3)

Procedure WndProc(hWnd, uMsg, wParam, lParam)
  
  Result = #PB_ProcessPureBasicEvents 
  
  Select uMsg
    Case #WM_DRAWITEM 
      *DRAWITEM.DRAWITEMSTRUCT = lParam       
      If *DRAWITEM\CtlType = #ODT_COMBOBOX 
        SetBkMode_(*DRAWITEM\hDC, #TRANSPARENT)
        If *DRAWITEM\ItemState & #ODS_FOCUS
          FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,Brush)
        ElseIf *DRAWITEM\CtlID = 1
          FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,Brush_2) 
        ElseIf  *DRAWITEM\CtlID = 2
          FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,Brush_3)  
        EndIf
        
        SendMessage_(*DRAWITEM\hwndItem,#CB_GETLBTEXT,*DRAWITEM\itemID, @Text$)
        If *DRAWITEM\itemID % 2 = 1
          SelectObject_(*DRAWITEM\hDC, FontID(0)) 
          SetTextColor_(*DRAWITEM\hDC,$0101FE)
          *DRAWITEM\rcItem\left = 36
          DrawIconEx_(*DRAWITEM\hDC, 8,*DRAWITEM\rcItem\top+6, icons(*DRAWITEM\itemID+1),24,16, 0,0,#DI_NORMAL|#DI_COMPAT)
          DrawText_(*DRAWITEM\hDC,@Text$,Len(Text$),*DRAWITEM\rcItem, #DT_SINGLELINE | #DT_VCENTER )
          ;TextOut_(*DRAWITEM\hDC,*DRAWITEM\rcItem\left+2,*DRAWITEM\rcItem\top+1,Text$,Len(Text$))
        Else
          SelectObject_(*DRAWITEM\hDC, FontID(1))
          SetTextColor_(*DRAWITEM\hDC, $000000)
          *DRAWITEM\rcItem\left = 36
          DrawIconEx_(*DRAWITEM\hDC, 8,*DRAWITEM\rcItem\top+12, icons(*DRAWITEM\itemID+1),24,16, 0,0,#DI_NORMAL|#DI_COMPAT)
          DrawText_(*DRAWITEM\hDC,@Text$,Len(Text$),*DRAWITEM\rcItem,  #DT_SINGLELINE | #DT_VCENTER )
          ;TextOut_(*DRAWITEM\hDC, *DrawItem\rcItem\left+2,*DRAWITEM\rcItem\top+1,Text$,Len(Text$))
        EndIf 
      EndIf
      
  EndSelect 
  
  ProcedureReturn Result 
EndProcedure 

OpenWindow(0,0,0,600,400, "Colored Items", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget ) 
SetWindowCallback(@WndProc())

ComboBoxGadget(1,10,10,190, 42,#CBS_OWNERDRAWFIXED|#CBS_HASSTRINGS)  
AddGadgetItem(1,-1, "Test #1") 
AddGadgetItem(1,-1, "Test #2") 
AddGadgetItem(1,-1, "Test #3")
AddGadgetItem(1,-1, "Test #4")
SetGadgetState(1,2)

ComboBoxGadget(2,210,10,190, 32,#CBS_OWNERDRAWFIXED|#CBS_HASSTRINGS)
AddGadgetItem(2,-1, "Test #2-1") 
AddGadgetItem(2,-1, "Test #2-2") 
AddGadgetItem(2,-1, "Test #2-3")
AddGadgetItem(2,-1, "Test #2-4")
SetGadgetState(2,1)

SendMessage_(GadgetID(1),#CB_SETITEMHEIGHT,0,42) 
SendMessage_(GadgetID(2),#CB_SETITEMHEIGHT,0,32) 

ButtonGadget(3,0,0,0,0,"dummy")

Repeat
  
  Select WaitWindowEvent()
      
    Case #PB_Event_CloseWindow
      Quit = 1       
      
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1 ,2
          Select EventType()
            Case #PB_EventType_Change 
              Debug GetGadgetText(GetActiveGadget() )
              SetActiveGadget(-1) 
          EndSelect         
      EndSelect          
      
  EndSelect 
  
Until Quit = 1
End

Re: [Windows] Coloring Comboboxes with images

Posted: Wed Mar 04, 2026 3:26 pm
by Michael Vogel
Thank you, you're a helpful genius.

For me it seems to be still a little bit tricky to do finetuning when display scaling is different to 100% (vertical alignment, etc.) to look identically to the original style but it gets even more difficult when the combobox has to be editable (#PB_ComboBox_Editable) - and that's what I actually have here.

I've played around with your code, this would finalize my tool which allows themes to color the windows caption and background, the statusbar, a progressbar, a trackbar, a frame and its text a iconlistbox including the headers,...
...the code below shows the owner drawn combobox in the middle of the dialog - it got no color in the edit area and font, alignment and sizing of the icon is quite different compared to the standard gadgets.

Code: Select all


#DrawOpaque=$FF<<24

Global ComboItemHeight.i

Procedure Init()

	Protected Metrics.NONCLIENTMETRICS

	Metrics\cbSize=SizeOf(Metrics)
	SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS,SizeOf(Metrics),@Metrics,0)

	LoadFont(0,PeekS(@Metrics\lfMenuFont\lfFaceName[0]),Metrics\lfMenuFont\lfHeight+2)

	Global Text$,Brush,Brush_2,Brush_3
	Text$ = Space(#MAX_PATH)
	Brush = CreateSolidBrush_($FADC72)
	Brush_2 = CreateSolidBrush_($99FEFA)
	Brush_3 = CreateSolidBrush_($B2FED3)

	Global Dim icons(3)
	ico.ICONINFO
	ico\fIcon=1

	For i=0 To 2
		CreateImage(i,32,32,32)
		StartDrawing(ImageOutput(i))
		DrawingMode(#PB_2DDrawing_AllChannels)
		Box(0,0,32,32,#White)
		Circle(15,15,13,#DrawOpaque|($ff<<(i<<3)))
		StopDrawing()
		ico\hbmMask=ImageID(i)
		ico\hbmColor=ImageID(i)
		icons(i)=CreateIconIndirect_(@ico)
		;FreeImage(0)
	Next i

EndProcedure

Procedure WndProc(hWnd, uMsg, wParam, lParam)

	Result = #PB_ProcessPureBasicEvents

	Select uMsg
	Case #WM_DRAWITEM
		*DRAWITEM.DRAWITEMSTRUCT = lParam
		If *DRAWITEM\CtlType = #ODT_COMBOBOX
			SetBkMode_(*DRAWITEM\hDC, #TRANSPARENT)
			If *DRAWITEM\ItemState & #ODS_FOCUS
				FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,Brush)
			ElseIf *DRAWITEM\CtlID = 1
				FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,Brush_2)
			ElseIf  *DRAWITEM\CtlID = 2
				FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,Brush_3)
			EndIf

			SendMessage_(*DRAWITEM\hwndItem,#CB_GETLBTEXT,*DRAWITEM\itemID, @Text$)
			If *DRAWITEM\itemID % 2 = 1
				SelectObject_(*DRAWITEM\hDC,FontID(0))
				SetTextColor_(*DRAWITEM\hDC,$0101FE)
				*DRAWITEM\rcItem\left = 36
				DrawIconEx_(*DRAWITEM\hDC, 8,*DRAWITEM\rcItem\top+2, icons((*DRAWITEM\itemID+1)%3),ComboItemHeight,ComboItemHeight, 0,0,#DI_NORMAL|#DI_COMPAT)
				DrawText_(*DRAWITEM\hDC,@Text$,Len(Text$),*DRAWITEM\rcItem, #DT_SINGLELINE | #DT_VCENTER )
				;TextOut_(*DRAWITEM\hDC,*DRAWITEM\rcItem\left+2,*DRAWITEM\rcItem\top+1,Text$,Len(Text$))
			Else
				SelectObject_(*DRAWITEM\hDC, FontID(0))
				SetTextColor_(*DRAWITEM\hDC, $000000)
				*DRAWITEM\rcItem\left = 36
				DrawIconEx_(*DRAWITEM\hDC, 8,*DRAWITEM\rcItem\top+2, icons((*DRAWITEM\itemID+1)%3),ComboItemHeight,ComboItemHeight, 0,0,#DI_NORMAL|#DI_COMPAT)
				DrawText_(*DRAWITEM\hDC,@Text$,Len(Text$),*DRAWITEM\rcItem,  #DT_SINGLELINE | #DT_VCENTER )
				;TextOut_(*DRAWITEM\hDC, *DrawItem\rcItem\left+2,*DRAWITEM\rcItem\top+1,Text$,Len(Text$))
			EndIf
		EndIf

	EndSelect

	ProcedureReturn Result
EndProcedure

Init()
If OpenWindow(0, 0, 0, 270, 180, "Combo Box Gadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ComboBoxGadget(0, 10, 10, 250, 40,#PB_ComboBox_Editable|#PB_ComboBox_Image)
	ComboBoxGadget(1, 10, 60, 250, 40,#PB_ComboBox_Editable|#CBS_OWNERDRAWFIXED|#CBS_HASSTRINGS)
	ComboBoxGadget(2, 10,110, 250, 40,#PB_ComboBox_Editable|#PB_ComboBox_Image)
	SetWindowCallback(@WndProc())

	ComboItemHeight=SendMessage_(GadgetID(0),#CB_GETITEMHEIGHT,0,0)
	SendMessage_(GadgetID(1),#CB_SETITEMHEIGHT,0,ComboItemHeight)

	For a = 0 To 8
		For n=0 To 2
			AddGadgetItem(n,a,"< - - ComboBox "+Str(n)+", item " + Str(a+1)+" - - >",ImageID(a%3))
		Next n
	Next a

	For a = 0 To 2
		SetGadgetState(a, 0)
		SetGadgetColor(a,#PB_Gadget_FrontColor,#Blue)
		SetGadgetColor(a,#PB_Gadget_BackColor,#Yellow)
	Next a

	Repeat
		; ?
	Until WaitWindowEvent() = #PB_Event_CloseWindow

EndIf