c# – 有没有办法显示“阻塞”WinForms ContextMenu?

有没有办法显示ContextMenu并阻止进一步执行,直到选择了一个项目?特别是,我想获得类似于ShowDialog()的行为,但是对于ContextMenu.

直接的方法不起作用:

ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("1",(s,e) => {value = 1;});
cm.Show(control,location);

因为Click回调不是直接从Show()调用,而是在消息循环处理click事件时稍后调用.

如果你运气不好,菜单会在事件处理之前被垃圾收集,在这种情况下,事件就会无声地丢失. (这意味着你不能以这种方式真正使用ContextMenus的局部变量.)

这似乎有效,但感觉“不干净”:

using (ContextMenu cm = new ContextMenu()) {
    cm.MenuItems.Add("1",e) => {value = 1;});
    cm.Show(control,location);
    Application.DoEvents();
}

有没有更好的办法?

解决方法

对不起,第一个答案.这是我尝试过的.我创建了另一个表单,我将上下文菜单一个timer.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();
    }
}

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...