Re: The basics of Windows' messages

Tech-Archive recommends: Fix windows errors by optimizing your registry



William DePalo [MVP VC++] wrote:

A very common strategy is to call PeekMessage() rather than GetMessage() there. It can do two things differently. First, it can take a look at (peek at) a message without deleting it from the queue. Second, it returns immediately if there is no message in the queue. So, your /ProcessMessages/ can proceed as long as there is a message in the queue, remove it and then translate and dispatch it.

Let's see if I understand it. Here is some illustrative pseudo-code:

// A lengthy process; invoked in response to some
// user-initiated event (e.g. a button click)
void doLengthyProcess()
{
for (...)
{
// Do a step of the lengthy process
doStep();

// Update the UI for progress monitoring
updateUi();

// Force pending messages to be processed
processMessages();
}
}

void processMessages()
{
while (PeekMessage(...))
{
TranslateMessage(...);
DispatchMessage(...);
}
}

Does the pseudo-code above more or less match your explanation? If so, then can I assume that /processMessages/ is just a regular function which will run in the context of the calling thread? In other words, there is actually no magic nor thread switching as in the way I had initially supposed.

Read the docs for PeekMessage() to understand how WM_PAINT and WM_QUIT are special cases. Also realize that because PeekMessage() does not block like GetMessage() that you end up polling. If you do that too much, that's bad for battery life.

I did so and learned that WM_QUIT messages are always processed, regardless of the message filtering used. I also learned that WM_PAINT messages are normally left in the queue.

Don't worry about that. :-) In the old days _all_ 16 bit windowed (not console) applications ran in the context of the same thread. An application that did not call GetMessage() could hang not only itself but innocent bystander applications. "Yielding" was important for system stability.

I see. I guess I should be more careful then, aware that the word "yielding" might be used without implying thread switching in a multiple-thread environment.

Does "yield" in that case mean what I think it does? In other words, does the code in /ProcessMessages/ actually cause a switching of the execution context?

GetMessage(), WaitMessage() and MsgWaitForMultipleObjects() do that. If there is no message in the queue then the thread waits, consuming no CPU cycles. The scheduler will happily move on to service something else.

I am glad it works that way. I would not be happy to see a supposedly idle application taking up all of the CPU.

Supposing that context swithing actually takes place; then, which thread actually processes a message after it is removed from the queue?

The calling thread. Always.

Great. So whenever the WndProc of a given window is called, it can be assumed that Windows has arranged for the call to take place in the context of that window's thread.

I wonder whether it should have been written in a separate thread (pun intended).

No, but imaybe(?) it belongs in the UI group.

Right. I will remember that in case I feel the need to start a new,
related thread.

Thank you once again, William.

--
Ney André de Mello Zunino
.


Quantcast