What exactly is going on in this Win32 messaging loop? - winapi

What exactly is going on inside this Win32 messaging loop? I understand that TranslateMessage is converting keycodes to UTF char codes and sending the WM_CHAR event, but what is the call to PeekMessage doing exactly? Is it filtering out a certain type of message and only translating those?
// Application / Player message loop.
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while(msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// work happens here...
}

Normally the message loop will use GetMessage instead of PeekMessage. The difference is that PeekMessage returns immediately. Returning either TRUE if a message was removed, or FALSE if no message was fetched. On the other hand if the queue is empty, GetMessage blocks until a message arrives.
The point is the comment stating work happens here. Presumably the author had some reason why the normal blocking message loop would not suffice. The down side of the non-blocking message loop code in the question is that it is a busy loop. It will not idle and so it will fully consume the CPU, unless there is a call to Sleep() or similar that you have excised.
In a comment you say that you actually want to pull off keyboard messages only, and just messages for a specific window. You need to call PeekMessage like this:
PeekMessage(&msg, hwnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)

All it is is a nonblocking way to get messages. It checks to see if there is a message, and if there is, it takes it out of the queue and puts it in &msg.
Check the docs.
The second parameter says which window to look in. In this case, it's "all windows in the thread."
The third and fourth parameter do let you specify whether you want keyboard or mouse events, but currently is set to "all".

Related

why exactly TranslateMessage

I am trying to make sense of 'The Message Loop'.
This is how it looks:
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
So far I am clear(at least I hope so) with the concept.When the user interacts with windows application using keyboard and mouse,those events are converted to appropriate messages by the respective device drivers and posted to system message queue.
The OS removes messages from the queue one by one and examines each of them to send them to respective application's thread's queue that is responsible for having created the destination window.
Now in my application
MSG msg;
GetMessage(&msg, NULL, 0, 0);
removes the message from thread specific message queue and fills the MSG structure.
But TranslateMessage is said to translate the virtual keystrokes to characters and post them back to the caller thread's message queue.
DispatchMessage directs the OS to call the Windows Procedure of appropriate target window.
Two doubts:
1)What is the exact functionality of TranslateMessage;is it just to translate virtual keystrokes to character messages(I assume virtual keystrokes to be keystrokes other than alphabets and numbers),if character message is posted back to queue,isn't the loop broken?
2)What about the mouse events?are they directly dispatched?
Yes, it doesn't make sense that you would have to call TranslateMessage() when your message loop looks like that. But that's not what the canonical Petzold message loop looks like:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Accelerators are what matters here, otherwise known as "short-cut keys". Your program wants to respond to them regardless of which window has the focus. Like F1 shows the program's help file, regardless which control has the focus. You don't want to have to write code that subclasses every control window to recognize F1.
So if it is a short-cut key then you don't want to call TranslateMessage. The key should not produce a WM_CHAR message if the key happens to match a typing key. Which is why it is a separate call.
In short,
Yes, it just to translate virtual keystrokes to character messages
Yes, they are directly dispatched, see this blog on msdn
For details see
TranslateMessage
GetMessage
Messages and Message Queues
About mouse Input

Is Application.DoEvents sending messages to a separate thread?

I've been trying to understand event loops (not going so well) in general and I've read that the windows messaging loop is single threaded. If it is, how can Application.DoEvents work? Doesn't an event loop process one message at a time and blocks while each message/event is being processed? Wouldn't the message event loop need to exist on a different thread from the one that is processing the message for Application.DoEvents to be possible? If there are separate threads, which one is it that we're calling the "main" thread? I'm sure I'm missing something very simple, I just don't know what it is.
I spend the better part of the day figuring this out (if anything I say is wrong, please comment and let me know so I can correct it). I actually had to build an old Win32 application and create the message loop myself (I'm a pretty persistent SOB). So there is a function called WinMain that starts up the message loop which looks like this:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
The thing about GetMessage() is that it blocks until a message is available in the message queue. If you run a Windowed application and just sit there and look at the window (don't cause any actions that would post a message to the queue), the main thread (the thread the window was created on) is paused on GetMessage(). Now when a message does get posted, we enter the while loop (that is if the message is not quit which is 0). DispatchMessage() is the interesting function here. This function will eventually lead to (in .NET) events being raised by controls and execution of EventHandlers. What puzzled me is if the call stack is GetMessage()/DispatchMessage()/.../EventHandler, how is it possible for Application.DoEvents() to process messages? Well it's pretty simple. DoEvents in Win32 would look like this:
void DoEvents()
{
MSG msg;
HACCEL hAccelTable;
hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_TESTWIN32));
// Main message loop:
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0)
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
So DoEvents() actually starts up another loop to process events while inside the initial message loop's DispatchMessage()! The key difference is that instead of using GetMessage() which blocks until there is a message in the queue, we use PeekMessage() which returns 0 and exists the loop when there are no longer any messages in the queue.
So what if we click a button twice and in that button's EventHandler we have a DoEvents() call? The initial event loop will process the first click and fire the event. While the EventHandler is executing, at the DoEvents() call, the event will be fired a second time and the EventHandler will be entered again (sort of like a recursive call). That's scary!
So in the end, everything is happening in a single thread and DoEvents() actually blocks until all messages are processed then returns. Now I'm going to go to sleep for a couple days.

windows - sendmessage

I'm calling a subroutine form the WndProc function in a windows app. WndProc was called from the message processing loop when a button was pushed. The subroutine takes a fair amount of time to run so it sends periodic messages using SendMessage(WM_USER). These messages should cause screen updates. Unfortunately, the updates are all held until the subroutine returns; at that time all the messages are processed and the screen updated. The handler for the message is in WndProc; it invalidates the window which should cause a paint message to be generated.
Do I need to run the subroutine as a separate thread?
If you want your UI to remain responsive while the subroutine runs, you either have to pump messages within the subroutine (which can itself get you into re-entrancy nasties), or move the subroutine out to a thread. The preferred way to do this is with a Worker thread.
There's an intro to worker threads on my website here. When the thread finishes its work, you can post a registered message back to your main window. Worker threads are pretty easy.
Anticipating your next question about cancelling a lengthy operation, there's a discussion of the options available to you for doing that on my site here. Warning, some of them are very silly, but I do try to be complete :-)
The best would be to use a separate thread.
But you could run the message loop in your handler function too:
HWND hwnd;
BOOL fDone;
MSG msg;
// Begin the operation and continue until it is complete
// or until the user clicks the mouse or presses a key.
fDone = FALSE;
while (!fDone)
{
fDone = DoLengthyOperation(); // application-defined function
// Remove any messages that may be in the queue. If the
// queue contains any mouse or keyboard
// messages, end the operation.
while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE))
{
switch(msg.message)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_KEYDOWN:
//
// Perform any required cleanup.
//
fDone = TRUE;
}
}
}

Why are "TranslateMessage" and "DispatchMessage" separate calls?

Most of the Win32 main loops I've seen are all structured like:
while (GetMessage(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message);
DispatchMessage(&message);
}
It was pointed out to me that MsgWaitForMultipleObjects may be used to add some variety to a main loop. But is there a scenario where doing something between GetMessage, TranslateMessage and DispatchMessage is actually useful?
The more traditional message loop looks like this:
while (GetMessage(&msg, 0, 0, 0))
{
if (!TranslateAccelerator(hwndMain, haccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
It is a pretty big hint to what you'd want to do before dispatching the message: catch messages that ought to be intercepted and treated specially before the window sees them. Keyboard shortcuts are a classic example, they need to be detected no matter what window has the focus.
Any GUI class library exposes it with a virtual method named something like App.PreProcessMessage, a virtual function that can be overridden so your program can implement its own shortcuts and whatnot.
They are different beasts.
For TranslateMessage function
Translates virtual-key messages into
character messages. The character
messages are posted to the calling
thread's message queue, to be read the
next time the thread calls the
GetMessage or PeekMessage function.
[...]
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
DispatchMessage, on the other hand, dispatches a message to a window procedure.
So DispatchMessage does the actual work of processing the message. TranslateMessage MAY or MAY NOT post a new message to the thread queue. If the message is translated then a character message is posted to the thread's message queue.
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
They are separate calls so you, the programmer, can have a chance to avoid the message translation provided by TranslateMessage.
Well to quote an example from the MSDN:
You can modify a message loop in a variety of ways. For example, you can retrieve messages from the queue without dispatching them to a window. This is useful for applications that post messages not specifying a window. You can also direct GetMessage to search for specific messages, leaving other messages in the queue. This is useful if you must temporarily bypass the usual FIFO order of the message queue.
You can also possibly avoid calls to Translate message if you don't need to convert keyboard input control codes.
TranslateMessage() converts virtual keys messages to character input messages.
It is a separate call for the remote chance that under certain circumstances you would want to not produce character input messages for certain virtual keys.

Best way to close and wait for a child frame window using Win32/MFC

There are a few options here, probably, but what would you suggest to be the safest way to accomplish the following:
I've got a child CFrameWnd with a parent = NULL (so that it can live a separate life from the main application, while the app is running, at least). I've got all those windows stored in a list. When the main app is closing (MainFrame getting an OnClose), I go through the array and issue a PostMessage(WM_CLOSE) to all. However, the problem is that each of them has to do stuff before closing down. So, I need to wait for them. But we're all on the same thread... So, how can I wait for the children to close, without blocking their own processing in a single-threaded application?
Or should I launch a worker thread to take care of that? Would it be easier?
Thanks in advance!
Use SendMessage() instead of PostMessage().
Edit: Another option might be to simply handle WM_DESTROY in your child windows (depending on your code of course).
Well you certainly can't just wait for them to close, you need to at least pump messages so that they would receive and handle the WM_CLOSE. How you do that is up to you I guess. But I see you are doing PostMessage. Why not do SendMessage instead - this will run the close synchronously in the window procedure for the window. Or are you trying to quit the app? Then you should really use PostQuitMessage then pump messages in the normal fashion until GetMessage returns 0. Lots of options.
Pumping messages means to have a loop in your code that looks like this. You don't have to call AfxPumpMessages, but that would probably do something similar. There are in fact many different ways to pump messages depending on what you want to do. In addition there are quite a few functions that pump messages for you.
BOOL bRet;
// note that GetMessage returns 0 when WM_QUIT is received - this is how PostQuitMessage
// would work to get us to shut down
// We are passing NULL for the hWnd parameter - this means receive all window and
// thread messages for this thread
while( (bRet = GetMessage( &msg, NULL /* hWnd */, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
If you post the message to a window or windows, then you need to pump messages. What happens is that the message goes into a queue for the thread associated with that window (this thread) - the message pump extracts them out and dispatches them off to the correct window procedure.
If you had sent the message instead of posting it, then the window procedure for the window is called directly - rather than going into a queue. You wouldn't need to pump messages because once SendMessage returns the message is fully handled.
The way PostQuitMessage works is by setting a flag on the message queue indicating that the application should quit. The WM_QUIT message isn't really a window message that you would send - what happens is that GetMessage will check this flag after all the other posted window messages are processed and returns 0 if it is set. This will cause all windows to correctly close, and you don't need to send it to the windows themselves.

Resources