When you call a function, your code doesn’t resume execution until that function returns

Consider this code fragment:

void foo()
  while (true) {

When foo calls bar(), and bar has not yet returned, does foo continue executing? Does baz get called before bar returns?

No, it does not.

The basic structure of the C/C++ language imposes sequential execution. Control does not return to the foo function until bar returns control, either by reaching the end of the function or by an explicit return.

Commenter Norman Diamond asks a bunch of questions, but they’re all mooted by the first:

I can’t find any of the answers in MSDN, and even an answer to one doesn’t make answers to others obvious.

Unless failures occur, the DialogBox function doesn’t return until the new dialog’s DialogProc calls EndDialog. It starts its own message loop. Dkring this time the hwndParent (i.e. owner not parent) window is disabled. However, disabling doesn’t prevent delivery of some kinds of messages to the parent window’s WindowProc or DialogProc, and doesn’t prevent delivery of any messages to the application’s main message loop, right? So aren’t there two or more message loops running in parallel?

As long as the function DialogBox has not yet returned, control does not return to the application’s main message loop, since it is the one which called DialogBox (most likely indirectly).

MSDN doesn’t explain this because it is a fundamental property of the C and C++ languages and is not peculiar to Win32.

Disabling a window does not prevent it from receiving messages in general; it only disables mouse and keyboard input. This is called out in the opening sentence of the EnableWindow function documentation:

The EnableWindow function enables or disables mouse and keyboard input to the specified window or control.

Messages unrelated to mouse and keyboard input are delivered normally. And they aren’t dispatched by the application’s main message loop because, as we saw above, the main message loop isn’t executing!

I would recommend reviewing a book that covers the basics of Win32 GUI programming, since there appear to be some fundamental misunderstandings. Since I try to target an advanced audience, I generally assume that everybody understands the basics and is ready to move on to the intermediate and advanced topics. If you have trouble with the basics, you should work on that part first.

Comments (18)
  1. Medinoc says:

    Norman Diamond seems to assume that Windows are associated to a particular message loop in their thread. Which is false: They just run on whichever message loop the thread is currently running.

    However, fun stuff such as IsDialogMessage() processing doesn't work a window that called DialogBox(). Which isn't that much of a problem, since it receives no keyboard input.

  2. Dan Bugglin says:

    Of course the code sample provided assumes a single-threaded environment.  Problems arise with multithreading since now we can have asynchronous functions that return immediately and continue their work on another thread.

    Though in this case it does sound like Norman didn't get that the message loop runs on the main thread (or more precisely, the calling thread that created the window, IIRC)… if you're running code you can't process messages at the same time.

    Even if you've just used .NET and not "low-level" Win32 you've probably figured this out… if you do something processor intensive the UI stops responding (since you are too busy to handle window messages).  The solution of course is to offload the work onto another thread.

  3. Henke37 says:

    This reminds me of when people mix up function definitions and the function actually getting called. With some languages allowing functions to be defined at any point, some people get confused.

  4. asf says:

    The dialog proc can SendMessage its parent, if they are on the same thread the WndProc is called directly, so while there might not be two message loops, you still have to handle this situation.

  5. AsmGuru62 says:

    Some dialogs behave differently — MFC ;) Message posted (not sent) to a dialog's parent will be received BEFORE dialog ends.

  6. Ben Voigt [Visual C++ MVP] says:

    @AsmGuru: And why wouldn't it?  The dialog's message loop processes the thread message queue.  When you post a message to the parent (assuming it was created in the same thread), it goes in the same queue, so (barring some really messed up PeekMessage filters) it has to get processed before the dialog can receive newly posted messages.  Medinoc has it exactly right, windows are owned by a thread, not by a message loop, and there's a single message queue per thread, not per message loop.

  7. Henning Makholm says:

    Clearly the confusion arises because the asker had not realized that the modal message loop inside DialogBox will happily dispatch messages to other windows if anyone posts them. One will not learn that just by reading the MSDN reference documentation for DialogBox itself — reasonably enough, every manpage cannot explain all the basics it presupposes — but "About Dialog Boxes" does clearly say so: "To process messages for the modal dialog box, the system starts its own message loop, taking temporary control of the message queue for the entire application. When the system retrieves a message that is not explicitly for the dialog box, it dispatches the message to the appropriate window. If it retrieves a WM_QUIT message, it posts the message back to the application message queue so that the application's main message loop can eventually retrieve the message."

  8. Dean Harding says:

    For a second there, I thought Microsoft had started making strides on that time machine… we haven't heard from Norman here in a looong time!

  9. Karellen says:

    Hmm…I'd get confused here because I was under the impression that the main thread message loop was capable of dealing with messages for more than one window at the same time. I mean, doesn't this happen with non-modal dialog boxes?

  10. santosh says:

    @Henning Makholm, Nice guessing what the original question was :)

    But, I think today's post was to point out that *Message Loop* is nothing but a bunch of function calls. "So aren't there two or more message loops running in parallel?" becomes "So aren't there two or more functions running in parallel (in same thread)?

    In some other parallel universe that may be true :)

  11. Chris Oldwood says:

    Problems that arise from code that does not handle re-entrancy (e.g. using static variables) can often manifest as problems that look similar to those you get with multi-threading. For example timer callbacks in your 'main window' will still be dispatched whilst your 'modal dialog' is displayed and to the unwary can appear as if you have two concurrent threads.

  12. alexcohn says:

    I believe that the term "message loop" is often misused, because usually it is handled by somebody else – MFC or .NET or is copied as is from some ancient HELLOWIN.C. We are more familiar with WinProc and message handlers, and sometimes we mistakenly refer to the latter as "message loop".

  13. 640k says:

    Does baz get called before bar returns?

    No, it does not.

    Until DialogBox() is replaced with CreateDialog()

    …to get a modeless window instead of a modal one. What can go wrong!?

  14. Medinoc says:

    @Karellen: You're not confused, you're *right*.

  15. Chris says:

    640k gotcha there Raymond, as soon as you change Norm's question your answer falls apart.

  16. alexcohn says:

    @Chris, thanks for drawing my attention to it: the original question has a very different meaning, as far as I can understand. Norman was asking if there was some implementation details of how the modal dialog message loop works – because this message loop replaces the application message loop (which we supply ourselves, unless we rely on MFC or .NET or other framework). True, he made a wrong assumption that more than one message loop is handling the window messages. It's unfortunate that this misunderstanding distracted Raymond's attention from the real question.

    [Only one message loop runs at a time. They do not run in parallel. That is a fundamental property of the sequential nature of the C language. Even if he misunderstood message loops, I don't see how you can come to the conclusion that the main function resumes execution before the subroutine returns. -Raymond]
  17. alexcohn says:

    @640k, there is an even more subtle way of changing the way message loop works: MFC! When you create a modal dialog with MFC, it's actually a modeless dialog! Probably, this is what AsmGuru62 referred to, not what Ben Voigt made of his comment.

  18. Richard VJ says:

    asynchronous C#/VB in PDC2010 presentation, have a look az8714.vo.msecnd.net/…/FT09-Hejlsberg.pptx

Comments are closed.