Reputation: 61
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);
}
}
Upvotes: 0
Views: 9178
Reputation: 706
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).
Upvotes: 1
Reputation: 9780
Yeah, try putting
e.Handled = true;
after the e.Suppress... = true;
.
Upvotes: 0