2
votes

A ComboBox has its color in white when created. I want to change is appearance so that it is colored (not the backgrouond color). I am using native winapi and don't know how to do it. I googled and I could find examples of changing the background color by handling the WM_CTLCOLORLISTBOX but that is not what I want. I also have the hint from google that I should subclass the ComboBox and handle the WM_NCPAINT message, but there is just no example the can achieve the effect I want. I have been battling this for few days with no luck. Any help is appreciated.

enter image description hereenter image description here

1
What's wrong with WM_CTLCOLORLISTBOX ? Does it not work? (That's entirely possible, I don't know for sure as I myself use ownerdraw, and that might be your best option here although it's more work, obviously). But forget that Google hint, that's way wrong.Paul Sanders
Passable ownerdraw sample code here.Paul Sanders
That's a combobox, not listbox. The style is either drop-down or drop-list, I can't tell. Do you want to redraw the button section in one style, and leave the drop-down list in a different style?Barmak Shemirani
@Paul, I meant the Green part of the combo, not the dropdown part of it. WCM_CTLCOLORLISTBOX allows the change of the dropdown of it.simon
@Paul, the suggested link does not apply to my question as it is about how to color the seleted item in the dropdown list. What I want is to paint the button (the green) part of it in the image above. I've also tried ownerdraw control but no luck. Much appreciate if you could share a relevant example.simon

1 Answers

4
votes

If Visual Style is enabled you can subclass the combobox and override WM_PAINT. This works only for CBS_DROPDOWNLIST (resource editor calls it "Drop List"). You have to manually draw a drop down arrow.

#include <Windows.h>
#include <CommCtrl.h>

#pragma comment(lib, "Comctl32.lib")

LRESULT CALLBACK ComboProc(HWND hwnd, UINT msg, WPARAM wParam,
    LPARAM lParam, UINT_PTR uIdSubClass, DWORD_PTR)
{
    switch(msg)
    {
    case WM_PAINT:
    {
        DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE);
        if(!(style & CBS_DROPDOWNLIST))
            break;

        RECT rc;
        GetClientRect(hwnd, &rc);

        PAINTSTRUCT ps;
        auto hdc = BeginPaint(hwnd, &ps);
        auto bkcolor = RGB(80, 140, 0);
        auto brush = CreateSolidBrush(bkcolor);
        auto pen = CreatePen(PS_SOLID, 1, RGB(128, 128, 128));
        auto oldbrush = SelectObject(hdc, brush);
        auto oldpen = SelectObject(hdc, pen);
        SelectObject(hdc, (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0));
        SetBkColor(hdc, bkcolor);
        SetTextColor(hdc, RGB(255, 255, 255));

        Rectangle(hdc, 0, 0, rc.right, rc.bottom);

        if(GetFocus() == hwnd)
        {
            RECT temp = rc;
            InflateRect(&temp, -2, -2);
            DrawFocusRect(hdc, &temp);
        }

        int index = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
        if(index >= 0)
        {
            int buflen = SendMessage(hwnd, CB_GETLBTEXTLEN, index, 0);
            TCHAR *buf = new TCHAR[(buflen + 1)];
            SendMessage(hwnd, CB_GETLBTEXT, index, (LPARAM)buf);
            rc.left += 5;
            DrawText(hdc, buf, -1, &rc, DT_EDITCONTROL|DT_LEFT|DT_VCENTER|DT_SINGLELINE);
            delete[]buf;
        }

        SelectObject(hdc, oldpen);
        SelectObject(hdc, oldbrush);
        DeleteObject(brush);
        DeleteObject(pen);

        EndPaint(hwnd, &ps);
        return 0;
    }

    case WM_NCDESTROY:
    {
        RemoveWindowSubclass(hwnd, ComboProc, uIdSubClass);
        break;
    }

    }

    return DefSubclassProc(hwnd, msg, wParam, lParam);
}

Usage:

INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lParam)
{
    static HBRUSH hbrBkgnd = CreateSolidBrush(RGB(0, 255, 0));
    switch(msg)
    {
    case WM_INITDIALOG:
    {
        HWND hcombo = GetDlgItem(hwnd, IDC_COMBO1);
        SetWindowSubclass(hcombo, ComboProc, 0, 0);
        ...
        break;
    }
    ...
}