I have a form with an button which is set as the AcceptButton of the form. The form has several other controls. Now when I press Enter on other controls the form gets closed because of the accept button on the form. Same goes for CancelButton. How do I handle this. I tried hooking on to keypress keydown event of the form and controls. None works. Any work around for this?
Thanks a ton,
Datte
That is how the AcceptButton property works. It specifies the button that is automatically clicked whenever you press <Enter>.
If you don't want this behaviour, don't set it as the AcceptButton. There is no other reason to do it.
Not exactly sure about how you expect your form to function, but you could do something like the following to have a little more control over things:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Enter)
{
// do something
}
if (keyData == Keys.Escape)
{
// do something else
}
return base.ProcessCmdKey(ref msg, keyData);
}
You can remove AcceptButton from form and set the KeyPreview property on the form that'll handle its KeyDown event. There you can check for the Enter key and take the action accordingly.
This is one of the feature of the form i.e.
if button does not have a focus if you still want desired code to be executed when user click Enter...
Set the AcceptButton property of a form to allow users to click a button by pressing the ENTER even if the button does not have focus.
Regards.
Try This One In VB>net
If CType(Me.ActiveControl, Button).Name = Button1.Name Then
End If
Related
I have a modal Form with three Buttons, A B and C.
In addition, I have two Buttons: OK and Cancel. The OK Button's DialogResult property is set to DialogResult.OK and the Cancel Button DialogResult.Cancel.
The Form's AcceptButton and CancelButton properties are set to these Buttons.
Currently, the Form is closed when I press the ESC key but if I click the ENTER key when one of the other Buttons (A,B,C) is the Active Control, the Form is not closed. How can I overcome this?
I have two options:
Enter will always close the form (select the focused button and then close it),
The first Enter key press will select the focused button and a second ENTER press will close the Form. The problem is that maybe Button A was selected but the user can go over Button B or C using the arrow keys.
I can't set a DialogResult.OK to the other Buttons, because - in that case - a normal click will also close the Form and I have no way to detect if the event was called because of a Click event or the ENTER key...
If you want to activate the Default button - the Button that is set as the Form's AcceptButton - when another Button has the Focus, but not another Control, as a TextBox, that may want to accept the Enter key, you can override ProcessCmdKey (since pressing the Enter key doesn't raise the KeyDown event and the Click event is raised before the KeyUp event), verify whether the ActiveControl is of type Button (or other type of Controls you want to behave the same way) and set the ActiveControl to your AcceptButton.
The Enter key is transferred to the AcceptButton and the Dialog is Closed, returning DialogResult.OK (since you have already set the Button's DialogResult value):
Note: this assuming that the Container Control is the same.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Enter) {
if (ActiveControl.GetType() == typeof(Button) &&
ActiveControl != AcceptButton) {
ActiveControl = AcceptButton as Button;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
In case you just want to change the ActiveControl, setting the Focus to the AcceptButton - so the User needs to press the Enter key twice to confirm, return true after you have changed the ActiveControl, to signal that the input has been handled:
// [...]
if (keyData == Keys.Enter) {
if (...) {
ActiveControl = AcceptButton as Button;
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
I have a Windows Form, with a ListView and a TextBox placed right on top of it. Also there is a button named 'Submit' on the Form with AcceptButton set to true.
Now, my requirement is that, whenever I load the form and hit Enter, Submit button gets triggered, which is fine. But, when I select the TextBox and type something in it and then hit Enter, the focus should come to the ListView , but not the AcceptButton
How can I achieve this?
You can set the AcceptButton based on the active control, or as a better option, handle ProcessDialogKey yourself. This is the method which contains the logic for AcceptButton.
So you can override it, for example:
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Enter)
{
if (this.ActiveControl == this.textBox1)
{
MessageBox.Show("Enter on TextBox1 handled.");
return true; //Prevent further processing
}
}
return base.ProcessDialogKey(keyData);
}
How can I prevent that if the user presses one of the arrow keys, a button on the form is focused?
I am programming a small game, so this would prevent the user from being able to move. Sorry for the vague explanation.
EDIT:
The player is a PictureBox with a graphic in it that is moved by:
private async void Form1_KeyDown(object sender, KeyEventArgs e)
In your Form.cs override the ProcessCmdKey like this:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (!msg.HWnd.Equals(Handle) &&
(keyData == Keys.Left || keyData == Keys.Right ||
keyData == Keys.Up || keyData == Keys.Down))
return true;
return base.ProcessCmdKey(ref msg, keyData);
}
A way to handle this scenario is to set form.KeyPreview = true (see MSDN) and then handle the keys in KeyPress / KeyDown event handlers:
Quoting MSDN for KeyPress Event:
To handle keyboard events only at the form level and not enable other controls to receive keyboard events, set the
KeyPressEventArgs.Handled property in your form's KeyPress
event-handling method to true.
Test for arrow in your keysEvent, manage them the way you need and set Handled=true to avoid default behavior (move focus to next control)
What works for me is to set the button property "TabStop" to false and you can also play with the TabIndex property of the controls on the form to technically set what will be focused when the form loads.
TabStop - sets if pressing TAB can set/give focus to the control and when pressing the TAB key it will increment through the controls on the form according to the -
TabIndex - which dictates which control will get focus next.
So if Button A has tabIndex 1 and Button B has tabIndex 2 and button C has tabIndex 3, but Button B has tabStop = false, then pressing TAB will go from button A to Button C, it will skip Button B.
-Keep in mind that not all controls seem to have a "TabStop" property, I have noticed that textbox, button and datagridview does have the property, but stuff like labels and groupbox and picturebox does not have TabStop, only TabIndex.
I used KeyDown event and some simple code like if (e.KeyCode == Keys.F1) to capture F1 is pressed on a form BUT if there are some text boxes on the form or if there are some spreadsheets with Dock Fill on the form then the code above gets useless and does nothing. But I want to do something when user presses F1 on this form. so how do we capture a specific keydown event like F1 on the whole form..and I do not want to go to the route that capture the KeyDown of all other controls on the form and pass them to the Form for processing. is there any cleaner way to do this?
Yes, indeed there is. The correct way for the form to handle key events regardless of the control that currently has the input focus is to override the ProcessCmdKey method of your form class:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.F1)
{
MessageBox.Show("You pressed the F1 key");
return true; // indicate that you handled this keystroke
}
// Call the base class
return base.ProcessCmdKey(ref msg, keyData);
}
You return true to indicate that you handled the keystroke and don't want it to be passed on to other controls. If you do want it to be passed on to the event handlers for other controls, simply return false.
And you're best off ignoring the KeyPreview property. That's an anachronism from the VB 6 days and not really the preferred way of doing this in the .NET world. Further reading: Disadvantage of setting Form.KeyPreview = true?
Set the form's KeyPreview to true. This will make sure the form get the keypress messages first and if you handle it, you can set e.Handled = true so it doesn't passed down to the controls.
Turn on KeyPreview and every key press in the form will get routed through it's key event handlers first.
Another way is to Override the ProcessCmdKey function http://msdn.microsoft.com/en-us/library/system.windows.forms.control.processcmdkey(v=VS.100).aspx
I have a C# winform, on which I have 1 button.
Now, when I run my application, the button gets focus automatically.
The problem is KeyPress event of my form does not work because the button is focused.
I have tried this.Focus(); on FormLoad() event, but still the KeyPress event is not working.
You need to override the ProcessCmdKey method for your form. That's the only way you're going to be notified of key events that occur when child controls have the keyboard focus.
Sample code:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// look for the expected key
if (keyData == Keys.A)
{
// take some action
MessageBox.Show("The A key was pressed");
// eat the message to prevent it from being passed on
return true;
// (alternatively, return FALSE to allow the key event to be passed on)
}
// call the base class to handle other key events
return base.ProcessCmdKey(ref msg, keyData);
}
As for why this.Focus() doesn't work, it's because a form can't have the focus by itself. A particular control has to have the focus, so when you set focus to the form, it actually sets the focus to the first control that can accept the focus that has the lowest TabIndex value. In this case, that's your button.
Try setting the Form's KeyPreview property to True.
Set keyPreview = true on main form
I would use one of the following:
Set the TabIndex property of the button to 0.
Set the IsDefault property of the button to true - So, It will be fired when pressing the ENTER key.
I had this same problem and I know this question was answered long ago, but my solution to this problem came from another stack overflow question in which my only button grabbed and kept focus. I accepted the users advice and created a button which couldn't get focus.
Maybe someone will find this useful:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace I2c_Programmer {
class NoSelectButton : Button{
public NoSelectButton() {
SetStyle(ControlStyles.Selectable, false);
}
}
}
Go into your designer, where the button is created and switch out the new System...button with your new class "new NoSelectButton();"