2008-11-11 151 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

相关问题