Why call InvalidateRect() in WM_PAINT message? - windows

So i am learning Windows API with book "Programming Windows - Charles Petzold (5th edition)". If i understand correctly, when handling WM_PAINT message calling function BeginPaint() validates given area that has to be updated. However, in this book (page 145 for PDF version or page 128 in printed version) you can see this code:
case WM_PAINT:
InvalidateRect (hwnd, NULL, TRUE) ; // what does this line do?
hdc = BeginPaint (hwnd, &ps) ;
DrawBezier (hdc, apt) ;
EndPaint (hwnd, &ps) ;
return 0 ;
Is this author mistake? i think InvalidateRect() should be called after using GetDC()/ReleaseDC() and not inside WM_PAINT message.

The one thing this does is force the entire window to be invalid and not just whatever happens to be invalid (for instance due to an overlapped window being moved out of the way).
I'm not sure that it matters in this case but that is what the call accomplishes.

According to the document:
The system is not the only source of WM_PAINT messages. The InvalidateRect or InvalidateRgn function can indirectly generate WM_PAINT messages for your windows. These functions mark all or part of a client area as invalid (that must be redrawn).
So maybe the author wants to mark all of a client area as invalid, but it doesn’t make sense to do so in this example, because the WM_PAINT message is triggered after the form has been marked invalid, so adding or deleting this line of code will not influential.

The answer is: no, it's not a mistake made by author. The function call InvalidateRect() is in right message and causes to repaint whole client area in all cases (as i assumed, but i wasn't 100% sure, so that's why i asked for a help).
If you have this book and struggle with understanding this example, please try to understand every line in code. It took me a week to understand why there is call to InvalidateRect() function.
Thank everyone for your answers, i highly appreciate it!

Related

Why should I call `GetDC` and `ReleaseDC` again and again?

Every example code I have seen are GetDC and ReleaseDC being called again and again. Or BeginPaint and EndPaint.
But I think drawing on the screen happens very frequently (especially in a game), so storing the drawing in memory is better than getting and releasing device contexts all time.
So I went the route of getting a DC and "keeping it", only releasing it when the program ends. But why don't people do it like this? Is it because GetDC and ReleaseDC cost very little?
case WM_CREATE:
hdc = GetDC(hWnd); //hdc is declared as global HDC
MyBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));
return 0;
case WM_PAINT:
MemDC = CreateCompatibleDC(hdc);
OldBitmap = (HBITMAP)SelectObject(MemDC, MyBitmap);
BitBlt(hdc, 0, 0, 300, 300, MemDC, 0, 0, SRCCOPY);
SelectObject(MemDC, OldBitmap);
DeleteDC(MemDC);
return 0;
The code you presented here is wrong. First off, you need to read a little more of the documentation. Here is a useful link: Painting and Drawing. Basically there are two ways to update a window:
In response to the WM_PAINT message. Use the BeginPaint and EndPaint functions to paint the client area properly. This message is sent by the system when a part of the client area is "invalidated" (as a result of resizing, restoring from minimized state, moving a window previously obscured, or programmatically invalidating it.) WM_PAINT is a low-priority message, received just before the message-queue gets empty.
Specifically drawing a part or the whole client area without having an invalidated region on it. Use GetDC and ReleaseDC for this. Useful if you want to make changes immediately visible, when the application (CPU) is busy.
Writing some code to process the WM_PAINT message is normally almost mandatory, while specifically drawing as well is optional, depending on the requirements of your application.
Never send or post a WM_PAINT message yourself, instead invalidate a part or the client area - the application will receive a WM_PAINT message before becoming idle. If you want the painting to occur immediately call UpdateWindow - this bypasses the message queue.
A recent (Aug 2016) security update in Windows 10 prevents the reuse of printer device contexts. After printing one document Windows 10 will refuse to print again with that same DC. It has always been a preferred practice to create a new DC for each document, but now it seems to be a requirement in Windows 10.

ValidateRect vs BeginPaint

From the MSDN documentation:
The BeginPaint function validates the entire client area.
The ValidateRect function should not be called if a portion of the
update region must be validated before the next WM_PAINT message is
generated.1
I've been programming with Win32 API for years, and I've never thought to call the ValidateRect function. A co-worker of mine today pointed that we were missing a call to ValidateRect, which fixed a bug we were having doing some high-speed animation using GDI (I know, an oxymoron)
Can someone tell me whether or not a call to ValidateRect is necessary after a BeginPaint/EndPaint pair? I have seen no documentation at MSDN that sheds light on this, and what documentation and examples I do see suggest that calling ValidateRect is not necessary.
It's not necessary. BeginPaint is used when you are validating the area because you handled it (painted it) in WM_PAINT.
ValidateRect is more to "cancel invalidation", usually after painting directly on the window without WM_PAINT or because something changed and you no longer want to be issued a pending WM_PAINT.
The fact that it fixed a bug likely means there's something else going on, and this accidentally fixed it (maybe by reducing the number of WM_PAINT messages?), or wrong observations (for example you changed 2 things but this one got the attention instead of the other which is the actual fix).

How does DispatchMessage decide which WndProc to use?

I'm going through some code for an open source project and this is my first time dealing with a Win32 app (mostly did console stuff). I see that several functions within the code are windows procedures because they return LRESULT CALLBACK.
Is there something the programmer has to do to make sure DispatchMessage invokes the right WndProc or is DispatchMessage coded in a way that it can determine the right WndProc all on its own?
EDIT:
I'm guessing that the way DispatchMessage(const MSG*) chooses between different WndProc's in an application is based on the window handle member (HWND) of the MSG object passed to it.[Hope previous sentence wasn't too confusing.] If the message was for the edit window for an application, for example, (and not for its main window,) then DispatchMessage will choose the WndProc member function for the particular class for which the edit window is an object of. If the message was for the main window, then it would choose the WndProc member function for the class that the main window is an object of (for me, this class would be the Notepad_plus_Window class). This is only a thought, though. I haven't found much to back it up so I'd be glad if anyone could confirm this.
Yes you are right, it uses MSG.hwnd to send the message to the correct window. One thing to be noted, it will use the WndProc associated with the window, not the window class. A window is an instance of a window class.
This article of Microsoft's "Under The Hood" illustrates this with rather detailed pseudo-code of DispatchMessage() that might be worth taking a look as well )

Difference between GetDC() and BeginPaint()

I am working on Win32 UI. I want to know the difference Between GetDC and BeginPaint. When to Use which API and when not to use which API.
GetDC simply returns the handle to the device context, which can be used any time anywhere to do your own drawing. BeginPaint on the other hand prepares the window for painting, and also provides information on what should be painted (such as whether the background needs repainting and the rect that needs to be painted).
Examples of when to use each? BeginPaint is most commonly seen inside WM_PAINT handlers (MSDN: An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call to the EndPaint function.). GetDC can be used anywhere, so if you want to draw on an external window. Basically anytime thats not in a WM_PAINT handler. BeginPaint and EndPaint also have some affect on the caret. Read msdn for more details.
GetDC() is not a substitute for Begin+EndPaint(). If you try, you'll find that your UI thread starts to burn 100% cpu core and your WM_PAINT handler getting called over and over again.
The big one is BeginPaint(), it clears the update region of the window. The value of PAINTSTRUCT.rcPaint. WM_PAINT is generated as long as the window has a dirty rectangle, created by an InvalidateRect() call by either the window manager or your program explicitly calling it. BeginPaint() clears it.
BeginPaint is intended to be called only in response to WM_PAINT message. The device context obtained by it points to the invalidated (to-be-redrawn) area of the window. It should be then released using EndPaint.
GetDC can be called at any time. The device context obtained by it points to the whole client area of the window. To release it, you should call ReleaseDC.

What Windows message is sent to repaint a partially occluded window?

I know that WM_PAINT tells a window that it needs to repaint itself entirely, but apparently that's not the message that gets sent when it's been covered partially and then the window that was in front of it is no longer in the way and it needs to repaint the dirty portion. Does anyone know what message is sent in this case?
EDIT: Found the problem:
The issue involved a Delphi control I wrote to embed a SDL rendering surface on a Delphi form. SDL has an API to build its renderer on another window's HWND, and it marks it as a "foreign window".
SDL usually handles WM_PAINT internally, so I ended up having to add some code to SDL's WindowProc to forward the message on to the external WindowProc if it's a foreign window. That was working sometimes, but it turns out there was a glitch that was stripping the foreign window flag from the window's data structure, so it was swallowing the message instead of passing it on to my app. Once I fixed that, I started getting the WM_PAINT messages all the time.
Why do you say it's apparently not? WM_PAINT should be called for partial redraws (the updated rect is returned by BeginPaint or GetUpdateRect). If it doesn't appear to be getting called, there may be a bug elsewhere in your app that's preventing it. What are you seeing that leads you to believe that it's not working?
WM_PAINT is sent to indicate that some portion (including the entirity) of the window needs to be repainted.
Call GetUpdateRect() to get a rectangle that bounds the region to be updated. This information is also included in the PAINTSTRUCT (as the rcPaint field) passed to BeginPaint().
The BeginPaint() function returns the rect that requires validation in its 2nd parameter: http://msdn.microsoft.com/en-us/library/dd183362(VS.85).aspx
case WM_PAINT:
{
PAINTSTRUCT psPaint;
HDC hdc = BeginPaint( hwnd, &psPaint );
// psPaint.rcPaint contains invalidated area
EndPaint (hwnd, &psPaint);
}
return 0;
Look at psPaint.rcPaint : http://msdn.microsoft.com/en-us/library/dd162768(VS.85).aspx
I'm pretty certain the Win32 API uses WM_PAINT even for partial repaints. From MSDN:
The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. [My italics].
That link has the full detail on WM_PAINT but if, as you say, the WM_PAINT message is not being sent for partial redraws, the Spy++ is the tool you need to find out for sure.
Take a look at WM_PRINTCLIENT. There are some circumstances when WM_PAINT is not sent and a WM_PRINTCLIENT message is sent instead. (AnimateWindow for example.)

Resources