views:

848

answers:

4

I'm trying to innocently call

PeekMessage(&msg, 0, WM_KEYDOWN, WM_KEYUP, PM_NOREMOVE | PM_NOYIELD);

and Windows Vista 64, in the PeekMessage call, is processing messages. The result is that I'm going re-entrant on my paint call, and all sorts of other code.

Painting can take seconds in our application, so we added the PeekMessage call to see if the user hit a key, so we could interrupt that painting and start up the next one. Little did we realize that Windows could start processing messages on us. It'd be a major refactoring to put the real work of painting in a separate thread... We're trying to see if specific keys were pressed, or if the mouse wheel rotated or mouse buttons were clicked, to interrupt rendering.

I've tried adding code specifically to prevent re-entrancy, and then re-injecting paint messages into the queue, etc. It's all very kludgey, and there are cases where it doesn't work well.

Is there some flag I could add to the PeekMessage call? I didn't see anything new in the documentation on MSDN. I really need a PeekMessage that doesn't process messages. Help!

+4  A: 

Perhaps I'm missing the obvious, but the spec is pretty verbose that it will do so:

The PeekMessage function dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist).

...

During this call, the system delivers pending, nonqueued messages, that is, messages sent to windows owned by the calling thread using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that matches the specified filter is retrieved. The system may also process internal events. If no filter is specified, messages are processed in the following order:

  • Sent messages
  • Posted messages
  • Input (hardware) messages and system internal events
  • Sent messages (again)
  • WM_PAINT messages
  • WM_TIMER messages

To retrieve input messages before posted messages, use the wMsgFilterMin and wMsgFilterMax parameters.

Remus Rusanu
Agreed. I didn't write this code. Unfortunately, I don't believe there is any function call that would do I what I need - determine IF a keypress or mouse event is in the queue, without processing any messages.
Matt Cruikshank
You can install hooks with SetWindowsHookEx on WH_KEYBOARD/WH_KEAYBOARD_LL (and mouse), but it requires some privileges and is harder to program against: http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx
Remus Rusanu
Thanks @Remus Rusanu! If you'd post this as an answer to my question, I'd accept it!
Matt Cruikshank
`GetAsyncKeyState` might get you out of the jam you're in. http://msdn.microsoft.com/en-us/library/ms646293%28VS.85%29.aspx
Adrian McCarthy
+1  A: 

I think this is what PeekMessage is supposed to do. The only difference between it and GetMessage is that GetMessage blocks until a message arrives, where as PeekMessage will return TRUE or FALSE depending on whether a message matching the filter was found. It will still process the messages if they are found.

IRBMe
A: 

PeekMessage processes messages because that's what PeekMessage does.

Maybe it's badly named, but PeekMessage do remove the message from the queue if there are any available.

nos
A: 

GetQueueStatus is the fastest way to check if there are available messages. It will only check a few flags and takes only 1 parameter compared to 5 parameters of peekmessage. It will give a quick hint if there are available messages, it will not process the message in any way.

GetQueueStatus and GetInputStatus are related functions.

zemtex