How does the message queue work in Win32?

I read something on Win32 and how the message loop works, and there is something that still remains unclear: what exactly is stored in the message queue? The integer value corresponding to the message ( WM_COMMAND , WM_CREATE , etc.), Or a pointer to the MSG structure containing the integer value of the message and other things, such as wParam , lParam , etc.

+6
source share
3 answers

To answer your question, each message in the queue stores at least

  • handle to the window the message is directed to
  • message code, wParam and lParam, as you rightly noted,
  • The post time of the message you retrieve using GetMessageTime() ,
  • for user interface messages, the cursor position when the message was published (see GetMessagePos() ).

Please note that not all messages are actually queued. Messages that are sent with SendMessage() window from the stream to which the window belongs are never saved; instead, the message function of the recipient window is called directly. Messages sent from other threads are saved until they are processed, and the sending thread is blocked until a message is received, either by exiting a window function or explicitly calling ReplyMessage() . The InSendMessage() API function helps you determine if the Windows function is processing a message sent from another thread.

Messages that you or the system publish are queued, with some exceptions.

  • WM_TIMER messages are never saved; instead, GetMessage() creates a timer message if there are no other messages in the queue and the timer has matured. This means that, firstly, timer messages have the lowest priority to delete from the queue, and secondly, several messages from the timer with a short period will never be overflowed by the queue, even if GetMessage() not called for some time. As a result, one WM_TIMER message is sent for this timer, even if the timer has passed several times since the last WM_TIMER message was processed from this timer.

  • Similarly, WM_QUIT is also not saved, but only marked. GetMessage() pretends to have received WM_QUIT after the queue has been exhausted, and this is the last message it receives.

  • Another example is the WM_PAINT message (@ cody-gray hint to remind you of this). This message is also mimicked when any part of the window is marked as dirty and needs to be repainted. This is also a low-priority message that was created so that several invalid areas in the window are repainted at the same time when the queue becomes empty, to reduce the responsiveness of the GUI and reduce flicker. You can call an immediate redraw by calling UpdateWindow() . This function acts like SendMessage() , in the sense that it does not return until the open part of the window is redrawn. This function does not send WM_PAINT to the window if the invalid area of ​​this window is empty, as an obvious optimization.

There may be other exceptions and internal optimizations.

Messages sent using PostMessage() fall into the thread queue to which the window to which the message is sent belongs.

What form of messages are stored inside, we do not know, and we do not care. The Windows API abstracts this completely. The MSG structure is populated in the memory you pass to GetMessage() or PeekMessage() . You do not need to know or worry about the details of the internal implementation beyond those described in the Windows SDK manuals.


¹ I do not know exactly how WM_PAINT and WM_TIMER take precedence over each other. I assume WM_PAINT has a lower priority, but I could be wrong.

+13
source

Message Queuing in Windows is an abstraction. It is very useful to think of it as a queue, but the actual implementation of it is much more detailed. There are four different message sources in Windows:

  • Messages sent by SendMessage (). Windows directly calls the window procedure, the message is not returned by Peek / GetMessage (), but requires a call to this function to send. Of course, most messages are delivered this way. WM_COMMAND is similar to this, it is directly dispatched by code that converts a key-down event, such as TranslateAccelerator (). No queuing behavior.

  • Messages that are synthesized from window state. The best examples are WM_PAINT, set when the status flag "window has dirty rectangle" is set. And WM_TIMER when the “Timer expired” status flag is set. These are low priority messages, only delivered when the message queue is empty. They are delivered by GetMessage () but do not live in the queue.

  • Enter event messages for the keyboard and mouse. These are messages that really have queued behavior. For the keyboard, this ensures that the forward-forward operation does not work, no keystroke is lost when the program is not ready to accept the keystroke. A bunch of states is associated with it, for example, the entire state of the keyboard is copied. About the same for the mouse, except that there are fewer states. The WM_MOUSEMOVE message is an interesting corner case; the queue does not store every pixel passed by the cursor. Changes in position are accumulated in one message, saved or delivered when necessary.

  • Messages stored in a queue using an explicit call to PostMessage (). This is fully consistent with the program code, it is obvious that it needs to store the call arguments plus the time the call was made so that it can be accurately reproduced back into GetMessage ().

+9
source

MSDN has a good article here explaining all messages and message queues.

But in order to answer your question, there is a queue for each window, it temporarily saves messages and their associated parameters, regardless of whether its MSG queue is defined, but it is most likely (or something similar) .It should also be noted that all messages are sent to the queue, some require immediate processing.

0
source

Source: https://habr.com/ru/post/1395881/


All Articles