2 out of 6 rated this helpful - Rate this topic

WM_CTLCOLORBTN message

Applies to: desktop apps only

The WM_CTLCOLORBTN message is sent to the parent window of a button before drawing the button. The parent window can change the button's text and background colors. However, only owner-drawn buttons respond to the parent window processing this message.

WM_CTLCOLORBTN

    WPARAM wParam;
    LPARAM lParam; 

Parameters

wParam

An HDC that specifies the handle to the display context for the button.

lParam

An HWND that specifies the handle to the button.

Return value

If an application processes this message, it must return a handle to a brush. The system uses the brush to paint the background of the button.

Remarks

If the application returns a brush that it created (for example, by using the CreateSolidBrush or CreateBrushIndirect function), the application must free the brush. If the application returns a system brush (for example, one that was retrieved by the GetStockObject or GetSysColorBrush function), the application does not need to free the brush.

By default, the DefWindowProc function selects the default system colors for the button. Buttons with the BS_PUSHBUTTON, BS_DEFPUSHBUTTON, or BS_PUSHLIKE styles do not use the returned brush. Buttons with these styles are always drawn with the default system colors. Drawing push buttons requires several different brushes-face, highlight, and shadow-but the WM_CTLCOLORBTN message allows only one brush to be returned. To provide a custom appearance for push buttons, use an owner-drawn button. For more information, see Creating Owner-Drawn Controls.

The WM_CTLCOLORBTN message is never sent between threads. It is sent only within one thread.

The text color of a check box or radio button applies to the box or button, its check mark, and the text. The focus rectangle for these buttons remains the system default color (typically black). The text color of a group box applies to the text but not to the line that defines the box. The text color of a push button applies only to its focus rectangle; it does not affect the color of the text.

If a dialog box procedure handles this message, it should cast the desired return value to a INT_PTR and return the value directly. If the dialog box procedure returns FALSE, then default message handling is performed. The DWL_MSGRESULT value set by the SetWindowLong function is ignored.

Requirements

Minimum supported client

Windows 2000 Professional

Minimum supported server

Windows 2000 Server

Header

Winuser.h (include Windows.h)

See also

Other Resources
RealizePalette
SelectPalette

 

 

Send comments about this topic to Microsoft

Build date: 3/6/2012

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
WM_CTLCOLORBTN bug
WM_CTLCOLORBTN does not perform as intended on Windows XP SP2/SP3 (and others?).

To properly change the foreground and background color of BUTTON types (and others)
Use the WM_CTLCOLORSTATIC message. You DO NOT use the BS_OWNERDRAW style!

Example code (using a BUTTON, with style BS_AUTORADIOBUTTON):

LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

    switch (msg) {
        case WM_CTLCOLORSTATIC: {
            if ((HWND)lParam == filterNameOff) {
            static HBRUSH hBrushColor;

                if (!hBrushColor) {
                    hBrushColor = CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF)); // White background is returned
                    SetBkColor((HDC)wParam, RGB(0xFF, 0xFF, 0xFF));          // White background for text
                }

                // Background color that is used to repaint the control (doesn't affect text background)
                return (LRESULT)hBrushColor;
            }
        }

    ....

Welcome! I hope this helps save somebody from a plethora of stress!
Application must destroy the brush later.
It is the application's responsibility to destroy the returned brush, although obviously not before it has been painted with.

As a result, if a non-stock brush is returned then the application must keep track of it for later disposal, otherwise it will leak the GDI object.

(This is mentioned in the WinCE documentation but seems to be missing from here.)

Return value cast (corrected)
The return value should be cast into an INT_PTR, not a BOOL (this has been corrected).

Edit2: Also, the SetDlgMsgResult() macro, defined in <windowsx.h>, as of Visual 2008, still casts the result to a BOOL too when the message is one of these.
Vista Issue
Windows Vista will ignore return value of this message if it will be GetStockObject(HOLLOW_BRUSH) - transparent brush is ignored. Any other color(white, gray, black etc.) will be preserved and background is painted with selected brush.
Value
WM_CTLCOLORBTN = &H135