Static Control Background Color with C++
Asked Answered
R

3

6

I am creating a basic GUI with the Windows API and I have run into an issue. It starts with a main window that opens with a custom background color I set (RGB(230,230,230)). It then displays text in the upper left corner with the static control.

settingstext = CreateWindow("STATIC",
                             "SETTINGS",
                             SS_LEFT | WS_CHILD,
                             12,
                             20,
                             100,
                             20,
                             hwnd,
                             NULL,
                             proginstance,
                             NULL);
ShowWindow(settingstext, 1);

This works, but when the text is displayed I need a way to change the background of it to match the main window or else it just looks like it doesn't blend in.

My question is, how do I do this? I currently use the method below and it works, but I wanted to know, is there a way to permanently set the background color somehow, right after the CreateWindow function for the static control without changing system colors, and just have it apply to that one control and not anything that sends the WM_CTLCOLORSTATIC message. I have experimented around with using the GetDC function and SetBkColor function outside of the message loop but nothing works.

    case WM_CTLCOLORSTATIC:
    {
    HDC hdcStatic = (HDC) wParam;
    SetTextColor(hdcStatic, RGB(0,0,0));
    SetBkColor(hdcStatic, RGB(230,230,230));
    return (INT_PTR)CreateSolidBrush(RGB(230,230,230));
    }

I want to do this because...

  • I don't want to fill up my message loop with functions that need to be called every time the window repaints.
  • Have the changes apply to only this static control.

I would be very thankful for any help that could be provided, at least pointing me in the right direction, thanks.

Rives answered 21/12, 2010 at 1:6 Comment(1)
You can restrict the effect of the WM_CTLCOLORSTATIC code to just your static control by checking that (HWND)lParam == settingstext. There's a problem with your example in that all those brushes you create will never get deleted.Zooplasty
V
16

For static text controls there's no permanent way to set the text color or their background. Even if you want to apply the changes to a single static control; you would still have to handle WM_CTLCOLORSTATIC notification message in parent dlgproc just when the control is about to be drawn.

This is due to the DefWindowProc overwriting your changes to the device context each time it handles WM_CTLCOLORSTATIC as stated in the MSDN:

By default, the DefWindowProc function selects the default system colors for the static control.

static HBRUSH hBrush = CreateSolidBrush(RGB(230,230,230));

case WM_CTLCOLORSTATIC:
{
    if (settingstext == (HWND)lParam)

              //OR if the handle is unavailable to you, get ctrl ID

    DWORD CtrlID = GetDlgCtrlID((HWND)lParam); //Window Control ID
    if (CtrlID == IDC_STATIC1) //If desired control
    {
       HDC hdcStatic = (HDC) wParam;
       SetTextColor(hdcStatic, RGB(0,0,0));
       SetBkColor(hdcStatic, RGB(230,230,230));
       return (INT_PTR)hBrush;
    }
}

If you're looking to make the control's background transparent over a parent dialog you could use SetBkMode(hdcStatic, TRANSPARENT).

Vitavitaceous answered 21/12, 2010 at 2:30 Comment(1)
Can you explain why you need to create hBrush for the background if you already called SetBkColor? And in case of transparent background do you need also a transparent brush?Oscillograph
K
1

Have you considered subclassing the static window and doing owner draw?

Krahmer answered 21/12, 2010 at 1:9 Comment(4)
I have no idea what that is so I'll do some quick research on subclassing.Rives
Basically, it means you have messages sent to the static control to instead go to your code (don't forget to pass those you don't handle to the original handler). If you handle the background erase and paint messages, then you can have the window display anything you want.Krahmer
So that would make it only happen on that single control, is there also a way to reduce the number of functions in the custom procedure I would make for that control. Basically what I'm getting at with the whole "not very many functions in the procedure" thing is that it seems like it would slow the application down having to perform those functions every time it must repaint, or is it not really a big deal?Rives
It would not be slower because your paint routines would replace the current ones (it's going to be painted anyway). Also, you don't have write paint routines for every control you subclass. You can subclass multiple windows with the same WndProc. I do this all the time. Still, it may be overkill for what you need. I'm not completely sure.Krahmer
S
1

I think there is a permanent way to do it.

Just after you create the label,use GetDC() function to get the Device Context. Then use:

SetTextColor(hdcStatic, RGB(0,0,0));
SetBkColor(hdcStatic, RGB(230,230,230)); // Code Copied from the above answer by cpx.

And it should do .

Solferino answered 8/2, 2015 at 13:29 Comment(1)
This doesn't work because the DefWindowProc will reset these changes to the device context each time it handles the WM_CTLCOLORSTATIC message for the control. MSDN: "By default, the DefWindowProc function selects the default system colors for the static control."Kinswoman

© 2022 - 2024 — McMap. All rights reserved.