views:

855

answers:

5

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.

+1  A: 

Not absolutely positive about this but my best guess says:

  1. The queue is a system object that you access with Win32 API calls. It is not in your process address space at all. So the interrupt handlers can access it (probably through the HAL (Hardware Abstraction Layer) of the kernel).

  2. In Win16, that call took the various subparts of a bigger message and mashed them into a whole. So TranslateMessage would add the WM_KEYPRESS when it found the corresponding WM_KEYDOWN WM_KEYUP sequence. It would also turn various button click messages into doubleclick messages based on internal setting and the timestamps of the messages. Whether it still does this in Win32, I don't know.

  3. DispatchMessage is probably where Window message hooks get processed. So if there's a hook on your window, it is either called here or when the GetMessage is called. I'm not sure. Other than that, DispatchMessage just looks up the WndProc address associated with the window and calls it. There's not much else for it to do.

Hope that helps.

jmucchiello
+9  A: 

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.

Stefan
This is all wrong. The parts of it that are correct, are correct only if the question was about Win16 where the entire OS and applications were co-operativly scheduled on a single thread.
Chris Becke
+3  A: 

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.

Larry Osterman
+1  A: 

To address the last subquestion, a dispatched message will go to your WindowProc after it's been piped through all hooks (WH_CALLWNDPROC)

MSalters
+1  A: 

The simple explanation:

Windows are associated with threads. Each thread with a window has a thread queue in the process's address space. The OS has an internal queue in its own address space for the hardware-generated events. Using details of the event and other state information (e.g., which window has the focus), the OS translates the hardware events into messages that are then placed in the appropriate thread queue.

Messages that are posted are placed directly in the thread queue for the target window.

Messages that are sent are usually processed directly (bypassing the queue).

The details get hairy. For example, the thread queues are more than lists of messages--they also maintain some state information. Some messages (like WM_PAINT) aren't really queued, but synthesized from the additional state information when you query the queue and it's empty. Messages sent to windows owned by other threads are actually posted to the receiver's queue rather than being processed directly, but the system makes it appear like a regular blocking send from the caller's point of view. Hilarity ensues if this can cause deadlock (because of circular sends back to the original thread).

The Jeffrey Richter books have a lot (all?) of the gory details. My edition is old (Advanced Windows). The current edition seems to be called Windows via C/C++.

The OS does a LOT of work to make the message stream appear rational (and relatively simple) to the caller.

Adrian McCarthy