Is there a function like PeekMessage that doesn't process messages?
Asked Answered
J

5

6

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!

Jarodjarosite answered 15/7, 2009 at 19:37 Comment(0)
D
5

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.

Damien answered 15/7, 2009 at 19:45 Comment(4)
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.Jarodjarosite
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: msdn.microsoft.com/en-us/library/ms644990(VS.85).aspxDamien
Thanks @Remus Rusanu! If you'd post this as an answer to my question, I'd accept it!Jarodjarosite
GetAsyncKeyState might get you out of the jam you're in. msdn.microsoft.com/en-us/library/ms646293%28VS.85%29.aspxPaba
D
3

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.

Damselfish answered 13/9, 2010 at 20:15 Comment(0)
G
2

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.

Genetic answered 15/7, 2009 at 19:49 Comment(0)
R
0

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.

Rahal answered 15/7, 2009 at 20:3 Comment(0)
P
-1
Just modified the PM_REMOVE flag for the PM_NOREMOVE





using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PROJECT_NAME
{
    class cUtil
    {
        //===============================
        cUtil()
        {
        }
        //================================
        ~cUtil()
        {
        }
        //=================================
        public struct Message
        {
            public IntPtr handle;
            public uint msg;
            public IntPtr wParam;
            public IntPtr lParam;
            public uint time;
            public System.Drawing.Point p;
        }

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool PeekMessage(out Message lpMsg, Int32 hwnd, Int32 wMsgFilterMin, Int32 wMsgFilterMax, uint wRemoveMsg);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool TranslateMessage(out Message lpMsg); //(ref Message lpMsg);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern Int32 DispatchMessage(out Message lpMsg); //(ref Message lpMsg);

        //private static uint PM_NOREMOVE = 0x0000;
        private static uint PM_REMOVE = 0x0001;
        //private static uint PM_NOYIELD = 0x0002;
        public static void Peek()
        {
            Message winMsg;
            while (PeekMessage(out winMsg, (Int32)0, (Int32)0, (Int32)0, PM_REMOVE))
            {
                TranslateMessage(out winMsg);
                DispatchMessage(out winMsg);
            }

        }
    }
}


//================================
//================================
//===============================

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PROJECT_NAME
{
    public partial class foNAME : Form
    {
        //===================================
        public foRAMQ()
        {
            InitializeComponent();
        }
        //===================================
        private void Job()
        {
            int cnt = 0;

            while( reading_DBMS() )
            {
                cUtil.Peek();

                .
                .
                .
                .
                .
                cnt++;
                lable_count.Text = string.Format("Count: {0}", cnt )            
            }
    }


    }
}
Pycnidium answered 3/2, 2015 at 15:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.