I have a form with CancelButton and AcceptButton (named btnCancel and btnOK). And I have some ComboBoxes as input fields.
ComboBoxes prevent my AcceptButton and CancelButton to receive Escape and Enter keys, so I added this code to KeyDown event for all fields:
if (e.KeyData == Keys.Escape)
{
ComboBox field = (ComboBox)sender;
if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
{
e.SuppressKeyPress = true;
btnCancel.PerformClick();
}
}
else if (e.KeyData == Keys.Enter)
{
ComboBox field = (ComboBox)sender;
if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
{
e.SuppressKeyPress = true;
btnOK.PerformClick();
}
}
This is the code in Clicked event of OK button:
if (!changesAreSaved)
{
SaveChangesToNode();
}
List<int> invalidIndices = ValidateAndRefineNodes(true);
if (invalidIndices.Count == 0)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
MessageBox.Show(this, "Enter correct values for all fields before you press OK.", "Cannot Save Information",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Everything is OK but when a ComboBox has Focus and I press Enter key on my keyboard, btnOK_Clicked calls Fields_KeyDown again only when it shows its MessageBox (on else part of if). Exactly right after MessageBox.Show(...) is being called, KeyDown event is being called for second time without any reason.
This is Call Stack for first call:
And this is for second:
Second call should not occur at all. In second Call Stack, first btnOK_Click (third line) again calls Fields_KeyDown (second line) from MessageBox.Show(...). How is this possible? I'm confused...
Call Stack for second call with External Code visible:
You cannot correctly process Escape and Enter key in KeyDown event because they are handled during the keyboard preprocessing phase - Control.IsInputKey and Control.ProcessDialogKey. Normally controls do that for you, but looks like there is a bug in ComboBox implementation when DropDownStyle is Simple.
To get the desired behavior, create and use your own ComboBox subclass like this
public class MyComboBox : ComboBox
{
protected override bool IsInputKey(Keys keyData)
{
if (DropDownStyle == ComboBoxStyle.Simple)
{
switch (keyData & (Keys.KeyCode | Keys.Alt))
{
case Keys.Return:
case Keys.Escape:
return false;
}
}
return base.IsInputKey(keyData);
}
}
P.S. And of course don't forget to remove your KeyDown event handlers.
While I have no idea about the main reason behind this behavior.
But in this situation obviously KeyDown event triggers 2 times. (Set a breakpoint and you will see.)
Since you need to handle it in code, You can try this to neglect one of Enter keys:
bool handled = true;
private void comboBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
/*Prevent handling the Enter key twice*/
handled = !handled;
if(handled)
return;
//Rest of logic
//OkButton.PerformClick();
}
}
I have a form with CancelButton and AcceptButton (named btnCancel and btnOK). And I have some ComboBoxes as input fields.
ComboBoxes prevent my AcceptButton and CancelButton to receive Escape and Enter keys, so I added this code to KeyDown event for all fields:
if (e.KeyData == Keys.Escape)
{
ComboBox field = (ComboBox)sender;
if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
{
e.SuppressKeyPress = true;
btnCancel.PerformClick();
}
}
else if (e.KeyData == Keys.Enter)
{
ComboBox field = (ComboBox)sender;
if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
{
e.SuppressKeyPress = true;
btnOK.PerformClick();
}
}
This is the code in Clicked event of OK button:
if (!changesAreSaved)
{
SaveChangesToNode();
}
List<int> invalidIndices = ValidateAndRefineNodes(true);
if (invalidIndices.Count == 0)
{
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
MessageBox.Show(this, "Enter correct values for all fields before you press OK.", "Cannot Save Information",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Everything is OK but when a ComboBox has Focus and I press Enter key on my keyboard, btnOK_Clicked calls Fields_KeyDown again only when it shows its MessageBox (on else part of if). Exactly right after MessageBox.Show(...) is being called, KeyDown event is being called for second time without any reason.
This is Call Stack for first call:
And this is for second:
Second call should not occur at all. In second Call Stack, first btnOK_Click (third line) again calls Fields_KeyDown (second line) from MessageBox.Show(...). How is this possible? I'm confused...
Call Stack for second call with External Code visible:
You cannot correctly process Escape and Enter key in KeyDown event because they are handled during the keyboard preprocessing phase - Control.IsInputKey and Control.ProcessDialogKey. Normally controls do that for you, but looks like there is a bug in ComboBox implementation when DropDownStyle is Simple.
To get the desired behavior, create and use your own ComboBox subclass like this
public class MyComboBox : ComboBox
{
protected override bool IsInputKey(Keys keyData)
{
if (DropDownStyle == ComboBoxStyle.Simple)
{
switch (keyData & (Keys.KeyCode | Keys.Alt))
{
case Keys.Return:
case Keys.Escape:
return false;
}
}
return base.IsInputKey(keyData);
}
}
P.S. And of course don't forget to remove your KeyDown event handlers.
While I have no idea about the main reason behind this behavior.
But in this situation obviously KeyDown event triggers 2 times. (Set a breakpoint and you will see.)
Since you need to handle it in code, You can try this to neglect one of Enter keys:
bool handled = true;
private void comboBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
/*Prevent handling the Enter key twice*/
handled = !handled;
if(handled)
return;
//Rest of logic
//OkButton.PerformClick();
}
}
VS2010 C# .Net 4.1
I am working on a form that the user must select or enter initial data in a ComboBox. Using the code below, which took some time to deduce, I enable the Edit button when the user hits the Tab key if the data is correct, otherwise the button is disabled it moves to the next button.
This code works, but a side effect is that the PreviewKeyDown event reoccurs when I set IsInputKey to true. This calls validation twice. The KeyDown event is only called once, and the IsInputKey is false again on the second call so I do need to check validation again.
I'd like to understand why and possibly avoid it.
private void comboBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
if (e.KeyData == Keys.Tab) {
if (ValidationRoutine()) {
e.IsInputKey = true; //If Validated, signals KeyDown to examine this key
} //Side effect - This event is called twice when IsInputKey is set to true
}
}
private void comboBox1_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyData == Keys.Tab) {
e.SuppressKeyPress = true; //Stops further processing of the TAB key
btnEdit.Enabled = true;
btnEdit.Focus();
}
}
The why? is hard to answer, Winforms just does. First from the message loop, again from the control's message dispatcher. The event was really meant as an alternative way to implement the protected IsInputKey() method without having to override the control class. Bit of a hack, I always override and never used the event.
The better mouse trap is to override ProcessCmdKey() instead. Like this:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (this.ActiveControl == comboBox1 && keyData == Keys.Tab) {
if (ValidationRoutine()) {
btnEdit.Enabled = true;
btnEdit.Focus();
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
I have a very simple Windows Forms Application. And, in Windows (or, atleast Windows Forms Applications), when you press Enter while inside a Single-line TextBox Control, you hear a Ding. It's an unpleasent sound, that indicated you cannot enter a newline, because it is a single-line TextBox.
This is all fine. However, in my Form, I have 1 TextBox, and a Search Button. And I am allowing the user to Perform a search by pressing Enter after they've finished typing, so they don't have to use the mouse to click the Search Button.
But this Ding sound occurs. It's very annoying.
How can we make it so just that sound doesn't play at all in my Form?
#David H - Here's how I'm detecting the enter pressing:
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// Perform search now.
}
}
It works for me:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
//Se apertou o enter
if (e.KeyCode == Keys.Enter)
{
//enter key is down
this.doSomething();
e.Handled = true;
e.SuppressKeyPress = true;
}
}
The SuppressKeyPress is the really trick. I hope that help you.
Check out the Form.AcceptButton property. You can use it to specify a default button for a form, in this case for pressing enter.
From the docs:
This property enables you to designate
a default action to occur when the
user presses the ENTER key in your
application. The button assigned to
this property must be an
IButtonControl that is on the current
form or located within a container on
the current form.
There is also a CancelButton property for when the user presses escape.
Try
textBox.KeyPress += new KeyPressEventHandler(keypressed);
private void keypressed(Object o, KeyPressEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.Handled = true; //this line will do the trick
}
}
Just add e.SuppressKeyPress = true; in your "if" statement.
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
//If true, do not pass the key event to the underlying control.
e.SuppressKeyPress = true; //This will suppress the "ding" sound.*/
// Perform search now.
}
}
You can Use KeyPress instead of KeyUp or KeyDown its more efficient
and here's how to handle
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
e.Handled = true;
button1.PerformClick();
}
}
and say peace to the 'Ding'
Use SuppressKeyPress to stop continued processing of the keystroke after handling it.
public class EntryForm: Form
{
public EntryForm()
{
}
private void EntryTextBox_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter)
{
e.Handled = true;
e.SuppressKeyPress = true;
// do some stuff
}
else if(e.KeyCode == Keys.Escape)
{
e.Handled = true;
e.SuppressKeyPress = true;
// do some stuff
}
}
private void EntryTextBox_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter)
{
// do some stuff
}
else if(e.KeyCode == Keys.Escape)
{
// do some stuff
}
}
}
On WinForms the Enter key causes a Ding sound because the form property AcceptButton is not specified.
If you don't need an AcceptButton the ding sound can be suppressed by setting the form KeyPreview to true and enter the following KeyPress event:
private void Form_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '\r')
e.Handled = true;
}
No matter what control is active, there will be no more ding sound when pressing the Enter key. Since the key event proccessing order is KeyDown, KeyPress and KeyUp the Enter key will still work for the KeyDown events for the controls.
I stumbled on this post while trying to handle a KeyDown this worked for me.
If e.KeyCode = Keys.Enter Then
e.SuppressKeyPress = True
btnLogIn.PerformClick()
End If
Supressing the Key Press stops the event from being sent to the underlying control. This should work if you're manually handling everything that the enter key will be doing within that textbox. Sorry about the Visual Basic.
$("#txtSomething").keypress(function (e) {
if (e.which == 13) {
e.Handled = true; //This will prevent the "ding" sound
//Write the rest of your code
}
});
There is a very little chance anyone gets to this answer but some other answers are truly scary. Suppressing event on KeyDown kills 2 additional events in one strike. Setting e.Handled property to true is useless in this context.
The best way is to set Form.AcceptButton property to the actual Search Button.
There is also another way of utilizing Enter key - some people may want it to act as TAB button. To do that, add a new Button, set its Location property outside of the Form area (i.e. (-100, -100)) - setting Visible property to false may disable Button handlers in some cases. Set Form.AcceptButton property to your new button. In Click event handler add following code
this.SelectNextControl(ActiveControl, true, true, true, true)
Now, you may want to transfer focus only when focus it on TextBox you may want to either test ActiveControl type or use e.Supress property in event handlers of controls not meant to use Enter as TAB
That's it. You don't even need to capture e.KeyCode
Set your Search button's IsDefault property to true. This will make it a default button and it will be auto-clicked when Enter is pressed.
Well I lived with this problem long enough and looked it up here.
After thinking about this for quite some time and wanting the simplest way to fix it I came up with the easiest but not so elegant way to fix it.
Here is what I did.
Put 2 invisible buttons "Ok" and "Cancel" on the form.
Set the AcceptButton and CancelButton Property on the form to the invisible buttons.
Added no code to the buttons!
This solved all the secondary problems listed in this thread including the ToolStripMenu. My biggest complaint was the BindingNavigator, when I would enter a record number into the Current position to navigate to and pressed enter.
As per the original question in which the programmer wanted a search function when the enter button was pressed I simply put the search code in the invisible OK Button!
So far this seems to solve all problems but as we all know with Visual Studio, something will probably crop up.
The only other possible elegant way I could think of would be to write a new keystroke handling class which is way to much work for most of my projects.
You can set your textbox multi-line to true then handle the Enter key press.
private void yourForm_Load(object sender, EventArgs e)
{
textBox1.Multiline = true;
}
//then write your TextBox codes
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// doSomething();
}
}
i changed the textbox properties for an multiline textbox and it works for me.
Concerning the e.SuppressKeyPress = true; solution, it works fine by itself. Setting SuppressKeyPress to true also sets Handled to true, so there's no need to use e.Handled= true;
void RTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Enter)
{
//do ...
bool temp = Multiline;
Multiline = true;
e.Handled = true;
Multiline = temp;
}
}
I have a form with a single text box on it. No other controls. Whenever I type the 'Enter' key or the 'Esc' key, the form functions as I desire; but I hear that horrible Windows error sound. The code looks similar to the following...
public class EntryForm: Form
{
public EntryForm()
{
}
private void EntryTextBox_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter)
{
// do some stuff
Hide(); // I've also used DialogResult = DialogResult.OK here
e.Handled = true;
}
else if(e.KeyCode == Keys.Escape)
{
Hide(); // I've also used DialogResult = DialogResult.Cancel here
e.Handled = true;
}
}
}
I can 'hack' it and make the noise stop by adding the following code to the form's constructor.
AcceptButton = new Button();
CancelButton = new Button();
As I stated this causes the sound to not play, but I think this is bad form; especially since I don't need a button on the form.
Anyone know why this is the behavior and if there is a cleaner way to stop the error sound from playing?
In the KeyDown event, set e.Handled = true and e.SuppressKeyPress = true.
There's a more "correct" fix, one that works regardless of how many controls you have and follows the Windows Forms design model. Paste this code into your form:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == Keys.Escape || keyData == Keys.Enter) {
this.Hide();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
This is too long a reply to Nobugz answer to fit in a comment. If you use Nobugz code as is :
the Form is going to be hidden no matter which control on the form is active and has keyboard input focus, and that is independent of whether the Form has the 'KeyPreview property set to 'true or 'false.
Here's what you need to do to make only a specific control (in this case a TextBox named 'textBox1) be hidden in the ProcessCmdKeys over-ride :
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (msg.HWnd == textBox1.Handle)
{
if (keyData == Keys.Escape || keyData == Keys.Enter)
{
textBox1.Hide();
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
Of course if you wanted to handle the case of multiple controls needing to be hidden, you could implement a 'switch statement or whatever to test the msg.HWnd against : note I make the assumption here that all controls that could have keyboard input will have a valid HWnd.
Some memory (vague) of a situation in which I used this technique, and a text input control somehow still had keyboard input focus ... when I did not intend for it to ... makes me want to add an additional test like this :
&& this.ActiveControl == textBox1
But, take that with a "grain of salt" since I can't be certain it is necessary.