Page 1 of 1

Coloring individual items in a ComboBox

Posted: Wed Jul 14, 2010 9:41 am
by merendo
Hiya folks!

I guess the subject already tells it all. In my app I need to selectively apply a color to individual items within a ComboBoxGadget, either to the text or to the background, doesn't really matter. I know that coloring the entire ComboBox is easy, but there seems to be no PB way to do this with individual items, leaving out the rest...

Is there any way to do this? Searching the purearea code archive as well as this forum hasn't turned up anything yet....

Thanks for any help on this one...

Re: Coloring individual items in a ComboBox

Posted: Wed Jul 14, 2010 11:27 am
by netmaestro
Ownerdraw is the only way I know of for that. It isn't native to PB for comboboxes.

Code: Select all

Procedure WinProc(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents

  Select msg 
  
    Case #WM_DRAWITEM 
      *dis.DRAWITEMSTRUCT = lparam
      If *dis\ctlid = 1 ; This gets changed to your gadget#
        With *dis
          text$ = GetGadgetItemText(\ctlid, \itemid)
          If \itemstate & #ODS_SELECTED  
            hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
            oldbrush = SelectObject_(\hdc, hBrush)
            FillRect_(\hdc, \rcitem, hBrush)
            DeleteObject_(hBrush)
            DrawFocusRect_(\hdc, \rcitem)
            SelectObject_(\hdc, oldbrush)
            SetBkColor_( \hdc, GetSysColor_(#COLOR_HIGHLIGHT))
            TextOut_( \hdc, \rcItem\left+5, \rcItem\top+1, text$, Len(text$))
          Else
            If \itemID%2
              hBrush = CreateSolidBrush_(#White)
              SetBkColor_( \hdc, #White)
            Else
              hBrush = CreateSolidBrush_(RGB(220,220,228))
              SetBkColor_(\hdc, RGB(220,220,228))
            EndIf
            oldbrush = SelectObject_(\hdc, hBrush)
            FillRect_(\hdc, \rcitem, hBrush)
            DeleteObject_(hBrush)
            SelectObject_(\hdc, oldbrush)
            TextOut_( \hdc, \rcItem\left+5, \rcItem\top+1, text$, Len(text$))
          EndIf
        EndWith
      EndIf
    
;     Only use for #CBS_OWNERDRAWVARIABLE:      
;
;     Case #WM_MEASUREITEM
;       *mis.MEASUREITEMSTRUCT = lparam
;       If *mis\ctlid = 1  ; This gets changed to your gadget#
;         *mis\itemheight = 24
;       EndIf      

  EndSelect
  
  ProcedureReturn result
  
EndProcedure

OpenWindow(0, 0, 0, 270, 140, "ComboBoxGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
SetWindowCallback(@WinProc())
ComboBoxGadget(1, 10, 40, 250, 23, #CBS_OWNERDRAWFIXED|#CBS_HASSTRINGS)

For a = 1 To 15
  AddGadgetItem(1, -1,"ComboBox item " + Str(a))
Next
SetGadgetState(1, 1) 

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Coloring individual items in a ComboBox

Posted: Sat Jul 17, 2010 1:22 pm
by merendo
Thanks for your snippet. This example colours every second item in the list. Is there a way to color only, say, one item or an item at a specific location? I imagine it has to do with the \itemID. What value does this variable hold?

Re: Coloring individual items in a ComboBox

Posted: Sat Jul 17, 2010 1:30 pm
by netmaestro
It holds the zero-based index of the item. You can use it to identify and color any item you want.

Re: Coloring individual items in a ComboBox

Posted: Sat Jul 17, 2010 1:42 pm
by merendo
Is it the same thing as the PureBasic item number?

Re: Coloring individual items in a ComboBox

Posted: Sat Jul 17, 2010 3:20 pm
by RASHAD

Code: Select all

Global Text$ = Space(256)

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 
          Brush = CreateSolidBrush_($C1C1C1) 
          FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,Brush) 
          DeleteObject_(Brush)
        Else 
          FillRect_(*DRAWITEM\hDC,*DRAWITEM\rcItem,GetStockObject_(#WHITE_BRUSH)) 
        EndIf                  
        SendMessage_(*DRAWITEM\hwndItem,#CB_GETLBTEXT,*DRAWITEM\itemID, @Text$)        
        If *DRAWITEM\itemID = 0 Or *DRAWITEM\itemID = 1                             ;index 0 and 1 in Red color
          SetTextColor_(*DRAWITEM\hDC,$0101FE)  
          TextOut_(*DRAWITEM\hDC,*DRAWITEM\rcItem\left+2,*DRAWITEM\rcItem\top+1,Text$,Len(Text$))
        Else
          SetTextColor_(*DRAWITEM\hDC, $000000)
          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 ) 
    
  ContainerGadget(0,20,20,200,26)
  SetGadgetColor(0,#PB_Gadget_BackColor,$000000)  
  ComboBoxGadget(1,2,2,196, 22,#CBS_OWNERDRAWFIXED)
  CloseGadgetList()
  
  AddGadgetItem(1,-1, "Test1") 
  AddGadgetItem(1,-1, "Test2") 
  AddGadgetItem(1,-1, "Test3") 
  
  SetWindowCallback(@WndProc())
Repeat 
Until WaitWindowEvent() = #PB_Event_CloseWindow 

End 

Re: Coloring individual items in a ComboBox

Posted: Mon Jul 26, 2010 11:24 pm
by netmaestro
Is it the same thing as the PureBasic item number?
Sure. It's just a different way of retrieving it.