1

我对C#PeekMessage中的方法使用有疑问。

这是我的情况:我按住一个键(例如 Enter 或 F8)一会儿。按住键时,代码会继续执行某些操作。

我试图创建代码以在释放密钥后立即停止做这些事情,但我遇到了一些困难。

我所做的是覆盖ProcessKeyPreview方法来确定一个键是否被按住一段时间以生成多个按键和/或按键事件。如果是这种情况,一旦释放键,我就 PeekMessage用来删除以下挂起的消息,并希望它会停止处理那些累积的按键/按键消息,但它没有用。

  1. WM_CHAR
  2. WM_SYSCHAR
  3. WM_IME_CHAR
  4. WM_KEYDOWN
  5. 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))
        {
        }
    }
}
4

0 回答 0