0

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.

4

1 回答 1

3

如评论中所述,您必须从 ContextMenuStrip 派生您自己的类,以便您可以覆盖 ProcessMnemonic() 方法。

稍微注释一下,键盘处理在 Winforms 中非常复杂。快捷键击键很早就被处理,在它们被分派到具有焦点的控件之前。必然如此,您不希望为每个控件实现 KeyDown 事件,以便您可以使快捷键起作用。

这从外向内工作,涉及几个受保护的方法,ProcessCmdKey、ProcessDialogChar 和 ProcessMnemonic。如果设置了表单的 KeyPreview 属性,则与 OnKeyDown 一样,这是一个 VB6 兼容功能。因此,表单首先对其进行了尝试,然后它从那里迭代控件,从容器到子控件。

ToolStrip 类(ContextMenuStrip 的基类)覆盖 ProcessMnemonic() 方法以识别按键,并将它们映射到菜单项。因此,为了拦截这个默认处理,您必须自己重写 ProcessMnemonic() 才能首先获得按键操作。

于 2013-01-13T18:06:11.477 回答