How do I set the keyboard shortcut character for a Windows Forms button with no text?
I have a Windows Forms app with some buttons images but no text. Normally the shortcut is specified with the ampersand character (&). But what does one do when there's no text?
I know there are tricks, such as leading spaces to push the text off to the right or down. Or play with the font, forecolor, etc. But I don't like such tricks because they sometimes backfire.
Should I consider handling the shortcuts for all controls through the Key events of the form? How would this sort out which control is selected? Are form Key events filtered through the form before they're sent on to the Key events of the controls? I'm not sure what to do if I went this way.
CodePudding user response:
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 onl oad(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 onl oad(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
CodePudding user response:
This is how I do it.
set the KeyPreview
to true
for the form to capture keys.
then check the keys on KeyPress
event on the form and trigger button1.PerformClick();
public Form1()
{
InitializeComponent();
KeyPreview = true;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("you pressed Ctrl S");
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.S)
{
button1.PerformClick();
}
}