【发布时间】: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 将在任务栏中显示图标化的窗口。它还可以解决您当前的问题。 -
太棒了!谢谢吉米。这让我走上了另一条学习之路,但它确实有效。它还解决了我在失去焦点时菜单不自动关闭的问题!超级明星。谢谢!