-1

I'm having an issue changing the color of a button in my winapi app. This is my winproc:

LRESULT CALLBACK WndProc(
    HWND hWnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam
)
{
    HWND A = NULL;
    switch (message) {
    case WM_CREATE:
        A = CreateWindow(
            L"BUTTON",
            L"A",      // Button text 
            WS_TABSTOP | WS_VISIBLE | WS_CHILD,
            0,
            0,
            (maxX) / 2,
            (maxY) / 2,
            hWnd,
            NULL,
            (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
            NULL
        );
        break;
    case WM_DESTROY:
        DestroyWindow(hWnd);
        break;
    case WM_CTLCOLORBTN:
        SetBkColor(GetDC(A), RGB(255, 0, 0));
        return (INT_PTR)CreateSolidBrush(RGB(255, 0, 0));
        break;
    default:
        return DefWindowProc(
            hWnd,
            message,
            wParam,
            lParam
        );
    }
    return 0;
}

I create the button and that works fine, it shows up on the app when I test it in debug mode. The problem is it doesn't seem to want to change color.

I saw that in the docs it says:

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.

So I removed the BS_DEFPUSHBUTTON from the button but it still doesn't work.

Would someone be able to help me make the button a different color?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    You are using the wrong `HDC`, as `A` is null when you process `WM_CTLCOLORBTN`. Use the `HDC` that is provided in the `wParam` of `WM_CTLCOLORBTN` instead. Also, you are leaking the `HBRUSH` that `CreateSolidBrush()` returns. You are responsible for freeing it when the button doesn't need it anymore. That being said, do what the quoted doc says - [use an owner-drawn button](https://learn.microsoft.com/en-us/windows/win32/controls/user-controls-intro) instead. Did you try that yet? – Remy Lebeau Aug 25 '23 at 14:47
  • @RemyLebeau What do you mean by using the wParam of WM_CTLCOLORBTN? – Elliot Scher Aug 25 '23 at 18:45
  • 1
    Every window message has `wParam` and `lParam` values associated with it, which are passed in as parameters to your `WndProc`. If you read the [documentation](https://learn.microsoft.com/en-us/windows/win32/controls/wm-ctlcolorbtn) for `WM_CTLCOLORBTN`, its `wParam` is "*An HDC that specifies the handle to the display context for the button.*" So, when calling `SetBkColor()`, you can replace `GetDC(A)` (which doesn't work anyway since `A` is null) with `(HDC)wParam` instead. – Remy Lebeau Aug 25 '23 at 18:49
  • @ElliotScher Have you seen my answer? It seems meeting your requirements. – Torrecto - MSFT Sep 01 '23 at 08:59

1 Answers1

0

Try to add BS_OWNERDRAW to WS_SYTLE. But If the created button is using visual styles, it won't send WM_CTLCOLORBTN. So I don't think it will have good change. enter image description here

I suggest you use custom-drawing.