【问题标题】:Problems displaying a ContextMenu during the KeyDown eventKeyDown 事件期间显示 ContextMenu 的问题
【发布时间】:2009-10-07 10:01:55
【问题描述】:

当有人按下“Alt-A”时,我正在使用以下代码在我的表单上显示上下文菜单:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Alt && e.KeyCode == Keys.A)
    {
        ContextMenuStrip  menu = new ContextMenuStrip();
        ToolStripMenuItem item = new ToolStripMenuItem("Hello &World");
        item.Click += new EventHandler(item_Click);
        menu.MenuItems.Add(item);

        ToolStripMenuItem item2 = new ToolStripMenuItem("Some &Andriod");
        item2.Click +=new EventHandler(item_Click);
        menu.MenuItems.Add(item2);

        menu.Show(this, new Point(0,0));
    }
}

void item_Click(object sender, EventArgs e)
{
    MessageBox.Show("Hey!")
}

我遇到的问题是第二个菜单项(“Some &Android”)在菜单显示后立即被“点击” - 显然是因为按键(Alt-A)被立即传递给菜单。

如果我将该菜单项更改为具有不同的助记符(例如“&Some Android”),则不会发生这种情况,并且菜单会正常显示。

我知道 ContextMenu 类已被弃用,但有什么方法可以防止这种行为吗?我已经尝试将 EventArgs 的 Handled 属性设置为 true,但什么也没做(大概是因为在事件处理程序完成之前不会做任何事情,并且 Show() 方法会暂停执行,直到不再显示 ContextMenu。

更新:我已经更新了代码以使用较新的 ContextMenuStrip 类并发现发生了同样的事情,但是 ContextMenuStrip 类为我提供了更多方法来覆盖允许更好地控制菜单项。

我注意到,使用 ContextMenuStrip 类时,Show() 方法会立即返回(同时仍显示菜单),但是即使将事件 args 上的 Handled 属性设置为 true 也不会阻止按键被处理通过上下文菜单。

我正在考虑使用一些更复杂的逻辑来决定是否根据自显示菜单以来是否经过某个时间间隔以及此后是否处理了 KeyUp 事件来触发 click 事件,但是这一切看起来都非常混乱 - 肯定有人以前遇到过这个问题吗?

【问题讨论】:

    标签: c# contextmenu


    【解决方案1】:

    我在打开上下文菜单时按下 Alt 键时遇到了同样的问题。我发现这是上下文菜单中的关键事件,它在创建后不久就释放了它。我通过继承 contextmenustrip 并覆盖ProcessCmdKey 方法解决了这个问题,如下所示:

    public partial class AdvancedContextMenuStrip : ContextMenuStrip
    {
        public AdvancedContextMenuStrip()
        {
            InitializeComponent();
        }
    
        protected override bool ProcessCmdKey(ref Message m, Keys keyData)
        {
            if ((keyData & Keys.Alt) == Keys.Alt)
                return true;
    
            return base.ProcessCmdKey(ref m, keyData);
        }
    }
    

    【讨论】:

    • 这解决了我的问题。如果当前按下某个键,我想停止上下文菜单打开。检测到目标键时在覆盖方法中使用 Close() 有效。
    • 我需要通过右键单击打开上下文菜单,但是当单击与 Alt 一起单击时会给出不同的项目。在不覆盖 ProcessCmdKey 的情况下,按下 alt 时上下文菜单会立即关闭。这段代码解决了这个问题。
    【解决方案2】:

    我认为这可能与您在 KeyDown 中打开菜单然后 KeyUp 被传递到菜单这一事实更相关。

    因此,您或许应该将打开的菜单移至 KeyUp 或 KeyPress。这应该可以完全避免这个问题。

    【讨论】:

    • 嗯,可能我有点草率 - 是的,将相同的逻辑放入 KeyUp 事件可以防止这种情况发生,但理想情况下我希望在 KeyDown 期间显示菜单 - 在我释放任何之前触发菜单键,(所以我不知道这是否是被触发的按键事件)
    • 嗯,那么我认为您应该尝试通过在菜单和表单上注册 KeyUp/Down 的事件处理程序并打印适当的诊断消息来弄清楚 what 到底发生了什么。就在我的脑海中,我不知道这里到底有什么责任。如果e.Handled = true 没有帮助,它闻起来就像是 KeyPress 或 KeyUp 触发了菜单条目。
    • 我已经为我的表单添加了 KeyPress 和 KeyUp 的处理程序,但是这些都没有被触发。我还覆盖了 MenuItem 上的 ProcessCmdKey 方法,并且也没有被触发 - 我想不出任何其他与按键相关的方法或事件要附加到。
    • 嗯,那我不知道,抱歉。
    • 我想我将不得不使用 ContextMenuStrip 重新实现并使用一些逻辑来过滤掉这个被引发的关键事件 - 我将其标记为已接受,因为它确实解决了问题(但让菜单出现在 KeyUp 上的 UI 感觉很糟糕)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-19
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    相关资源
    最近更新 更多