使非客户区无效

Ism*_*ael 7 c++ windows gdi

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

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

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

thi*_*ims 6

实际上,这样做可以解决问题:

SetWindowPos(hwnd, 0, 0, 0, 0, 0,
    SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
Run Code Online (Sandbox Code Playgroud)

  • 这样做实际上有很多开销。在 Spy++ 中使用 `SetWindowPos()` 与 `RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);` 进行观察,后者只是发送一个 `WM_NCPAINT`,而前者发送窗口移动时会发生的所有消息/大小。 (4认同)

Adr*_*thy 5

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

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

RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
RedrawWindow(hwnd, NULL, NULL, RDW_NOFRAME | RDW_VALIDATE);
Run Code Online (Sandbox Code Playgroud)

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

RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_UPDATENOW | RDW_NOCHILDREN);
Run Code Online (Sandbox Code Playgroud)

另一个想法是在第二个或第三个参数中指定一个空的 RECT 或 HREGION。它可能不会以这种方式使客户区无效。