【问题标题】:Setting text color of child window设置子窗口的文字颜色
【发布时间】:2019-09-12 12:54:38
【问题描述】:

我正在尝试更改静态控件的文本/背景颜色。我可以通过以下方式做到这一点:

   // This is the 'main' window
   BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
   {
       hInst = hInstance;
       HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW &~WS_MAXIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
    CW_USEDEFAULT, 0, 1035, 764, nullptr, nullptr, hInstance, nullptr);
       ...
   }

   LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
   {
     case WM_CTLCOLORSTATIC:
        {
            MessageBox( NULL, "CTLCOLORSTATIC called", "", MB_OK );
            HDC hdcStatic = (HDC)wParam;
            SetTextColor(hdcStatic, RGB(200, 200, 20));
            SetBkColor(hdcStatic, RGB(10, 10, 10));

            return (INT_PTR)CreateSolidBrush(RGB(30, 30, 30));
        }
        default:
                return DefWindowProc( hWnd, message, wParam, lParam );
   }

但如果我将窗口放在另一个窗口中,子控件文本/背景颜色将保持默认:

    // This is the 'parent' window, which resides in the 'main' window
    HWND parent = CreateWindowEx
    (
        0,
        _TEXT("STATIC"),
        "",
        WS_TABSTOP | WS_VISIBLE  | BS_SOLID | WS_CLIPCHILDREN,
        10, 10, 500, 500,
        hwnd,
        NULL,
        (HINSTANCE)GetWindowLong(hwnd, GWLP_HINSTANCE),
        NULL
    );

    // This is the 'child' window which resides in the 'parent' window
    HWND child = CreateWindowEx
    (
        0,
        _TEXT("STATIC"),
        "SubItem",
        WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_SOLID,
        10, 10, 100, 100,
        parent,
        NULL,
        (HINSTANCE)GetWindowLong(parent, GWLP_HINSTANCE),
        NULL
    );

总之,我有 3 个窗口:

    HWND hwnd;   // the 'main' application window (color changes fine)
    HWND parent; // the 'parent/container' window which is inside the 'main' window (color changes fine)
    HWND child;  // the 'child' window which is inside the 'parent' window (color DOES NOT change)      

即使我将 MessageBox 放在 WM_CTLCOLORSTATIC 中,我看到它在每次绘制子项时都会触发,但不会为子项更改颜色,而只是为父项更改颜色。

据我了解,我需要在主窗口过程中处理消息,但我并不完全清楚如何执行此操作。如果我将 (HWND)lParam 与儿童的 HWND 进行比较,它们是相同的(在默认开关情况下),所以我可以在“默认”部分获得参考,但我不确定我应该如何处理它从那里..

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    case WM_CTLCOLORSTATIC:
    {
        if ((HWND)lParam == child )
            MessageBox( NULL, "Reference Match for CTLCOLORSTATIC", "", MB_OK ); // <-- THIS NEVER TRIGGERS
    }
        ....
    default:
        if ((HWND)lParam == child )
            MessageBox( NULL, "Reference Match for DEFAULT", "", MB_OK ); // <-- THIS DOES TRIGGER

            return DefWindowProc( hWnd, message, wParam, lParam );
        }
        return 0;
}

我将一个窗口放在另一个窗口中的原因是我可以在父级中使用 WS_CLIPCHILDREN 属性(因为子级会移动/滚动)。

【问题讨论】:

  • 显示更多你的代码,不要只是描述它。你也漏刷了。你有 3 层窗户吗?
  • @Andres 对此感到抱歉,我用更多代码更新了我的问题。是的,这是正确的——我有一个“默认/主”窗口,我在其中添加了“父”,而“父”将包含一个子窗口。我无法更新“子”颜色(第三级窗口),但“父”颜色和“主”窗口一样可以更新。
  • WM_CTLCOLORSTATIC:“静态控件,或只读或禁用的编辑控件,发送WM_CTLCOLORSTATIC消息到其父窗口时即将绘制控件。”
  • @IInspectable 感谢您的回复。对不起,但我不清楚如何处理这个问题。这是否意味着我需要将其状态更改为“非只读”,还是需要以另一种方式处理?为什么 1 级和 2 级窗口不是“只读”的,而第三级是?谢谢!
  • 我把相关部分加粗。

标签: c++ winapi


【解决方案1】:

通过阅读MSDN文档,我知道了一个函数SetWindowsLongPtr,它的参数GWLP_WNDPROC可以为窗口过程设置一个新地址。

这个函数可以改变子窗口的文字颜色和背景颜色,也就是说可以触发WM_CTLCOLORSTATIC

但是经过测试发现对辅助窗口无效,也就是说不能改变父窗口的文字颜色。

我也查阅了很多资料,关于三层windows的文档很少。

所以,我觉得要解决这个问题,让三个窗口都改变文字的颜色,你可能得自己重写WndProc,但这很复杂,涉及的东西很多。

编辑:如果只需要更改文本颜色和背景颜色 的静态控件,您可以自定义一个控件,以便您可以 处理它的所有操作。

希望能帮到你。

【讨论】:

    【解决方案2】:

    WM_CTLCOLORSTATIC 由静态控件发送到其父窗口,而不是顶级窗口。

    hwndMain: WM_CTLCOLORSTATIC for hwnd1
    |    
    \--hwnd1: WM_CTLCOLORSTATIC for hwnd2 (You might have to subclass hwnd1)
       |
       \--hwnd2
    

    您还泄漏了画笔,请在创建窗口时将来自CreateSolidBrush 的画笔存储在某处,并在窗口被销毁时将其删除。

    【讨论】:

      猜你喜欢
      • 2015-10-23
      • 1970-01-01
      • 2018-02-23
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多