Invalidating non-client areas
Asked Answered
W

2

10

I've a window which has custom border/caption, in order to do that I handle WM_NCPAINT message. My caption has two backgrounds a brighter one for the active window, and a darker one for the background window.

But under some circumstances, for example when the window loses/gain focus, my caption is not updated so I end with the wrong background.

Until now I've handled WM_NCACTIVATE, and send a RedrawWindow(hwnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE), but this causes the whole window to repaint. Do you have any advice about this?

Wrung answered 12/5, 2010 at 14:52 Comment(0)
U
7

Overriding non-client area is always fraught with peril. It seems the Window manager makes a lot of assumptions for optimization. Clearly it can be done, see Office, but it might take a lot of experimentation.

Just an idea. Call RedrawWindow twice, once to invalidate the non-client area then again to validate the client area.

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

Another idea is to try to paint just the frame immediately, without invalidating anything:

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

Yet another idea is to specify an empty RECT or HREGION in the 2nd or 3rd parameters. It might not invalidate the client area that way.

Understructure answered 11/8, 2010 at 19:42 Comment(3)
I've tried to use the VALIDATE flag but it didn't work as desired. When some of the childs controls needed to be updated VALIDATE will prevent that. In the end I've done something similar to your second suggestion, I pass a region which is the window rect minus the client rect, these seems to work the case of rectangular windows but doesn't for non-rect windows, which is good enough for me.Wrung
I believe that RDW_VALIDATE meant to be RDW_INVALIDATE on the second line?Evasion
@Paul: No, I intended RWD_VALIDATE. I guess I didn't explain my hypothesis clearly enough. The frame invalidation seemed to be invalidating the entire window. So my guess what that then validating the client area would leave only the non-client area invalid. No matter, Ismael's comment says that didn't solve the problem. What did work was the very last suggestion about providing an empty RECT or HREGION.Understructure
L
6

Actually, this does the trick:

SetWindowPos(hwnd, 0, 0, 0, 0, 0,
    SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
Lorenza answered 18/12, 2015 at 11:45 Comment(1)
There is actually a lot of overhead in doing it this way. Watch it in Spy++ using SetWindowPos() vs. RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); the latter simply sends a WM_NCPAINT while the former sends all the messages that would occur if the window was moved/sized.Peary

© 2022 - 2024 — McMap. All rights reserved.