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
G++ Error:/Usr/Lib/Rpm/Redhat/Redhat-Hardened-Cc1: No Such File or Directory
How to Write an Adl-Enabled Trailing Return Type, or Noexcept Specification
What's the Point of Std::Unique_Ptr::Get
Difference Between Long Double and Double in C and C++
Avoid Exponential Grow of Const References and Rvalue References in Constructor
Why am I Not Provided with a Default Copy Constructor from a Volatile
How to Install Llvm Toolchain for Eclipse Cdt
Programmatically Selecting File in Explorer
Error Lnk2005: New and Delete Already Defined in Libcmtd.Lib(New.Obj)
Why Is Name Mangling Not Standardized
What Is the Modern, Correct Way to Do Type Punning in C++
Alternative to C++ Static Virtual Methods
How to Check If Given Int Exists in Array
How to Build a Full Path String (Safely) from Separate Strings