【问题标题】:ContextMenuStrip.Show not working half the timeContextMenuStrip.Show 一半时间不工作
【发布时间】:2021-01-31 07:08:29
【问题描述】:

tl/dr:我每第二次调用 ContextMenuStrip.Show,它就不会显示。

我正在构建一个在后台运行的应用程序,但当用户点击特定热键时,它会在鼠标光标上显示一个下拉菜单。

如果应用程序有焦点,这将在 100% 的时间内有效。如果另一个应用程序有焦点(这是我的主要用例),它恰好有 50% 的时间失败。具体来说,第一次按下热键有效,但是一旦您从菜单中选择了一个项目(触发了一个短功能),下一次按下热键就不会显示菜单。如果您在不单击菜单的情况下按住热键,则菜单会在光标位置不断弹出。如果切换回应用程序,每次都会出现菜单。

我对编码还很陌生,但我已经简化了代码,使得热键按下除了运行一行代码 (ContextMenuStrip.Show) 之外什么都不做,我在调试器和 那一行确实会受到打击,而且所有变量在我看来都是一样的,无论是正常工作还是不工作。

编辑:这是我能做的最简单的代码版本。请原谅任何奇怪的事情。我是编码新手,可能正在做一些不相关的奇怪事情!

要重现,运行程序,切换到另一个窗口,按 Ctl-Q 调出菜单,选择一个项目,再次按 Ctl-Q,菜单将无法显示。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
using System.Runtime.InteropServices;

namespace Bug
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            // Register hotkey
            int UniqueHotkeyId = 1;
            int HotKeyCode = (int)Keys.Q;
            Boolean F9Registered = RegisterHotKey(
                this.Handle, UniqueHotkeyId, 2, HotKeyCode
            );
            myPopupMenu.menu = myPopupMenu.BuildMenu();
        }
        // Stuff that makes the hotkey work
        [DllImport("user32.dll")]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        protected override void WndProc(ref Message m)
        {
            // Catch when a HotKey is pressed !
            if (m.Msg == 0x0312)
            {
                int id = m.WParam.ToInt32();
                if (id == 1)
                {
                    // Show Menu on hoteky press
                    myPopupMenu.ShowMenu();
                }
            }
            base.WndProc(ref m);
        }
        public PopupMenu myPopupMenu = new PopupMenu();
    }
    

    public class PopupMenu
    {
        public ContextMenuStrip menu { get; set; }

        public ContextMenuStrip BuildMenu()
        {
            ContextMenuStrip menu = new ContextMenuStrip();
            ToolStripMenuItem item;
            ToolStripMenuItem submenu;

            submenu = new ToolStripMenuItem();
            submenu.Text = "submenu";

            item = new ToolStripMenuItem("item", null, MenuClick);
            submenu.DropDownItems.Add(item);
            menu.Items.Add(submenu);

            return menu;
        }

        public void ShowMenu()
        {
            menu.Show(Cursor.Position);
        }

        public void MenuClick(object sender, EventArgs e) { }
    }
}

【问题讨论】:

  • 你能把你的代码再简化一点,让它可以被其他人运行吗?理想情况下,我希望能够最终复制和复制。我正在寻找MRE
  • 添加了我能做的最好的 MRE!感谢您的观看。
  • 如果您不调用SetForegroundWindow([ContextMenuStrip].Handle)(这是处理该控件的正确方法),您的 ContextMenuStrip 及其所有 ToolStripMenuItem 将在任务栏中显示图标化的窗口。它还可以解决您当前的问题。
  • 太棒了!谢谢吉米。这让我走上了另一条学习之路,但它确实有效。它还解决了我在失去焦点时菜单不自动关闭的问题!超级明星。谢谢!

标签: c# .net winforms


【解决方案1】:

改变

ContextMenuStrip menu = new ContextMenuStrip();

ContextMenuStrip menu = new ContextMenuStrip { AutoClose = false };

您的示例现在 100% 对我有效(专注和不专注)。

为什么,我不太确定。只需使用自动化工具快速更改事物,直到出现所需的行为。

【讨论】:

  • 非常感谢!我用头撞了好几个小时。我不完全理解为什么会这样,但它给了我一些很好的研究领域。我现在在需要的地方添加了手动menu.Close() 命令,看起来一切正常。你是圣人。
  • @Fishy 是的,如果我能找到一些时间,我会查看源代码,但希望尽快为您提供解决方案。如果我发现我会更新的原因。
  • 顺便说一下,我很想知道那个工具是什么!
猜你喜欢
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多