C# · 12月 31, 2021

c# – 当您右键单击菜单项时如何显示上下文菜单

我正在将一个MFC应用程序移植到.NET WinForms.在MFC应用程序中,您可以右键单击菜单或上下文菜单项,并显示另一个包含诊断和配置项的上下文菜单.我试图将这个功能移植到.NET,但是我遇到麻烦.

我已经能够捕获右键单击,禁用基本菜单的点击并弹出正确位置的上下文菜单,但是原始菜单会在失去焦点后立即消失.

在MFC中,通过使用TPM_RECURSE标志调用TrackPopupMenuEx来显示新的上下文菜单.

ContextMenu和.NET中的新的ContextMenuStrip类只有一个Show方法.有人知道如何在.NET中执行此操作?

编辑

我已经尝试通过p / 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; }}