Holy cow, I wrote a book!
The MsgWaitForMultipleObjects and
allow you to specify whether you want to want for any or all
of the handles
(either by passing bWaitAll = TRUE or by passing
dwFlags = MWMO_WAITALL, accordingly).
But you never want to wait for all handles.
bWaitAll = TRUE
dwFlags = MWMO_WAITALL
Waiting for all handles means that the call does not return unless
all the handles are signalled and a window message
meeting your wake criteria has arrived.
Since you are typically waiting for messages out of a sense of
obligation (keeping the UI thread responsive)
rather than one of expectation,
even if all the handles you pass become signalled,
your program will still stall until a window message arrives.
(And if you thought you were being a good UI citizen by using
MsgWaitForMultipleObjectsEx, you aren't actually helping any
because waiting for all objects means that
the call will not return even if a message is ready,
since it's also waiting for those handles you passed.)
which are built on top of
the MsgWaitForMultipleObjectsEx function
suffer from the same problem.
The reason for this can be gleaned from the
you just have to put on your thinking cap.
Notice that if a message arrives when you are waiting for any handle,
the return value is
WAIT_OBJECT_0 + cHandles.
Notice also that the maximum number of objects you can wait
MAXIMUM_WAIT_OBJECTS - 1.
Obviously, what's happening under the covers is that
creates a handle that will be signalled when the message
queue reaches one of the states you requested in the wake mask,
adds that handle to the end of the array you passed in,
and then passes the whole thing to the
(Note that the getting access to that internal handle won't be
of any use to you, the application, since you don't know how to
tell the window manager what wait states should result
in the event being set.)
WAIT_OBJECT_0 + cHandles
MAXIMUM_WAIT_OBJECTS - 1
(Larry Osterman reminded me that he
covered the same topic a while back.
So now you get to see it twice.)