The simple question: What kind of message is that? And where does it come from?
The symptoms:
I experience a crash in CWnd::WalkPreTranslateMessage while closing
my application. This is caused by a message processed by
CWinApp::PreTranslateMessage after the main frame is destroyed and its C++
object is destructed and before MFC processes the WM_QUIT message internally
- I do not call (Afx)PostQuitMessage.
I overloaded the CWinApp::PreTranslateMessage to trace the messages
passing through.
This happens with VS2005 (32bit) and VS2010 (64bit) and in debug and release mode.
The timeline:
CWinThread::m_pMainWnd is NULL (been destructed properly)
CWinApp::PreTranslateMessage is called
Its parameter MSG* message looks like:
hwnd: NULL
message: varies from 49390 to 49401
wParam: 17
lParam: looks random
=> crash in CWnd::WalkPreTranslateMessage
At runtime I see messages with that IDs passing through
CWinApp::PreTranslateMessage. There is one kind of message
interesting that may help to identify where these messages
come from:
The MSG* message looks like:
hwnd: NULL
message: 49390
wParam: 17
lParam: looks random at first, though ...
lParam hiword: is incremented by 1 each time the message passes through
lParam loword: is constant
These messages seem to be thread messages where hwnd is explicitly NULL.
I still wonder what they are good for, how to stop them filling the message queue
or how to handle them not to crash the application while closing.
Well, for now I handle it like this which is just not right.
if (m_pMainWnd)
return CWinApp::PreTranslateMessage(pMsg);
else
return FALSE;
Please help me identify these messages, thank you!
Messages in that range (anything above 0xC000) are returned from RegisterWindowMessage. I suspect that you're doing something wrong, since this sort of thing shouldn't happen - and doesn't in properly written MFC applications.
Related
I'm looking for some feedback on an issue that I can workaround, but want to understand better. I have some multithreaded code where a worker thread uses the Win32 API PostMessage function to post a message to the main UI thread in order to update a TreeView. Some of the posted messages sometimes fail to ever appear via the UI thread's message pump, despite my logging showing that the PostMessage returned successfully.
I've already found numerous explanations of how this could happen if I'd done something funky in my message pump, due to the presence of a modal message pump in certain circumstances, but I'm not doing anything funky.
I think (but would like confirmed) that my problem is due to calling PostMessage too early in the UI thread's lifetime. My WinMain calls CreateWindowEx to create its main window, and the WM_CREATE handler for that window indirectly launches the background threads that will, fairly quickly, call PostMessage using the main windows's HWND, possibly even before the WM_CREATE handler finishes, very likely before WinMain's message pump is started.
Is it possible/likely that some messages in this situation would be lost, even though PostMessage returned success? In testing, I've determined that adding a small delay (Sleep(50)) in the worker thread before it calls PostMessage is enough to prevent any message loss. However, I'm not convinced that this is solving the underlying problem so would like to know if I need to keep digging.
EDIT:
There's only one message loop in all my code and it's not doing anything unusual beyond calling the usual TranslateAccelerator etc:
// Enter the message loop
while (GetMessage (&msg, NULL, 0, 0)) {
if (!TranslateMDISysAccel(hwndClient, &msg) && !TranslateAccelerator (hwndFrame, hAccel, &msg)) {
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
I've already found numerous explanations of how this could happen if I'd done something funky in my message pump, due to the presence of a modal message pump in certain circumstances, but I'm not doing anything funky.
Modal loops don't throw away window messages, unless they are coded wrong and don't pass unknown messages to TranslateMessage()/DispatchMessage() like they should.
I think (but would like confirmed) that my problem is due to calling PostMessage too early in the UI thread's lifetime.
If that were the case, PostMessage() would simply fail, but you have already ruled that out. As soon as a thread calls any user32.dll function, the message queue is created and can begin receiving messages, even if the queue is not polled right away.
Is it possible/likely that some messages in this situation would be lost, even though PostMessage returned success?
No. Something else is going on. Either your message loop is filtering messages incorrectly, or a malformed modal loop is discarding messages, or you are simply posting to the wrong HWND. Hard to say as you did not show any of your code.
In testing, I've determined that adding a small delay (Sleep(50)) in the worker thread before it calls PostMessage is enough to prevent any message loss.
What is your main thread normally doing during those 50ms? Sounds like something in your UI code is receiving and discarding your posted messages during that time.
On the other hand, how do the threads know which HWND to post to? Is your WM_CREATE handler passing its hwnd parameter to the threads, or are the threads relying on the HWND returned by CreateWindowEx()? In the latter case, PostMessage() should fail if called before CreateWindowEx() exits. Unless your receiving HWND variable is initially uninitialized and contains a random non-null value that PostMessage() interprets as a valid HWND elsewhere on the system.
I noticed that some messages in WinAPI can be retrieved only in the "main message loop" with PeekMessage() (like WM_QUIT), others can only be retrieved in the user defined winProc() function (like WM_CLOSE and WM_SIZE), and some messages like WM_MOUSEMOVE are retrieved with both.
What's the difference? How do I know where the WM message is going to be sent to?
Messages that were posted with a NULL window handle can only be retrieved in the message loop. Necessarily so, DispatchMessage() can't do its job. This is quite rare.
But yes, WM_QUIT, note how PostQuitMessage() does not take a window handle. That's rather inevitable, when you call PostQuitMessage() you (usually) don't have any window left so only a NULL window handle is sensible. Of course its real intention is to make GetMessage() return FALSE and thus terminate the message loop.
The only other case I can think of are messages generated with PostThreadMessage(). Note how this is a pretty dangerous function, it should never be used to post messages to a thread that ever displays any window. Such messages fall in the bit-bucket when another message loop pumps. Like the one that allows the user to move/resize a window. Or the one that keeps MessageBox() modal. It is only useful in process and thread interop marshaling.
So just ignore this, it is a corner-case.
I have a VC++ code that uses PostMessage to trigger a function call. Although the function gets called eventually, I see that the function does not get called right after PostMessage is executed. It does not even get called after the function containing the PostMessage command completes execution. I noticed that a few more functions got called before the desired function was called.
I would like to know what determines when exactly the callback for a message gets called.
The message is a WM_USER message.
The Windows event-driven model in a nutshell (with many important details simplified away):
There is a "message pump," which is a loop that, on each iteration, pulls a message out of a queue and "dispatches" it by calling the "window procedure" associated with the specific window, passing it the details from the message.
If you're using a framework, it's likely that the message pump and the window procedure are provided for you and that the provided window procedure calls your handler functions in response to the messages it receives.
When a message is posted, it's added to the queue, and nothing else happens to it until the message pump gets to it. There may be messages ahead of it in the queue, and/or a bunch of other code may run before execution returns to the message pump.
When a message is sent, the message is not added to the queue. Instead, the sending code will call the window procedure directly. (Caveat: this is an oversimplification. Things are more complicated when sending a message to another thread.)
So if other functions are being called before the one you expect from your posted message, here are some possibilities:
Other messages were already in the queue when you posted your message.
Other messages are being sent rather than posted, so they're handled immediately, and only when they're done and the message pump eventually runs again will your posted message be handled.
The message pump decided that other messages, which were posted after yours, are more important and therefore should be handled first. (This is not actually common. Certain types of messages, like WM_PAINT, are very low priority and are only generated when there's nothing in the queue, but I can't think of a case where a message takes priority over one that's already in the queue.)
You're posting your message during initialization before the message pump even starts. For example, if you create a window, post a message to it, and then start the message pump, it's possible that there will be a series of messages in the queue related to the window creation ahead of your posted message.
Not all messages are equal. PostMessage doesn't simply add it to a queue data structure; the OS will do a lot of manipulation and prioritizing. Different messages get different priorities, and some messages like WM_PAINT, cannot be sent like this at all.
So there's no way to generalize "when will PostMessage invoke the message handler?" It depends on which message you're sending, how busy the target message queue is, and how the target message loop behaves.
I don't think there is any concise list of how messages are prioritized.
I've got a relatively simple Window class. I've created a window, associated my this, etc etc. Now later, I've thrown an exception to indicate a problem. When I call MessageBox to pop up the error, the program crashes, because it's attempting to call my Window Proc. Now, I mean, admittedly, I failed SRP here and just writing a brief self-owning HWND class will solve this problem, as the window wasn't cleaned up properly. However, I'm really mystified as to why it's trying to process Window messages in my MessageBox call- the owner parameter is nullptr. Any suggestions?
Edit: If I call DestroyWindow appropriately, then now the message box just doesn't show up, although the app doesn't crash. It only works if I manually remove this from the window, so that if the proc were called it would forward to DefWindowProc, and then DestroyWindow. I mean, I thought that if you called MessageBox without an owner, then it would just work, regardless of what you had done to other windows in the system.
What is happening here is that there are still messages for the dud window in the queue when you show the message box. The message box runs a modal window message pump and dispatches the troublesome messages. Remember that all windows created from the same thread share a single message queue.
I have no idea how to fix your problem but that's what's going on.
By the way, passing a null owner isn't a great idea as it will result in your message box not being minimised when your main app is minimised, for example.
Is there a way to hook for a particular windows message without subclassing the window.
There is WH_GETMESSAGE but that seems create performance issues.
Any other solutions apart from these which doesn't deteriorate performance?
AFAIK there's no better solution than what you mentioned. And, of course, subclassing the window is better than hooking all the messages of the thread.
Let's think which path the message passes up until it's handled by the window:
The message is either posted or sent to the window, either by explicit call to PostMessage/SendMessage or implicitly by the OS.
Posted messages only: eventually the thread pops this message from the message queue (by calling GetMessage or similar), and then calls DispatchMessage.
The OS invokes the window's procedure by calling CallWindowProc (or similar).
The CallWindowProc identifies the window procedore associated with the window (via GetClassLong/GetWindowLong)
The above procedure is called.
Subclassing - means replacing the window procedure for the target window. This seems to be the best variant.
Installing hook with WH_GETMESSAGE flag will monitor all the messages posted to the message queue. This is bad because of the following:
Performance reasons.
You'll get notified only for windows created in the specific thread
You'll get notified only for posted messages (sent messages will not be seen)
A "posted" message doesn't necessarily means "delivered". That is, it may be filtered by the message loop (thrown away without calling DispatchMessage).
You can't see what the actual window does and returns for that message.
So that subclassing seems much better.
One more solution - in case your specific message is posted (rather than sent) you may override the message loop, and for every retrieved message you may do some pre/post-processing