Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

In a KeyDown event I used SuppressKeyPress to avoid calling KeyPress and KeyUp events. However, although the KeyPress event was stopped the KeyUp event still fires. Why is this?

private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.H)
    {
        listBox1.Items.Add("key down" + e.KeyCode);
        // e.SuppressKeyPress = true;
    }
}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == 'h')
    {
        listBox1.Items.Add("key press" + e.KeyChar);
    }
}

private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
    if(e.KeyCode==Keys.H)
    {
        listBox1.Items.Add("key up" + e.KeyCode);
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
404 views
Welcome To Ask or Share your Answers For Others

1 Answer

Taking a look at how SuppressHeyPress is handled in Control class:

protected virtual bool ProcessKeyEventArgs(ref Message m)
{
    // ...
    if (e.SuppressKeyPress)
    {
        this.RemovePendingMessages(0x102, 0x102);
        this.RemovePendingMessages(0x106, 0x106);
        this.RemovePendingMessages(0x286, 0x286);
    }
    return e.Handled;
}

it's obvious you can't do something like this to suppress a WM_KEYUP message (when a you process the KeyDown event, a KeyPress message is already sent to your control, but the KeyUp message won't fire until the user release the key).

You can test this with following code:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage([In, Out] ref MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove);

[Serializable, StructLayout(LayoutKind.Sequential)]
public 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;
}

private void RemovePendingMessages(Control c, int msgMin, int msgMax)
{
    if (!this.IsDisposed)
    {
        MSG msg = new MSG();
        IntPtr handle = c.Handle;
        while (PeekMessage(ref msg, new HandleRef(c, handle), msgMin, msgMax, 1))
        {
        }
    }
}

private void SuppressKeyPress(Control c)
{
    this.RemovePendingMessages(c, 0x102, 0x102);
    this.RemovePendingMessages(c, 0x106, 0x106);
    this.RemovePendingMessages(c, 0x286, 0x286);
}

private void SuppressKeyUp(Control c)
{
    this.RemovePendingMessages(c, 0x101, 0x101);
    this.RemovePendingMessages(c, 0x105, 0x105);
}

private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.H)
    {
        SuppressKeyPress(sender);       // will work
        SuppressKeyUp(sender);          // won't work
    }
}

A solution would be to use a boolean flag suppressKeyUp, set it to true at KeyDown and check it and resetting it in KeyUp, but you'll have to check it thoroughly and see what happens when the user misbehaves (like pressing two keys).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...