3

So I was trying to set a ComboBox's background & text color using Common-Controls & WINAPI. I did manage to set the background & text color of the combo box itself, but the colors of its dropdown list remain the same.

Here is pretty much what I did: When creating the combo box, I used the CBS_DROPDOWNLIST style (along with WS_VISIBLE & WS_CHILD). Then in the window handler function, I handled the CTLCOLOR_LISTBOX messge in the following way:

SetBkMode(dc, OPAQUE);
SetTextColor(dc, RGB(255, 255, 255));
SetBkColor(dc, 0x383838);
comboBrush = CreateSolidBrush(0x383838); //global var
return (LRESULT)comboBrush;

As I said, this only colors the combobox itself, and not its drop-down list. How can I can color the drop down list as well?

aviad1
  • 354
  • 1
  • 10

1 Answers1

4

For the background color and text color of the combo box, you can handle the WM_CTLCOLORLISTBOX and WM_CTLCOLOREDIT messages respectively.

WM_CTLCOLORLISTBOX : Sent to the parent window of a list box before the system draws the list box. By responding to this message, the parent window can set the text and background colors of the list box by using the specified display device context handle.

Some code:

   // Create Combox control
   int xpos = 100;            // Horizontal position of the window.
   int ypos = 100;            // Vertical position of the window.
   int nwidth = 200;          // Width of the window
   int nheight = 200;         // Height of the window
   HWND hwndParent = hWnd; // Handle to the parent window

   hWndComboBox = CreateWindow(WC_COMBOBOX, TEXT(""),
       CBS_DROPDOWNLIST | WS_CHILD |  WS_VISIBLE, 
       xpos, ypos, nwidth, nheight, hwndParent, NULL, hInstance,
       NULL);

   // load the combobox with item list.  
   // Send a CB_ADDSTRING message to load each item

   TCHAR Planets[9][10] =
   {
       TEXT("Mercury"), TEXT("Venus"), TEXT("Terra"), TEXT("Mars"),
       TEXT("Jupiter"), TEXT("Saturn"), TEXT("Uranus"), TEXT("Neptune"),
       TEXT("Pluto??")
   };

   TCHAR A[16];
   int  k = 0;

   memset(&A, 0, sizeof(A));
   for (k = 0; k <= 8; k += 1)
   {
       wcscpy_s(A, sizeof(A) / sizeof(TCHAR), (TCHAR*)Planets[k]);

       // Add string to combobox.
       SendMessage(hWndComboBox, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
   }

   // Send the CB_SETCURSEL message to display an initial item 
   //  in the selection field  
   SendMessage(hWndComboBox, CB_SETCURSEL, (WPARAM)2, (LPARAM)0);

   ...

Updated:

//Windows Process
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {    
    case WM_CTLCOLORLISTBOX:
    {       
        COMBOBOXINFO info;
        info.cbSize = sizeof(info);
        SendMessage(hWndComboBox, CB_GETCOMBOBOXINFO, 0, (LPARAM)&info);
        COMBOBOXINFO info1;
        info1.cbSize = sizeof(info1);
        SendMessage(hWndComboBox1, CB_GETCOMBOBOXINFO, 0, (LPARAM)&info1);

        if ((HWND)lParam == info.hwndList)
        {
            HDC dc = (HDC)wParam;
            SetBkMode(dc, OPAQUE);
            SetTextColor(dc, RGB(255, 255, 0));
            SetBkColor(dc, 0x383838); //0x383838
            HBRUSH comboBrush = CreateSolidBrush(0x383838); //global var
            return (LRESULT)comboBrush;
        } 
        if ((HWND)lParam == info1.hwndList)
        {
            HDC dc = (HDC)wParam;
            SetBkMode(dc, OPAQUE);
            SetTextColor(dc, RGB(255, 0, 0));
            SetBkColor(dc, RGB(0, 0, 255)); 
            HBRUSH comboBrush = CreateSolidBrush(RGB(0, 0, 255)); 
            return (LRESULT)comboBrush;
        }
    }
    case WM_CTLCOLOREDIT:
    {
        HWND hWnd = (HWND)lParam;
        HDC dc = (HDC)wParam;
        if (hWnd == hWndComboBox)
        {
            SetBkMode(dc, OPAQUE);
            SetTextColor(dc, RGB(255, 0, 255));
            SetBkColor(dc, 0x383838); //0x383838
            HBRUSH comboBrush = CreateSolidBrush(0x383838); //global var
            return (LRESULT)comboBrush;
        }
        else if (hWnd == hWndComboBox1)
        {
            SetBkMode(dc, OPAQUE);
            SetTextColor(dc, RGB(255, 255, 0));
            SetBkColor(dc, RGB(0, 255, 0)); 
            HBRUSH comboBrush = CreateSolidBrush(RGB(0, 255, 0)); 
            return (LRESULT)comboBrush;
        }
    }
    ...

Change the background color by comparing the edit handle and listbox handle returned by the window.

Debug:

enter image description here

Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • The given handle (lParam) in the `WM_CTLCOLOREDIT` message seems to not be the combobox's handle. Is there any other way to identify the combo box inside of the window handler? what if I want to have two combo boxes for example, each one with a different color? – aviad1 Jun 29 '20 at 22:55
  • Thanks a lot! That's exactly what I was looking for – aviad1 Jun 30 '20 at 19:58
  • For selected item background color, need owner-drawn ComboBox. – RCECoder Jul 31 '23 at 06:44