ValidateRect vs BeginPaint - winapi

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

Related

No WM_SIZE received when windows resized

I have a fairly simple windows program that created a listview control that should exactly fill the client area. That works at start up, and I think will work if the window is resized --- except the windows NEVER receives any WM_SIZE messages (after the initial one sent on window creation.) I verified this using Spy++x64 as an administrator to ensure I was capturing everything. Spy++ showed the window receiving WM_SIZING, WM_WINPOSCHANGED, WM_NCCALCSIZE, and WM_WINPOSCHANGING (this list isn't in any particular order) but NEVER a WM_SIZE.
This is a 64-bit program, but I don't know why that should matter.
So, is there something I could have done that allows the window to be completely resizable, but prevent Windows from ever generating WM_SIZE messages when that happens? If not, is there something I need to do (that was never needed in the past 30 years) to let Windows know I need to see those WM_SIZE events?
It turns out that the default window procedure generates the WM_SIZE when it processed WM_WINDOWPOSCHANGED and, since I was handling WM_WINDOWPOSCHANGED, no size messages were created. So I forwarded the position changed message to the default handler and the messages are back.
This follows documented behavior. There's a remark in the documentation for the WM_WINDOWPOSCHANGED documentation:
By default, the DefWindowProc function sends the WM_SIZE and WM_MOVE messages to the window. The WM_SIZE and WM_MOVE messages are not sent if an application handles the WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient to perform any move or size change processing during the WM_WINDOWPOSCHANGED message without calling DefWindowProc.
Yup, I'm sorry to admit that I failed to read the documentation for all of the Window messages that I was NOT having problems with when I needed to find out about WM_SIZE. Silly me for not assuming the documentation I needed about WM_SIZE was only to be found under some other message! All it says about the message generation in the WM_SIZE documentation is:
Sent to a window after its size has changed.
There is no mention AT ALL of any dependency on the default processing for a DIFFERENT message to be found. Ergo, the behavior is effectively undocumented, especially since it may be critical information, as it was for me.
Oh well, I give up, this place has become far too much of just smacking people down for asking questions some people think are too easily answered. Try to remember that not everyone has an eidetic memory and access to all of the documentation you have all memorized. Some of us look up the thing we're working on and expect to find the important details about it. THEY ARE NOT PRESENT. Bye!

Determine if a handle points to an element of the screen (and not a printer etc)

I'm looking for a way to identify if a handle references something on the/a screen (a screen, a window, a control, the entire virtual desktop, etc).
I'm trying to standardise the resolution of the interface so that I can consistently save it and do non-regression testing on it. So I've hooked a couple of system calls like GetDeviceCaps so that I can intercept the resolution and change it to a consistent 96DPI.
So far I've found GetObjectType that doesn't necessarily tell me if the object is part of the screen (comparing to OBJ_DC and OBJ_MemDC). Combining that with WindowFromDC I can get a slightly more indicative result, but it's still not perfect.
I thought maybe I could use EnumDisplayMonitors with null for the first two parameters, but it never seems to function.
Does anyone have a fool proof way of telling if a handle references a screen object or not?
Thank you in advance!
Loren
Turns out I could've used GetDeviceCaps with the parameter index set to TECHNOLOGY. An object related to rendering to a screen will be identified as DT_RASDISPLAY
See https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getdevicecaps

How to read content of WM_PAINT message?

My goal is to screen-scrape a portion of a program which constantly updates with new text. I have tried OCR with Tesseract but I believe it would be much more efficient to somehow intercept the text if possible. I have attempted using the GetWindowText() function, but it only returns the window title. Using Window Detective I have determined that whenever the window updates in the way I wish to capture, a WM_PAINT message is reliably sent to the window.
I have looked a bit into Windows API Hooks, but it seems that most of these techniques involving DLL injection are intended at sending new messages, not accessing the content of already sent messages.
How should I approach this problem?
When you say 'screen-scrape', is that what you really mean? Reading your post, it sounds like you actually want to get at the text in the child window or control in question - as text, and not just as a bitmap. To do that, you will need to:
Determine which child window or control actually contains the text you want to get at. It sounds like you may have already done that but if not, the tool of choice is generally Spy++. (Please note: the version of Spy that you use must match the 'bitness' of your application.)
Then, firstly, try to figure out whether the text in that window can be retrieved somehow. If it's a standard Windows control (specifically EDIT or RICHEDIT) then there are documented ways to do that, see MSDN.
If that doesn't pan out, you might have some success hooking calls to ExtTextOut(), although that's not a pleasant proposition and I think you might struggle to achieve it. That said, I believe the accepted way (in some sense of the word 'accepted') is here.
With reference to point 3, even if you achieve it, how would you know whether any particular call to ExtTextOut() was drawing to the window you're interested in? Answer, most likely, HWND WindowFromDC().
I hope that helps a little. Please don't come back at me with a bunch of detailed questions about how this might apply to your particular use-case. I'm not really interested in that, these are just intended as a few signposts.

Why is WM_PAINT sometimes called with empty rectangle?

I'm dealing a lot with drawing. Currently I'm using WM_TIMER to schedule painting using InvalidateRect. For some reason WM_PAINT is then very often called with region (0,0,0,0), so basically an empty rectangle. I tried to interpret this as "the whole window", but then it seemed to cause quite some performance decrease. Why is Windows sending it then?
Your question is quite well answered in the standard documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/dd145213%28v=vs.85%29.aspx.
Basically, the system sends WM_PAINT messages when the message queue is empty and by default it does so on occasion regardless of whether there is anything to paint or not. Many older applications depended on WM_PAINT (for example to do idle time processing) and keeping this behaviour ensures compatibility.
No, you must not assume it means the whole screen. If the region is empty you should avoid calling BeginPaint/EndPaint and just pass it through to the default window procedure.

Layered window still receiving WM_PAINT message after UpdateLayeredWindow call

I've got a few layered windows in my app that use UpdateLayeredWindow() to handle their visual representation. According to the MSDN article on layered windows, "when using UpdateLayeredWindow() the application doesn't need to respond to WM_PAINT or other painting messages." They shared some of the same message handlers as non-layered windows, so I figured I would just return early from WM_PAINT handling if the target is a layered window.
Of course, this caused one major issue: if one of the layered windows did get a WM_PAINT message, the input queue would end up flooded with an unending stream of WM_PAINT messages. This end-result makes sense, since the window would never be validated and so it will keep thinking it needs to paint (I shouldn't be returning from the handler without validating or BeginPaint()ing, etc.), but what doesn't make sense is why it received the message in the first place, since it has no effect on a window that was using UpdateLayeredWindow().
It wouldn't even happen reliably -- just every now and then, and not every time the window's pixels needed redrawing. Sanity was restored by falling back to DefWindowProc() when a layered window got a WM_PAINT message, but I feel like something is going on that I don't understand. And considering how seldom this problem manifested itself, I'm worried this might just be hiding an even subtler problem. Is it expected behavior for a window using UpdateLayeredWindow() to still get the occasional WM_PAINT message? Does it matter, as long as I handle it correctly?
Additional info, if needed: the window is calling UpdateLayeredWindow() immediately after being created, and then it's left on its own (it doesn't call it again, since it doesn't change). Using C++ and win32 API, no MFC.
I had run into similar issues before, although my memory may be a bit rusty by now.
First off, keep the DefWindowProc. When the docs say you don't have to respond, I would take that to mean to ignore the message entirely, rather than prevent default handling.
I personally experienced this from two different causes. One was a window which was actually sending WM_PAINT messages (evil! beware!). The other (IIRC) resulted from certain RedrawWindow calls. In both cases, I chalked the problem up to poorly written code, outside of my control, and never had any situations arise from simply passing it down to DefWindowProc.
Hopefully you will have the same experience!
Good luck. I found layered windows to be poorly documented and full of interesting caveats and gotchas, but very pleasing once you get all the kinks worked out.

Resources