【问题标题】:Invalidating non-client areas使非客户区无效
【发布时间】:2011-02-18 16:21:27
【问题描述】:

我有一个具有自定义边框/标题的窗口,为此我处理 WM_NCPAINT 消息。我的标题有两个背景,一个用于活动窗口的较亮背景,一个用于背景窗口的较暗背景。

但在某些情况下,例如当窗口失去/获得焦点时,我的标题没有更新,所以我以错误的背景结束。

到目前为止,我已经处理了 WM_NCACTIVATE,并发送了 RedrawWindow(hwnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE),但这会导致整个窗口重新绘制。您对此有什么建议吗?

【问题讨论】:

    标签: c++ windows gdi


    【解决方案1】:

    覆盖非客户区总是充满危险。窗口管理器似乎为优化做了很多假设。显然它可以完成,请参阅 Office,但可能需要大量实验。

    只是一个想法。调用 RedrawWindow 两次,一次使非客户区无效,然后再次使客户区有效。

    RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
    RedrawWindow(hwnd, NULL, NULL, RDW_NOFRAME | RDW_VALIDATE);
    

    另一个想法是尝试立即仅绘制框架,而不会使任何内容无效:

    RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_UPDATENOW | RDW_NOCHILDREN);
    

    还有一个想法是在第二个或第三个参数中指定一个空的 RECT 或 HREGION。这样可能不会使客户区无效。

    【讨论】:

    • 我尝试使用 VALIDATE 标志,但没有按预期工作。当需要更新某些子控件时,VALIDATE 将阻止这种情况。最后我做了类似于你的第二个建议的事情,我传递了一个区域,它是窗口矩形减去客户端矩形,这些似乎适用于矩形窗口但不适用于非矩形窗口,这很好对我来说足够了。
    • 我相信RDW_VALIDATE 的意思是第二行的RDW_INVALIDATE
    • @Paul:不,我打算RWD_VALIDATE。我想我没有足够清楚地解释我的假设。框架失效似乎使整个窗口失效。所以我猜然后验证客户区只会使非客户区无效。无论如何,伊斯梅尔的评论说这并没有解决问题。起作用的是最后一个关于提供空 RECT 或 HREGION 的建议。
    【解决方案2】:

    其实这样就行了:

    SetWindowPos(hwnd, 0, 0, 0, 0, 0,
        SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
    

    【讨论】:

    • 这样做实际上有很多开销。在 Spy++ 中使用 SetWindowPos()RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); 观看它,后者只是发送一个 WM_NCPAINT,而前者发送如果窗口被移动/调整大小会发生的所有消息。
    猜你喜欢
    • 2011-01-16
    • 1970-01-01
    • 2020-02-24
    • 2017-01-19
    • 1970-01-01
    • 2010-09-11
    • 2018-04-27
    • 2021-12-15
    相关资源
    最近更新 更多