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.
2
votes
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;
}
...
}
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