C++中的静态控件背景颜色设置

5

我正在使用Windows API创建一个基本的GUI,但是遇到了问题。它开始于一个带有我设置的自定义背景颜色(RGB(230,230,230))的主窗口。然后,在左上角用静态控件显示文本。

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

这种方法能够实现目标,但是当文本被显示时,我需要一种方式来改变它的背景颜色以匹配主窗口,否则它看起来就像没有融入其中。我的问题是,我该如何做到这一点?我目前使用下面的方法并且它可以工作,但我想知道,是否有一种方法在 CreateWindow 函数之后永久设置背景颜色,而不更改系统颜色,并且仅适用于该控件,而不是向发送 WM_CTLCOLORSTATIC 消息的任何内容。我尝试了在消息循环之外使用 GetDC 函数和 SetBkColor 函数进行实验,但是没有任何效果。
    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));
    }

我希望这样做是因为...

  • 我不想让我的消息循环被需要在每次窗口重绘时调用的函数填满。
  • 使更改仅应用于此静态控件。

如果能提供任何帮助,至少指引我走向正确的方向,我将非常感激,谢谢。


1
你可以通过检查(HWND)lParam == settingstext来限制 WM_CTLCOLORSTATIC 代码的影响范围,仅作用于你的静态控件。你示例中存在一个问题,即创建的所有画刷都永远不会被删除。 - Brian Nixon
3个回答

16

对于静态文本控件,没有永久设置文本颜色或背景的方法。即使您想将更改应用于单个静态控件; 您仍然需要在父dlgproc中处理WM_CTLCOLORSTATIC通知消息,只有当控件即将绘制时才会处理。

这是由于DefWindowProc在处理WM_CTLCOLORSTATIC时每次都会覆盖您对设备上下文所做的更改,正如MSDN所述:

默认情况下,DefWindowProc函数为静态控件选择默认系统颜色。

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;
    }
}

如果您想使控件在父对话框上的背景透明,可以使用 SetBkMode(hdcStatic, TRANSPARENT)


1
你能解释一下为什么在调用了 SetBkColor 后还需要创建 hBrush 来设置背景吗?如果是透明背景,是否还需要一个透明的画刷? - Ameen

2
我认为有一种永久的方法可以实现它。
在创建标签后,使用GetDC()函数获取设备上下文。 然后使用:
SetTextColor(hdcStatic, RGB(0,0,0));
SetBkColor(hdcStatic, RGB(230,230,230)); // Code Copied from the above answer by cpx.

它应该执行。


这不起作用,因为DefWindowProc将在每次处理控件的WM_CTLCOLORSTATIC消息时重置设备上下文对这些更改。MSDN:“默认情况下,DefWindowProc函数会为静态控件选择默认的系统颜色。” - whY

1
你考虑过子类化静态窗口并进行自绘吗?

我不知道那是什么,所以我会快速研究一下子类化。 - contrapsych
基本上,它意味着您将消息发送到静态控件,而不是发送到代码(不要忘记将那些您不处理的消息传递给原始处理程序)。如果您处理背景擦除和绘画消息,则可以使窗口显示任何您想要的内容。 - Jonathan Wood
那么这只会在单个控件上发生,是否还有一种方法可以减少我为该控件创建的自定义过程中的函数数量。基本上,我想表达的是整个“过程中没有很多函数”的意思是,每次必须重新绘制时执行这些函数似乎会减慢应用程序的速度,或者这并不是一个大问题吗? - contrapsych
它不会变慢,因为您的绘制例程将替换当前的例程(无论如何都要绘制)。此外,您不必为每个控件编写绘制例程。您可以使用相同的WndProc子类化多个窗口。我一直这样做。但是,对于您所需的内容可能有些过度。我不完全确定。 - Jonathan Wood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接