New keyboard APIs: KeyEventArgs.SuppressKeyPress


Here's the scenario:

In 1.1 whenever someone types one character you want to replace it with another.  (If you're thinking password textbox there's a TextBox.UseSystemPassword=true flag you should use).

So you sync TextBox KeyDown, set handled to true and tack on some placeholder * at the end.

 private void textBox1_KeyDown(object sender, KeyEventArgs e) {
            e.Handled = true;
            textBox1.Text += "*";
  }

The problem is that "Handled" doesn't take care of pending WM_CHAR messages already built up in the message queue - so setting Handled = true does not prevent a KeyPress from occurring.

In order not to break anyone who has currently got e.Handled = true, we needed to add a new property called SuppressKeyChar.  If we went the other way, if "handling" a keydown suddenly started to actually work, we might break folks who accidentally had this set to true.

The new code?

private void textBox1_KeyDown(object sender, KeyEventArgs e) {
            e.SuppressKeyPress = true;
            textBox1.Text += "*";
 }

[Edit 8:43PM - technical correction - thanks Matt!] 

Comments (6)

  1. mabster says:

    This is a timely blog entry, since I discovered SuppressKeyPress only yesterday and used it in a NumericUpDown’s KeyDown event to stop it from beeping when I press Enter. However, I still don’t understand the difference. When you say “only get the very first WM_CHAR”, what does that mean? Surely the first WM_CHAR is the key we pressed, and setting e.Handled should suppress that key? I mean, yeah, obviously it doesn’t, but I don’t understand the why’s and wherefore’s. Matt

  2. jfoscoding says:

    Ok, you got me there, e.Handled doesn’t remove any of the pending WM_CHARs in the queue. e.Handled really only is used to determine if the DefWndProc should be called with the key message… so theoretically if you’re in 1.1 you could set e.Handled in your KeyDown, KeyPress, and KeyUp event. This will prevent the base control from getting it if it implements its logic in the DefWndProc. Calling SuppressKeyPress will remove pending WM_CHAR messages, so the KeyPress event will never get called.

  3. mabster says:

    Ah! So now this is starting to make sense.

    So even if you set e.Handled to true in KeyDown, KeyPress is still called? How bizarre!

    What exactly does e.Handled prevent, then? Obviously if used in, say, a TextBox, it stops the character from being inserted/appended to the control’s Text. But yeah, if I set e.Handled in a NumericUpDown’s KeyDown event when the user hits Enter, I still hear a “beep” as if the key made it to the control.

  4. jfoscoding says:

    Usage of e.Handled is kindof dubious – you really have to know that what you want to do is prevent the DefWndProc (default window proceedure) to be called – and the functionality of the control has to be implemented in DefWndProc for it to work at all.

    If you see e.Handled in your code – you might want to review if it’s actually doing what you think it is.

  5. Sheva says:

    But in WPF, set e.Handled to true does remove the pending WM_CHAR messages.

    Sheva

  6. jfoscoding says:

    Nice!

    Windows Forms and WPF have separate keyboard input models. For Windows Forms you’ll have to use the new property if you want what you think “handled” should do.

Skip to main content