我正在将一个MFC应用程序移植到.NET WinForms.在MFC应用程序中,您可以右键单击菜单或上下文菜单项,然后显示另一个包含诊断和配置项的上下文菜单.我试图将此功能移植到.NET,但我遇到了麻烦.
我已经能够捕获右键单击,禁用单击底层菜单并在正确的位置弹出上下文菜单,但原始菜单一丢失焦点就会消失.
在MFC中,我们通过使用TPM_RECURSE标志调用TrackPopupMenuEx来显示新的上下文菜单.
ContextMenu和.NET中较新的ContextMenuStrip类只有一个Show方法.有谁知道如何在.NET中这样做?
编辑
我已尝试通过ap/invoke 使用TrackPopupMenuEx,但这限制了您使用ContextMenu而不是在我们的应用程序中看起来不合适的ContextMenuStrip.它仍然无法正常工作.它不适用于新的MenuStrip和ContextMenuStrip.
我还尝试了子类化ToolStripMenuItem以查看是否可以向其添加上下文菜单.这适用于MenuStrip,但ContextMenuStrip仍允许右键单击事件作为点击进行传递.
编辑,由于评论:
在:
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; } }