2011-12-06 107 views
4

有沒有辦法顯示一個ContextMenu並阻止進一步的執行,直到一個項目被選中?特別是,我想要獲得類似於ShowDialog()的行爲,但要獲得ContextMenu的行爲。有沒有辦法顯示「阻塞」WinForms的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(); 
} 

有沒有更好的辦法?

+1

將您現有的Show()調用後的任何代碼移動到Collapse事件的事件處理函數中。或者使用一個窗體,這樣你可以使用ShowDialog。 –

回答

0

在仍顯示ContextMenu的同時,您可以輕鬆地阻止垃圾回收。

問題是您正在使用lambda作爲菜單項的事件處理程序。這是一個匿名方法,因此它本身不附加到任何會導致ContextMenu被引用並保持活動狀態的對象實例。向封閉對象添加一個方法,然後創建一個標準的EventHandler。這樣,封閉實例的存在將保持ContextMenu的活力。不像C#1.0那麼簡潔,但它可以解決問題。

1

對不起,第一個問題。這是我試過的。我做了另一個窗體,我放置了上下文菜單和一個計時器。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(); 
    } 
} 
0

只是等待菜單不可見。

ContextMenu cm = new ContextMenu(); 
cm.MenuItems.Add("1", (s,e) => {value = 1;}); 
cm.Show(control, location); 
while (cm.Visible == true) Application.DoEvents(); 
相關問題