'The Enter Key does not close a Form if the Focus is on a Button that is not the AcceptButton

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:

  1. Enter will always close the form (select the focused button and then close it),

  2. 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...



Solution 1:[1]

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);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1