Mordachai
Mordachai

Reputation: 9662

How Do I Set the Background Color of buttons including a Checkbox button?

How Do I Set the Background Color of buttons including a Checkbox button?

I struggled to find the answer to this today - thinking it should be simple to answer this, but the information I stumbled on was less than helpful, so at the risk of duplicating stuff that's out there but I couldn't find, I'll make this quick'n'dirty how-to...

Upvotes: 0

Views: 2527

Answers (1)

Mordachai
Mordachai

Reputation: 9662

All 'Button' class windows send WM_CTLCOLORSTATIC to their parent window, which can then call ::SetBkColor((HDC)wParam, rgbBkColor), and return a brush for that color.

If this is all using system colors, then the brush handle doesn't need to be managed, you can simply ask for the ::GetSysColor(sysIndex), and return the ::GetSysColorBrush(sysIndex) for the returned brush.

If you're using a custom color, then you'll need to create your own brush and manage the handle for that.

I needed this code for a Message Box replacement, which has the upper part using a white background, and the lower part using a gray background, per the Windows standard message box. So my static control (icon) needed to be white, while my other buttons (including a "Don't ask again" checkbox) needed to have a gray background (checkboxes normally have a white background).

So, I handle WM_ERASEBKGND to paint the two portions of the background correctly, and then I handle WM_CLTLCOLORSTATIC to ensure that all buttons are properly "transparent" for the background that they appear on. In my case, the I used a "Static" control for the icon, which draws its background in gray, and a couple of push-buttons plus a checkbox button - which a checkbox button always paints its background in white, so both required a fix.

My example is using MFC, but hopefully you can translate that trivially enough for your purposes:

// add to the message map:

    ON_MESSAGE(WM_CTLCOLORSTATIC, OnCtlColorStatic)

// create the implementation:

LRESULT CRTFMessageBox::OnCtlColorStatic(WPARAM wParam, LPARAM lParam)
{
    // buttons and static controls (icon) send WM_CTLCOLORSTATIC, so we can force them to use the correct background color here...
    const HDC hdc = (HDC)wParam;
    const int idc = ::GetDlgCtrlID((HWND)lParam);

    // choose a system color or brush based on if this is icon (static) or another control (a button)
    const int idx = idc == IDC_STATIC ? COLOR_WINDOW : COLOR_3DFACE;

    // select system color
    ::SetBkColor(hdc, GetSysColor(idx));

    // return system brush (which we don't need to delete!)
    return (LRESULT)GetSysColorBrush(idx);
}

Upvotes: 3

Related Questions