When a ContextMenuStrip is opened, if the user types the first letter of a possible selection – it’s as if he clicked on it. I want to intercept that and get the character that he clicked.
The following code does that, but with hard-coding the possible character. I want a generic way to do this, either by disabling the automatic selection by key stroke (leaving only the mouse clicks) or some way to intercept the character.
The following simplified code assumes I want to have a winform’s Text to be the character typed, and the ContextMenuStrip has one option which is “A”.
public Form1()
{
InitializeComponent();
contextMenuStrip1.KeyDown += contextMenuStrip1_KeyDown;
}
private void button1_Click(object sender, EventArgs e)
{
contextMenuStrip1.Show();
}
void contextMenuStrip1_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
if (e.KeyCode == Keys.A)
{
if (e.Shift) Text = "A";
else Text = "a";
}
}
Using the KeyPress event and checking e.KeyChar doesn’t work because it doesn’t get fired. (the “A” click-event gets fired instead.)
Using one of these: e.KeyCode, e.KeyData, or e.KeyValue doesn’t work (without further hard-coding) because they accept a Shift as a Key.
As noted in the comment, you have to derive your own class from ContextMenuStrip so you can override the ProcessMnemonic() method.
Annotating this a bit, keyboard processing is very convoluted in Winforms. Shortcut keystrokes are processed very early, before they are dispatched to the control with the focus. Necessarily so, you would not want to implement the KeyDown event for every control so that you could make a shortcut keystroke work.
This works from the outside in and involves several protected methods, ProcessCmdKey, ProcessDialogChar and ProcessMnemonic. As well as OnKeyDown if the form’s KeyPreview property is set, a VB6 compat feature. So the form gets a shot at it first, then it iterates controls from there, going from container to child controls.
The ToolStrip class (a base class for ContextMenuStrip) overrides the ProcessMnemonic() method to recognize key presses, mapping them to menu items. So in order to intercept this default processing, you have to override ProcessMnemonic() yourself to get a shot at the key press first.