Should I consider handling the shortcuts for all controls through the Key events of the Form?
You sure can, overriding ProcessCmdKey() in your Form(s). As you can read in the docs, it's kind of made for this (to provide additional handling of main menu command keys and MDI accelerators)
To associate a Button to a bitwise combination of Keys (the Windows Forms Keys enumerator is decorated with the [Flags]
attribute), you can use a map, often a Dictionary that associates a Key to something else.
In this case, it could be a Button Control or an Action. For example:
private Dictionary<Keys, Button> accelerators = null;
protected override void OnLoad(EventArgs e) {
accelerators = new Dictionary<Keys, Button>() {
[Keys.Alt | Keys.A] = someButton,
[Keys.Alt | Keys.Control | Keys.B] = otherButton
};
base.OnLoad(e);
}
In the ProcessCmdKey
override, test whether the map (Dictionary) contains the combination of keys pressed and raise the Click event of the associated Button if it's a match:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (accelerators.ContainsKey(keyData)) {
accelerators[keyData].PerformClick();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
VB.Net version (since it's tagged):
Private accelerators As Dictionary(Of Keys, Button) = Nothing
Protected Overrides Sub OnLoad(e As EventArgs)
accelerators = New Dictionary(Of Keys, Button)() From {
{Keys.Alt Or Keys.A, someButton},
{Keys.Alt Or Keys.Control Or Keys.B, otherButton}
}
MyBase.OnLoad(e)
End Sub
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If accelerators.ContainsKey(keyData) Then
accelerators(keyData).PerformClick()
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function