有没有一种方法可以显示“阻塞”?WinForms快捷菜单
本文关键字:阻塞 WinForms 菜单 显示 一种 方法 有没有 | 更新日期: 2023-09-27 18:16:52
是否有一种方法可以显示ContextMenu
并阻止进一步执行,直到项目被选中?特别是,我想获得类似于ShowDialog()
的行为,但对于ContextMenu
。
直接的方法不起作用:
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
因为Click
回调不是直接从Show()
调用,而是在消息循环处理点击事件时稍后的某个点调用。
如果不走运,menu
在事件处理之前被垃圾收集,在这种情况下,事件只是无声地丢失。(这意味着您不能以这种方式真正使用 ContextMenu
s的局部变量。)
这似乎有效,但感觉"不干净":
using (ContextMenu cm = new ContextMenu()) {
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
Application.DoEvents();
}
有更好的方法吗?
抱歉第一个答案。这是我尝试过的。我制作了另一个表单,在其中放置了上下文菜单和计时器。Form2显示为Form1的模态,然后计时器显示Form2上的上下文菜单。
注意表单2设置了一些属性:在任务栏中不可见,没有边框,大小应该与上下文菜单的大小相等。
希望对你有帮助。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Form2 ctxForm = new Form2();
ctxForm.Location = this.PointToScreen(e.Location);
ctxForm.Size = new Size(0, 0);
ctxForm.ShowDialog();
}
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void timer1_Tick(object sender, EventArgs e)
{
//show menu once
contextMenuStrip1.Show(this, PointToClient(Location));
contextMenuStrip1.Focus();
timer1.Enabled = false;
}
private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
this.Close();
}
}
你可以很容易地防止垃圾收集的上下文菜单,而它仍然是显示。
问题是您正在使用lambda作为菜单项的事件处理程序。这是一个匿名方法,因此本身不附加到任何对象实例,这将导致上下文菜单被引用,因此保持活跃。向封闭对象添加一个方法,然后创建一个标准的EventHandler。这样,封闭实例的存在将使ContextMenu保持活动状态。不像c# 1.0那么简洁,但它可以解决问题。
等待菜单不可见。
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
while (cm.Visible == true) Application.DoEvents();