Difference between InvalidateRect and RedrawWindow - c++

When I want to redraw a window, is there any preferred function to call between InvalidateRect and RedrawWindow?
For instance, are these two calls equal: (win would be a HWND)
RedrawWindow(win, NULL, NULL, RDW_INVALIDATE);
InvalidateRect(win, NULL, NULL);
The main question(s): When should I use one or the other? Are there any differences that happen in the background? (different WM_messages / focus / order / priorities..)
The reason that I want to redraw the window is because I send a new image to it that I want it to display, meaning the content of the window is no longer valid.

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.

RedrawWindow(win, NULL, NULL, RDW_INVALIDATE); and InvalidateRect(win, NULL, NULL); are equivalent. Both functions invalidate the window. The WM_PAINT occurs at the normal time (no other messages in the application queue) in both cases.
If you want the paint to be done immediately then calling either RedrawWindow(win, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW) or InvalidateRect followed by an UpdateWindow will do that.
RedrawWindow simply gives more options with the RDW_* bits. If all you want is to invalidate the window without the immediate paint then calling InvalidateRect seems cleaner.

I don't like just giving links, but the MSDN gives you all the information you need and it would be a waste of time to re-type it all here.
RedrawWindow
InvalidateRect
In short, yes there are differences. The question is, why do you want to redraw the window? Is it because the contents are no longer valid? If so, use InvalidateRect, otherwise use RedrawWindow.

RedrawWindow repaints the window immediately. InvalidateRect only marks the window to be repainted on the next WM_PAINT message. But WM_PAINT messages have lower priority than other messages, so the repainting won't be immediately if your app is busy handling other messages.

Related

Does SetWindowPos paint immediately

On every mouse move event, I am moving my window. From the documentation it appears that if the move is successful SetWindowPos return a non-zero value.
I wanted to confirm my inference that every time SetWindowPos returns a non-zero value, the move has already happened. Which means, the window has actually been re-painted at the new position and only then does the function return. It is NOT the case that move will happen a little while later (when some kind of message is processed) after the function has returned.
I wanted to confirm my inference that every time SetWindowPos returns a non-zero value, the move has already happened. Which means, the window has actually been re-painted
This is false assumption. Successful move and non-zero return has nothing to do with painting.
The API changes position and non-zero returned value confirm that new values were accepted. The API does not promise, does not do the complete repaint cycle as a part of its execution. More to that, change in position, Z-order etc. is likely to affect visibility of other windows too, which in turn need repaint, which in turn has to happen on respective threads. The repaints are scheduled, they are not synchronized with SetWindowPos return. Documentation on MSDN does not have any promises regarding repaints/updates. Then zero return from the API is an indication that your arguments are not accepted at all (esp. invalid window handle).
Bonus reading:
When you call the Set­Window­Pos function, the window manager updates the window size, position, whatever, and then it goes around repainting the windows that were affected by the operation. By default, the Set­Window­Pos function does a quick-repaint of the windows before returning. After the function returns, the normal WM_PAINT message does the real work of painting the window. The quick-repaint is done so that there is immediate feedback that the window did change its size, position, whatever.
SetWindowPos returns immediately after it has done its job.
But the main painting is deferred until WM_NCPAINT and WM_PAINT are received by the window. From my experience, I can say that changes to the frame are often drawn directly by SetWindowPos.
If you want the window completely redrawn call UpdateWindow or RedrawWindow (with appropriate flags) after the call to SetWindowPos

Correct method for redrawing a layered window

I have a window created with the WS_EX_LAYERED window style. I am currently drawing onto a memory bitmap using GDI+, and using UpdateLayeredWindow to update the graphical content of my layered window. I intend to use this window as the main window of my application, which would require it to redraw frequently.
Seeing as layered windows do not receive the WM_PAINT windows message[?], I need to come up with an appropriate method for re-drawing the window. Optimisation is not essential, but it's always nice to have your cake and eat it too. Therefore, I am in search of the "correct" method to use.
Here are my thoughts so far:
I would guess that it's a good idea to render onto an off-screen bitmap before BitBlting or similar.
60 frames rendered per second should be (more than?) enough (but how does this compare to other applications' frame rates?).
Possible solutions:
Use SetTimer to send the WM_TIMER message on a regular basis.
Useful because through specifying the time-out value, I can achieve my desired frames per second, without the requirement to measure the duration a "frame" takes to be rendered.
Would likely cause input or other lags due to the frequency and speed of the messages.
Render frames only when particular events occur, such as a window resize.
Would require me to figure out all events that would require a redraw.
Would greatly reduce the amount of unnecessary frames being rendered.
Render frames when there are no messages in the message queue, by checking PeekMessage.
This might slow down the processing of window messages.
This will cause a high CPU usage because more frames than necessary are being processed.
Create a new thread to perform the render loop.
Timing calculations will have to be performed in order to maintain a steady frame-rate.
Layered windows don't receive WM_PAINT messages that would otherwise be generated after window visibility changed, but it won't prevent them to receive this message at all.
You can continue to use InvalidateRect to change window update region, wait for WM_PAINT in you window procedure, draw contents in bitmap and call UpdateLayeredWindow to change window contents. You can use this method to request redraw when content of window changes, for example, when button was pressed, or window has been resized (or activated/deactivated).
It shouldn't be so complicated, this is the pseudo code for you message loop:
while (true)
{
// GetMessages
while (PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE))
{
if (!GetMessage(&msg, hWnd, 0, 0 ))
{
// Need to handle WM_QUIT
...
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
// Check if we need to draw
if (TimeForANewFrameHasCome() ||
IfWeNeedToDrawAfterInputOrInvalidate() ||
AnyOtherCaseThatCausesAnUpdate())
{
// Render
UpdateMemoryDCOrBitmap(...);
// Display it
UpdateLayeredWindow(...);
}
// May sleep a while
// Either Sleep(20); or better MsgWaitForMultipleObjects, that makes it possible
// to wake up upon an Event too...
MsgWaitForMultipleObjects(...);
}

How to update the screen once it has lost focus

I'm working on a program that requires WM_ERASEBKGND to be disabled (to avoid flickering).
The problem comes in when my main window loses focus, and another window (another program) gains the focus.
The window that has the focus (not my program) invalidates MY program's window every time it passes over it! The result is, my window's screen turns white everywhere that another window has passed by it, leaving it almost totally blank afterward. Obviously, I cannot have a program where the screen turns white every time it loses focus.
Is there any way to continue my window's drawing operations, (continue calling wm_paint, for example) even after my window has lost focus (WM_KILLFOCUS)?
First of all, from the comments above, never send the WM_PAINT manually with SendMessage or PostMessage. Use InvalidateRect to instruct the window to be repainted.
About the WM_ERASEBKGND, the return value is used to indicate the WM_PAINT handler that the background has been erased, in case the paint procedure can be optimized. To actually prevent the background from being erased, simply do not call DefWndProc() for that message. Or even easier, set the hbrBackground to NULL in the window class.
As others mentioned the focus has nothing to do with repainting, and your window should paint normally even while in the background.

What are the differences between RedrawWindow and UpdateWindow in Win32?

What are the differences between RedrawWindow and UpdateWindow in Win32?
Since they seem to have the same purpose to refresh a window, what are the differences?
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.

On Win32, can I disable painting of a window for a period of time?

Is there a function that will freeze window repainting for some time, while I do changes to the layout of my dialog?
If you find that you actually need to do this, you should send the window a WM_SETREDRAW message with the wParam set to FALSE. This indicates that the window should not be redrawn after its contents are changed.
When you want to re-enable drawing, send another WM_SETREDRAW message, this time with the wParam set to TRUE.
Sample code:
// Disable window updates
SendMessage(hWnd, WM_SETREDRAW, FALSE, 0);
// Perform your layout here
// ...
// Re-enable window updates
SendMessage(hWnd, WM_SETREDRAW, TRUE, 0);
For more information, Raymond Chen's blog article on the subject is a great read.
You should do the repositioning in a single swoop; use BeginDeferWindowPos et al.
The way Windows paints is that the system posts your window WM_PAINT messages instructing you to paint. You can elect to ignore these messages if you so wish, whilst you are modifying the layout, and then force a paint cycle once you have finished modifying the layout.
However, my experience of writing UI on Windows is that you usually don't need to take such steps. Since you are in charge of pumping your message queue, if the window is being refreshed whilst you are in the middle of modifying the layout, then you must have taken action that led to the message queue being pumped.
Put simply, stop pumping the queue whilst modifying the layout and your problems will vanish.