使非客户区无效
Posted
技术标签:
【中文标题】使非客户区无效【英文标题】:Invalidating non-client areas 【发布时间】:2011-02-18 16:21:27 【问题描述】:我有一个具有自定义边框/标题的窗口,为此我处理 WM_NCPAINT 消息。我的标题有两个背景,一个用于活动窗口的较亮背景,一个用于背景窗口的较暗背景。
但在某些情况下,例如当窗口失去/获得焦点时,我的标题没有更新,所以我以错误的背景结束。
到目前为止,我已经处理了 WM_NCACTIVATE,并发送了 RedrawWindow(hwnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE),但这会导致整个窗口重新绘制。您对此有什么建议吗?
【问题讨论】:
【参考方案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
,而前者发送如果窗口被移动/调整大小会发生的所有消息。以上是关于使非客户区无效的主要内容,如果未能解决你的问题,请参考以下文章
Invalidate() InvalidateRect() 与 UpdateWindow()