[英]Is there a way to show a “blocking” WinForms ContextMenu?
有沒有辦法顯示ContextMenu
並阻止進一步執行,直到選擇了一個項目? 特別是,我想獲得類似於ShowDialog()
行為,但是對於ContextMenu
。
直接的方法不起作用:
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
因為Click
回調不是直接從Show()
調用,而是在消息循環處理click事件時稍后調用。
如果你運氣不好, menu
會在事件處理之前被垃圾收集,在這種情況下,事件就會無聲地丟失。 (這意味着你不能以這種方式真正使用ContextMenu
的局部變量。)
這似乎有效,但感覺“不干凈”:
using (ContextMenu cm = new ContextMenu()) {
cm.MenuItems.Add("1", (s,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();
}
}
只是等待菜單不可見。
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
while (cm.Visible == true) Application.DoEvents();
您可以輕松地阻止ContextMenu的垃圾收集,同時仍然顯示它。
問題是您使用lambda作為菜單項的事件處理程序。 這是一個匿名方法,因此它本身不會附加到任何會導致ContextMenu被引用並因此保持活動的對象實例。 將方法添加到封閉對象,然后創建標准EventHandler。 這樣,封閉實例的存在將使ContextMenu保持活動狀態。 不是簡潔和非常C#1.0,但它將解決問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.