问题
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!
回答1:
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.
回答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.
回答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.
回答4:
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.
回答5:
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 )
}
}
}
}
来源:https://stackoverflow.com/questions/1133507/is-there-a-function-like-peekmessage-that-doesnt-process-messages