2008-11-11 95 views
10

我正在將MFC應用程序移植到.NET WinForms。在MFC應用程序中,您可以右鍵點擊菜單或上下文菜單項,然後顯示另一個包含診斷和配置項目的上下文菜單。我試圖將此功能移植到.NET,但我遇到了麻煩。如何右鍵單擊菜單項時顯示上下文菜單

我已經能夠捕獲右鍵單擊,禁用底層菜單的點擊並在正確的位置彈出右鍵菜單,但原始菜單一失去焦點就立即消失。

在MFC中,我們將展示通過調用TrackPopupMenuExTPM_RECURSE標誌的新的上下文菜單。

的ContextMenu和新的ContextMenuStrip類在.NET中只能有一個顯示方法。有誰知道如何在.NET中做到這一點?

編輯

我一直在使用TrackPopupMenuEx通過的P/Invoke嘗試過,但限制你使用文本菜單代替的ContextMenuStrip看起來出來的地方在我們的應用程序。它也仍然無法正常工作。它不適用於新的MenuStripContextMenuStrip

我也嘗試了ToolStripMenuItem的子類來查看是否可以向它添加上下文菜單。這是工作MenuStrip,但ContextMenuStrip仍然允許右鍵單擊事件通過點擊。

+0

爲什麼不直接使用一個子菜單中,這樣,當你將鼠標懸停在菜單項,它顯示了更多的項目? – 2008-11-11 19:18:18

+0

我們的許多菜單已經有子菜單。我們使用此功能爲管理員調整菜單的安全性。例如,右鍵單擊一個菜單並將其設置爲禁用。這存儲在數據庫中並對所有用戶都有影響。 – 2008-11-11 19:21:09

回答

10

編輯,由於評價:

在:

protected override void OnClick(EventArgs e) 
{ 
    if (SecondaryContextMenu == null || MouseButtons != MouseButtons.Right) 
    { 
     base.OnClick(e); 
    } 
} 

這部分

MouseButtons != MouseButtons.Right 

應該和不編譯,因爲它是Control.MouseButtons通話。由於Form繼承Control類,所以直接調用MouseButtons屬性就足夠了。

希望這有助於:

public partial class Form1 : Form 
{ 
    class CustomToolStripMenuItem : ToolStripMenuItem 
    { 
     private ContextMenuStrip secondaryContextMenu; 

     public ContextMenuStrip SecondaryContextMenu 
     { 
      get 
      { 
       return secondaryContextMenu; 
      } 
      set 
      { 
       secondaryContextMenu = value; 
      } 
     } 

     public CustomToolStripMenuItem(string text) 
      : base(text) 
     { } 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing) 
      { 
       if (secondaryContextMenu != null) 
       { 
        secondaryContextMenu.Dispose(); 
        secondaryContextMenu = null; 
       } 
      } 

      base.Dispose(disposing); 
     } 

     protected override void OnClick(EventArgs e) 
     { 
      if (SecondaryContextMenu == null || MouseButtons != MouseButtons.Right) 
      { 
       base.OnClick(e); 
      } 
     } 
    } 

    class CustomContextMenuStrip : ContextMenuStrip 
    { 
     private bool secondaryContextMenuActive = false; 
     private ContextMenuStrip lastShownSecondaryContextMenu = null; 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing) 
      { 
       if (lastShownSecondaryContextMenu != null) 
       { 
        lastShownSecondaryContextMenu.Close(); 
        lastShownSecondaryContextMenu = null; 
       } 
      } 
      base.Dispose(disposing); 
     } 

     protected override void OnControlAdded(ControlEventArgs e) 
     { 
      e.Control.MouseClick += new MouseEventHandler(Control_MouseClick); 
      base.OnControlAdded(e); 
     } 

     protected override void OnControlRemoved(ControlEventArgs e) 
     { 
      e.Control.MouseClick -= new MouseEventHandler(Control_MouseClick); 
      base.OnControlRemoved(e); 
     } 

     private void Control_MouseClick(object sender, MouseEventArgs e) 
     { 
      ShowSecondaryContextMenu(e); 
     } 

     protected override void OnMouseClick(MouseEventArgs e) 
     { 
      ShowSecondaryContextMenu(e); 
      base.OnMouseClick(e); 
     } 

     private bool ShowSecondaryContextMenu(MouseEventArgs e) 
     { 
      CustomToolStripMenuItem ctsm = this.GetItemAt(e.Location) as CustomToolStripMenuItem; 

      if (ctsm == null || ctsm.SecondaryContextMenu == null || e.Button != MouseButtons.Right) 
      { 
       return false; 
      } 

      lastShownSecondaryContextMenu = ctsm.SecondaryContextMenu; 
      secondaryContextMenuActive = true; 
      ctsm.SecondaryContextMenu.Closed += new ToolStripDropDownClosedEventHandler(SecondaryContextMenu_Closed); 
      ctsm.SecondaryContextMenu.Show(Cursor.Position); 
      return true; 
     } 

     void SecondaryContextMenu_Closed(object sender, ToolStripDropDownClosedEventArgs e) 
     { 
      ((ContextMenuStrip)sender).Closed -= new ToolStripDropDownClosedEventHandler(SecondaryContextMenu_Closed); 
      lastShownSecondaryContextMenu = null; 
      secondaryContextMenuActive = false; 
      Focus(); 
     } 

     protected override void OnClosing(ToolStripDropDownClosingEventArgs e) 
     { 
      if (secondaryContextMenuActive) 
      { 
       e.Cancel = true; 
      } 

      base.OnClosing(e); 
     } 
    } 

    public Form1() 
    { 
     InitializeComponent(); 


     CustomToolStripMenuItem itemPrimary1 = new CustomToolStripMenuItem("item primary 1"); 
     itemPrimary1.SecondaryContextMenu = new ContextMenuStrip(); 
     itemPrimary1.SecondaryContextMenu.Items.AddRange(new ToolStripMenuItem[] { 
      new ToolStripMenuItem("item primary 1.1"), 
      new ToolStripMenuItem("item primary 1.2"), 
     }); 

     CustomToolStripMenuItem itemPrimary2 = new CustomToolStripMenuItem("item primary 2"); 
     itemPrimary2.DropDownItems.Add("item primary 2, sub 1"); 
     itemPrimary2.DropDownItems.Add("item primary 2, sub 2"); 
     itemPrimary2.SecondaryContextMenu = new ContextMenuStrip(); 
     itemPrimary2.SecondaryContextMenu.Items.AddRange(new ToolStripMenuItem[] { 
      new ToolStripMenuItem("item primary 2.1"), 
      new ToolStripMenuItem("item primary 2.2"), 
     }); 

     CustomContextMenuStrip primaryContextMenu = new CustomContextMenuStrip(); 
     primaryContextMenu.Items.AddRange(new ToolStripItem[]{ 
      itemPrimary1, 
      itemPrimary2 
     }); 

     this.ContextMenuStrip = primaryContextMenu; 
    } 
} 
2

您可能必須調用該方法。

[DllImport("user32.dll")] 
static extern bool TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, 
IntPtr hwnd, IntPtr lptpm); 

const int TPM_RECURSE = 0x0001; 
+0

到目前爲止,我還沒有設法得到這個工作。 – 2008-11-11 21:19:57

相關問題