Home > database >  How do I set the keyboard shortcut character for a Windows Forms button with no text?
How do I set the keyboard shortcut character for a Windows Forms button with no text?

Time:10-20

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();
        }
    }
  • Related