我对C#PeekMessage
中的方法使用有疑问。
这是我的情况:我按住一个键(例如 Enter 或 F8)一会儿。按住键时,代码会继续执行某些操作。
我试图创建代码以在释放密钥后立即停止做这些事情,但我遇到了一些困难。
我所做的是覆盖ProcessKeyPreview
方法来确定一个键是否被按住一段时间以生成多个按键和/或按键事件。如果是这种情况,一旦释放键,我就 PeekMessage
用来删除以下挂起的消息,并希望它会停止处理那些累积的按键/按键消息,但它没有用。
- WM_CHAR
- WM_SYSCHAR
- WM_IME_CHAR
- WM_KEYDOWN
- WM_SYSKEYDOWN
任何帮助,将不胜感激。
部分代码片段如下所示:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool PeekMessage([In, Out] ref MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove);
//----------------------------------------------
// Define the PeekMessage API call
//----------------------------------------------
[Serializable, StructLayout(LayoutKind.Sequential)]
private struct MSG
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
public int pt_x;
public int pt_y;
}
/// <summary>
/// Trap any keypress before child controls get hold of them
/// </summary>
/// <param name="m">Windows message</param>
/// <returns>True if the keypress is handled</returns>
protected override bool ProcessKeyPreview(ref Message m)
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_CHAR = 0x102;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;
const int WM_SYSCHAR = 0x106;
const int WM_IME_CHAR = 0x286;
KeyEventArgs e = null;
if ((m.Msg != WM_CHAR) && (m.Msg != WM_SYSCHAR) && (m.Msg != WM_IME_CHAR))
{
e = new KeyEventArgs(((Keys)((int)((long)m.WParam))) | ModifierKeys);
if ((m.Msg == WM_KEYUP) || (m.Msg == WM_SYSKEYUP))
{
//If the key is held down for a while to generate multiple WM_KEYDOWN messages
if (mRepeatCount > 1)
{
e.Handled = true;
e.SuppressKeyPress = true;
}
mRepeatCount = 0;
}
// Remove any WM_CHAR type messages if supresskeypress is true.
if (e.SuppressKeyPress)
{
this.RemovePendingMessages(WM_KEYDOWN, WM_KEYDOWN);
this.RemovePendingMessages(WM_SYSKEYDOWN, WM_SYSKEYDOWN);
this.RemovePendingMessages(WM_CHAR, WM_CHAR);
this.RemovePendingMessages(WM_SYSCHAR, WM_SYSCHAR);
this.RemovePendingMessages(WM_IME_CHAR, WM_IME_CHAR);
}
if (e.Handled)
{
return true;
}
}
return base.ProcessKeyPreview(ref m);
}
private void RemovePendingMessages(int msgMin, int msgMax)
{
if (!this.IsDisposed)
{
MSG msg = new MSG();
IntPtr handle = this.Handle;
while (PeekMessage(ref msg, new HandleRef(this, handle), msgMin, msgMax, 1))
{
}
}
}