Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is Win32 event-driven programming implemented under the hood?

In a Win32 C++ application, we start a message loop that fetches messages from a queue, translates them and then dispatches them. Eventually, each message reaches our WndProc where the associated event can be handled.

I understand that part. What I don't understand is the in between goings-on. Specifically:

  1. Different kinds of OS interrupt handlers must be placing messages in the said 'message queue', but where within the process address space does this queue reside? How is it exposed to the interrupt handler code?
  2. What does it mean to 'translate' the message? What does the call to TranslateMessage() really do?
  3. Once dispatched by DispatchMessage(), what all places does the message swing by before reaching my WndProc (i.e. what does the OS do with it)?

If anyone knows the answers to the above, kindly satisfy my curiosity. Thanks.

like image 362
Frederick The Fool Avatar asked Apr 19 '09 13:04

Frederick The Fool


2 Answers

The OS maintains a message queue, where it puts the events (e.g., from interrupts or other sources). It then sends the messages from that queue to all windows, depending on the message (e.g., it won't send key messages to a window that doesn't have focus).

Applications can have their own queue to process messages. Those queues are created on request (only if needed).

Translating a message is used to create messages that are not 'real' events. For example, the WM_CONTEXTMENU message is 'translated' from either a mouse right-click, or the context menu key, or shift-F10. The WM_CHAR is translated from WM_KEYDOWN messages. And of course many other messages are 'translated' that way.

A message is posted to every window that should receive it. The OS decides depending on the type of message whether a window should receive that message or not. Most messages are waited for by the system, i.e., the message won't get posted to another window until it was processed by the window. This has a great impact for broadcast messages: if one window doesn't return when handling that message, the queue is blocked and other windows won't receive the message anymore.

like image 166
Stefan Avatar answered Oct 06 '22 21:10

Stefan


It depends on how your message is sent and how it's handled.

When you call SendMessage, if the target window is owned by the current thread, the call bypasses the message queue for the window and the window manager directly calls the windowproc on the target window. If the target window is owned by another thread, the window manager effectively calls PostMessage and pumps window messages until the target window returns from the window proc.

When you call PostMessage, the window manager marshals the message parameters and inserts the corresponding object onto the message queue for the target window. When it next calls GetMessage the message is removed from the message queue.

The window manager also registers for raw input events from the input devices (keyboard and/or mouse) and it generates messages for those input events. It then inserts those messages in the queue as appropriate (the processing of input events is complicated because it depends on what messages are already in the message queue for the window).

As Stefan indicated, TranslateMessage just translates accelerator keys - for instance it converts key sequences to WM_COMMAND messages.

like image 35
ReinstateMonica Larry Osterman Avatar answered Oct 06 '22 19:10

ReinstateMonica Larry Osterman