Some time ago, we learned that the MsgÂWaitÂForÂMultipleÂObjects
function waits only for new events to arrive. In particular, this means that when MsgÂWaitÂForÂMultipleÂObjects
tells you that an event has arrived, you need to process all of those events before looping back and calling MsgÂWaitÂForÂMultipleÂObjects
again, because MsgÂWaitÂForÂMultipleÂObjects
isn’t going to tell you about those old events.¹
It so happens that the GetÂQueueÂStatus
function also manipulates the queue status. Each time you call GetÂQueueÂStatus
to check a flag, that flag is marked as no longer “new” in the queue status, in the same way that MsgÂWaitÂForÂMultipleÂObjects
marks the flag as no longer “new” when it wakes up due to a queue status change.
This behavior of GetÂQueueÂStatus
is very surprising, because you don’t expect a function called “Get” to have destructive side effects.
The GetÂQueueÂStatus
function returns the queue status in two forms, packed into a single 32-bit integer. The low-order 16 bits contain the new queue status bits (the queue status changes since the last time you asked about them), whereas the high-order 16 bits contain the cumulative queue status bits (all the status bits, both old and new). This is explained in the “Return value” section of the documentation, but it’s something that you may read without fully comprehending the consequences.
Therefore, if you want to know if there is (say) any raw input available, either old or new, you need to write
if (HIWORD(GetQueueStatus(QS_RAWINPUT)) & QS_RAWINPUT)
And if you want to drain the raw input, you should use a while
loop to keep processing the raw input until the bit goes clear in the high word.
The fact that GetÂQueueÂStatus
is a destructive operation is one of those hidden gotchas of the window manager. This sort of atomic “test and clear” operation is common inside the window manager, so they exposed a function that let applications do it too, using the same name that the window manager used internally, so you might say that this function was named while wearing window manager colored glasses: The fact that this is a “test and clear” function is obvious if you work on the window manager, and completely surprising if you don’t.
¹ The MsgÂWaitÂForÂMultipleÂObjectsÂEx
function lets you pass the MWMO_
flag to mean, “Also consider old events that haven’t yet been processed.”
Is there a way to post custom coalesceable windows message, like WM_TIMER and WM_PAINT?
The motivation is basically the same as WM_PAINT, "Combining WM_PAINT messages reduces the number of times a window must redraw the contents of its client area.", but with custom tasks.
An imperfect solution is to use MsgWaitForMultipleObjects and SetEvent. But this method is hampered by many internal modal message loops which the application has no control over.
For example, MsgWaitForMultipleObjects has...