Difference Between Invalidaterect and Redrawwindow

Difference between InvalidateRect and RedrawWindow

InvalidateRect does not immediately redraw the window. It simply "schedules" a future redraw for a specific rectangular area of the window. Using InvalidateRect you may schedule as many areas as you want, making them accumulate in some internal buffer. The actual redrawing for all accumulated scheduled areas will take place later, when the window has nothing else to do. (Of course, if the window is idle at the moment when you issue the InvalidateRect call, the redrawing will take place immediately).

You can also force an immediate redraw for all currently accumulated invalidated areas by calling UpdateWindow. But, again, if you are not in a hurry, explicitly calling UpdateWindow is not necessary, since once the window is idle it will perform a redraw for all currently invalidated areas automatically.

RedrawWindow, on the other hand, is a function with a much wider and flexible set of capabilities. It can be used to perform invalidation scheduling (i.e. the same thing InvalidateRect does) or it can be used to forcefully perform immediate redrawing of the specified area, without doing any "scheduling". In the latter case calling RedrawWindow is virtually equivalent to calling InvalidateRect and then immediately calling UpdateWindow.

What are the differences between RedrawWindow and UpdateWindow in Win32?

RedrawWindow is typically used to force a redraw of the entire window (or some specified region within) right now.

UpdateWindow will force a redraw of only the update region of the window, i.e. that part of the window that has been invalidated (e.g. by calling InvalidateRect) since the last paint cycle.

c++: RedrawWindow() Flickering

The flickering happens because painting is in most normal windows a two phase operation. 1. The background is erased, 2. The window is repainted.

So the problem is the child window that needs redrawing. There are a lot of articles about non flickering painting.

Also you can optimize the redrawing in just invalidating just the parts of windows that are affected. You force a redraw of the complete windows. That isn't ideal. In such a case a large portion of the window might flicker.

BTW: RedrawWindow with the specific flags are better than calling Invalidate/Update sequences and may be a tick faster.

Also it may be better to use a method to draw Bars with an XOR-Paining during dragging. And update the window size when the LButtonUp-Event happens. The way CSplitterWnd is doing it... you have the source. Look into it.

Invalidating non-client areas

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.

Behavior of WS_CLIPCHILDREN and InvalidateRect in Windows 7

You can try calling RedrawWindow, passing flags RDW_INVALIDATE and RDW_ALLCHILDREN.

Edit:

To redraw the background, you can add RDW_ERASE. If you want to redraw the background on the parent but not the children, call both RedrawWindow and InvalidateRect(...,TRUE).

InvalidateRect is not repainting the window

it just paints another polygon without erasing the other one

When you call BeginPaint, the system will normally call WM_ERASEBKGND before returning. The WM_ERASEBKGND handler is then given a chance to "erase" the window. The default handler (from DefWndProc) will fill the area with the brush from the WNDCLASS for this window.

It sounds like the erasing isn't happening which can mean: (1) you've provided WM_ERASEBKGND handler that doesn't actually erase the screen, or (2) the hbrBackground in the WNDCLASS is set wrong or set to the null brush.

In either of those cases, what should happen is that the fErase field of the PAINTSTRUCT you got from BeginPaint will be set to something other than 0, which tells you that you [the WM_PAINT handler] still have to erase the window first.

Now sometimes people play games with their own custom WM_ERASEBKGND handler when trying to optimize painting (or in a miguided attempt to reduce flicker). That can result in the fErase flag being 0 even if you do need to erase first.

My advice is to let DefWndProc handle the WM_ERASEBKGND and to make sure you've got a proper value set for hbrBackground in the WNDCLASS. Once that works, you can experiment with other approaches.

Why validating/invalidating the area is used?

Imagine someone's throwing balls at a fence. Do you repaint the fence as many times as balls hit it? No, you repaint the fence if, and only if, a ball hit it since the last time you repainted.

You're suggesting that any time an area would be marked invalid, instead a WM_PAINT message should be sent to the application. The big problem with this is that if the same area got invalidated many times, that would result in many WM_PAINT messages being sent and no way to know that many of them have already been handled. So at the time when you most need high performance (because you're falling behind on drawing) you'd have to repeat the same drawing operations over and over. That doesn't make sense.



Related Topics



Leave a reply



Submit