2

I have managed to set the colors of static and edit controls when I set all of them to the same color, but I cant figure out how to set the color of just one without affecting the others. I've looked around on the internet but none of the things I find are about how to set color of just one static or edit control. Here is the code I am using at the moment to set the color of all static text fields:

#include <windows.h>

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

HWND staticTextField, staticTextFieldTwo;

char szClassName[ ] = "WindowsApp";

int WINAPI WinMain(HINSTANCE hThisInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpszArgument,
                   int nFunsterStil)

{
    HWND hwnd;
    MSG messages;
    WNDCLASSEX wincl;

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS; 
    wincl.cbSize = sizeof (WNDCLASSEX);

    wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = CreateSolidBrush(RGB(0, 255, 255));

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (
       0,
       szClassName,
       "Windows app",
       WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
       CW_USEDEFAULT,
       CW_USEDEFAULT,
       544,
       375,
       HWND_DESKTOP,
       NULL,
       hThisInstance,
       NULL
    );

    ShowWindow (hwnd, nFunsterStil);

    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }

    return messages.wParam;
}


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
    HDC hdcStatic = (HDC)wParam;

switch (message)
{
    case WM_DESTROY:
        PostQuitMessage (0);
        break;
    case WM_CREATE:

         staticTextField = CreateWindow("STATIC", "static 1", WS_VISIBLE 
         | WS_CHILD, 20, 20, 300, 25, hwnd, NULL, NULL, NULL);


         staticTextFieldTwo = CreateWindow("STATIC", "static2", WS_VISIBLE | 
         WS_CHILD | WS_BORDER, 100, 200, 300, 20, hwnd, NULL, NULL, NULL);

         break;
    case WM_CTLCOLORSTATIC:
        SetTextColor(hdcStatic, RGB(255, 0, 0));
        SetBkColor(hdcStatic, RGB(0, 255, 255));
        return (INT_PTR)CreateSolidBrush(RGB(0, 255, 255));
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
}

return 0;
}
Max
  • 160
  • 3
  • 15
  • 1
    You might consider using a GUI framework such as Qt, wxWidgets, FLTK, and many others. In general, these are much easier to use than windows API and as a bonus, porting to another OS gets much easier, if you intend to do so at some time in the future... – Aconcagua Jul 17 '18 at 08:16

1 Answers1

6

When responding to WM_CTLCOLORSTATIC, check lParam which holds the handle of the control.

CreateSolidBrush creates a GDI object. It should be deleted with DeleteObject otherwise it causes a resource leak. You can declare the brush as static and delete it at the end. Example:

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HBRUSH hbrush = NULL;
    switch(message)
    {
    case WM_DESTROY:
        if (hbrush) DeleteObject(hbrush);
        hbrush = NULL;
        PostQuitMessage(0);
        break;
    case WM_CREATE:
        staticTextField = CreateWindow("STATIC", "static 1", WS_VISIBLE
            | WS_CHILD, 20, 20, 300, 25, hwnd, NULL, NULL, NULL);
        staticTextFieldTwo = CreateWindow("STATIC", "static2", WS_VISIBLE |
            WS_CHILD | WS_BORDER, 100, 200, 300, 20, hwnd, NULL, NULL, NULL);
        break;
    case WM_CTLCOLORSTATIC:
    {
        HDC hdcStatic = (HDC)wParam;
        if(lParam == (LPARAM)staticTextFieldTwo)
        {
            SetTextColor(hdcStatic, RGB(0, 255, 0));
            SetBkColor(hdcStatic, RGB(0, 255, 255));
            if (!hbrush)
                hbrush = CreateSolidBrush(RGB(0, 255, 255));
            return (LRESULT)hbrush;
        }
        break;
    }
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • 1
    @JonathanPotter Thanks, fixed it. – Barmak Shemirani Jul 17 '18 at 08:37
  • 2
    of course your manipulations with `hbrush` assume that only one single window at any time use this window procedure. even if this true in concrete code, solution not nice. correct always associate some class with window and `hbrush` must be class member – RbMm Jul 17 '18 at 09:44
  • @RbMm You are right. I changed it again so that it works with more than one window with `static` brush. This assumes the static brush is always the same color. – Barmak Shemirani Jul 17 '18 at 16:12
  • @Barmak Shemirani Thanks so much! That worked. Just wondering, how would I do the same with buttons? – Max Jul 18 '18 at 00:09
  • You can't do that with buttons. You can use `WM_CTLCOLORBTN` but this only works with *"owner draw"* buttons, it needs `BS_OWNERDRAW` flag. Or you may use *"custom draw"* method. See this Q&A [link](https://stackoverflow.com/questions/20815233) – Barmak Shemirani Jul 18 '18 at 01:05