views:

224

answers:

5

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.

A: 

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.

paxdiablo
A: 

The BeginPaint() function returns the rect that requires validation in its 2nd parameter: http://msdn.microsoft.com/en-us/library/dd183362%28VS.85%29.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%28VS.85%29.aspx

vanja.
+1  A: 

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().

Kevin Montrose
+1  A: 

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?

Toji
Because I've got a Delphi component with a method to handle WM_PAINT, but it's not getting called for partial redraws. I can only conclude, then, that no WM_PAINT is being sent. Either that, or something's very wrong somewhere along the line, because I *am* getting it just fine for full paints.
Mason Wheeler
What are you doing to invoke a partial redraw (and what OS?)
Toji
I'm only seeing this on XP, since Vista stores the appearance of each form in its own buffer before drawing them to the screen. What I'm doing is opening another window, which shows up in front of the form I'm using, and then bringing my form back to the foreground. Everything gets repainted properly except the one component, which is never getting a WM_PAINT message, and I'm trying to figure out what's going on and why.
Mason Wheeler
A: 

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.)

Stephen Nutt