Win32 message timeout clears my window - winapi

Take the simplest possible Windows program with a window and message loop, such as a Hello, World program.
Suppose that just before I enter the message loop, I draw into the window (naughtily done outside processing of wm_paint, but bear with me).
If I spend more than about 5 seconds doing this, or I draw something then spend 5 seconds doing something else, before I start the message loop, then the message system seems to 'time out'. The MSDN docs for PeekMessage says it becomes 'unresponsive' and turns it into a 'ghost' window.
My problem however is that it also clears the contents of the window!
Is there way of stopping it doing that? The same 'unresponsive' caption is shown if I spend too long drawing into the window even during offical wm_paint processing; it also starts to behave oddly by generating more wm_paint messages.
It seems very restrictive if everything (eg. complicated rendering, or image processing) must be done within 5 seconds, or if any algorithm needs to keep prodding the message queue to stop it timing out!

This is by design. You must keep checking for messages so that you can respond to user events such as resizing or closing the window. Even worse, if your application is not responding to events then that may cause other applications to freeze, as they may send your application a message and be stuck waiting for a reply.
If you have to do a lot of processing then either check for messages periodically, or do the work in a separate thread.

create a thread for extensive drawing on a cache bitmap. while bitmap is not ready just print on WM_PAIN event "processing please wait..." for example. when ready print that bitmap. and destroy the thread.

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!

Why we need to call UpdateWindow following ShowWindow?

ShowWindow(g_hWnd, 1);
UpdateWindow(g_hWnd);
I am wondering why we need to call UpdateWindow following the ShowWindow?
It is entirely unnecessary, your window will paint just fine without it.
You'll see a minor benefit from it if your program goes off doing lots of stuff after creating the window but before entering the message loop. The user has something to look at. A splash screen is the more typical approach.
ShowWindow does not repaint the window. The call to UpdateWindow sends WM_PAINT message to the window and thus repainting it.
Normally, the system sends WM_PAINT only if the message queue is empty. Under normal circumstances this is good enough and it actually optimizes out a lot of unnecessary repaint. The messages in the queue often will change application state which can often result in invalidating part of the window, and hence result in yet another painting (so the user sees the new application state). So the repaint just happens after all such messages are handled and the system thinks the new window content will be valid for some time (until yet another message(s) come into the queue).
However if you need to force the WM_PAINT immediately and bypass the logic above, you may force sending WM_PAINT (if there is an invalid region) by calling UpdateWindow().
ShowWindow causes a WM_PAINT message, whereas anything which makes a previously hidden part of a window visible. UpdateWindow does any outstanding paint message(s) to be delivered immediately, waiting until the paint processing is complete until returning. Without the call to UpdateWindow the message isn't received until your program goes into the message loop. This avoids any possible delay in response to the user.

MFC app doesn't seem to receive input messages?

We have a MFC Visual-C++ application that is not reacting to any user input.
(Note: Currently only known on one machine. The behavior does recur occasionally, but only after the App has been running for several days!)
The application is redrawn when we switch to it via Alt-Tab (or the Task Bar), but we cannot, for example, activate it's main window by clicking on the title bar.
We have already pulled 4 dumps with WinDbg and checked the active instructions. We always were in some redraw code or somesuch inside the main thread (the GUI thread). We definitely were/are not in a modal message loop and the main thread's stack always looked "OK". (Most/all worker threads were idling, waiting for some event, no suspicious code there either.)
When investigating the problem with Spy++, we see the behavior specified also in this separate question, namely that we seem to get paint and activation messages, but no user input is routed to the application. When I have the application window on the screen, and select it to show messages of the main window,
it will only show "generic" "referesh" messages and nothing else
If I drill deeper, and select all messages for the whole process,
this is what we see:
The app is apparently only processing messages on one hidden sub-window (00CB09F0), and what we see there is a constant stream of 200 WM_PAINT messages per second.
Normally this Sub Window isn't processing any messages at all (except refresh WM_PAINT etc. when Windows sends them). It is normally used as a drawing area and the drawing happens through a WM_TIMER message on it's parent (010A09B8) window. (This WM_TIMER message isn't shown on the hanging app either though.)
The performance profile as shown in process explorer looks like this (100% kernel time, more or less):
I'd say that you have a redraw loop in that window that receives the WM_PAINT flood.
That usually happens if you call Invalidate or similar from the processing of the WM_PAINT message, directly or indirectly.
Other posibility is that, since you say that you are using a timer to redraw the window, the actual drawing is taking more time that the time it self, so the messages pile up in the queue.
Yet another posibility is that you are invalidating the window from a different thread than the one making the painting.
Anyway, you should ensure that you are calling Invalidate*() properly (you showed no code), and never from the OnPaint event. And avoid calling UpdateWindow() as this function can mess things if called without a little care.
I've seen this problem when an exception is thrown from a dialog. MFC's DoModal function disables the main program window then reenables it when the dialog returns; exceptions bypass the reenabling part and the main window remains disabled forever.

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.

Bring form on top of others when clicked on taskbar button in Delphi

Base question: TStatusBar flickers when calling Update procedure. Ways to painlessly fix this
The executed code is in the questions first posts first part ( you can see light grey separating line ) ...
But - problem is that while this code is executed, form does not automatically activate and focus on the top of all other applications.
I have read these articles:
http://www.installationexcellence.com/articles/VistaWithDelphi/Original/Index.html
http://delphi.about.com/od/formsdialogs/l/aa073101b.htm
but according to them it should be working no matter what. I tried all the TApplicationEvents and TForm events with Show; Visible: Repaint; Refresh; BringToFront; ... nothing works.
So - I think I have two options - multithreading or trapping WM_SYSCOMMAND message and in the SC_ACTIVE event simply repaint form. Could this scenario become successful?
None of your linked articles deal with the problem you are having. What you see is the behaviour of a program that does not process Windows messages, so consequently it will not redraw parts that become invalid, and it will not react to keyboard or mouse input (for example moving or resizing with the mouse, or app activation using the taskbar button).
In your code you call StatusBar1.Update, so at least the status bar text is redrawn, but apart from coming to the foreground your application is probably also ignoring move or resize requests.
You need to process Windows messages in a timely manner, so any execution path that takes more than say 200 or 300 milliseconds needs to make sure that messages are handled, otherwise the application will appear unresponsive or hung.
You have basically three options:
Keep the long running code, and insert calls to Application.ProcessMessages - this will allow Windows messages to be processed. Make sure that you keep the code from being entered again, for instance by disabling all the controls that are used to start the operation.
Rework your code in a way that it appears as a sequence of steps, each taking no more than a few 10 milliseconds. Put calls to the code in a timer event handler, or call it from the Application.OnIdle handler.
Call your code in a worker thread, and post messages to the main GUI thread to update your UI.
All these options have their own pros and cons, and for multithreading especially there is a lot of questions and answers already here on SO. It is the most difficult but best option overall when you are working on anything more than a toy program.

Resources