如何将ContextMenuStrip添加到ToolStripMenuItem

我希望当我点击一个菜单项时,显示一个上下文菜单,其中包含“删除”,“重命名”等项目。

右键单击菜单项时如何绑定自己的上下文菜单?

我想到的第一个想法是在ToolStripMenuItem上连接一些MouseDown事件,并在屏幕坐标中的鼠标位置显示第二个ContextMenuStrip 。 但事情并非如此简单。 问题是这样做需要连接每个项目的事件,在该事件上以某种方式显示第二个ContextMenuStrip 将关闭当前的ContextMenuStrip(甚至我们添加一些Closing事件处理程序并设置e.Cancel = true; )。 这里有点棘手。 我们可以想到当前ContextMenuStripMouseDown事件,但实际上这个事件几乎没有被触发,因为所有项都位于ContextMenuStrip之上。 这让我想到了我们可以捕获WM_RBUTTONDOWN并在那里运行代码的更深层次的阶段。 我们可以自定义ContextMenuStrip以在WndProc捕获该消息,或者我们可以使用自定义NativeWindow 。 我想在这里使用NativeWindow 。 这是代码的时间(完美地工作):

 public class NativeContextMenuStrip : NativeWindow { public class ShowContextMenuEventArgs : EventArgs { public ToolStripDropDown ContextMenuToShow {get; set;} } public delegate void ShowContextMenuEventHandler(ShowContextMenuEventArgs e); public event ShowContextMenuEventHandler ShowContextMenu; private Color previousItemBackColor; public ToolStripItem SourceItem { get; set; } bool keepOpen; protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == 0x204) {//WM_RBUTTONDOWN OnShowContextMenu(new ShowContextMenuEventArgs()); } } protected virtual void OnShowContextMenu(ShowContextMenuEventArgs e) { var handler = ShowContextMenu; if (handler != null) { handler(e); if (e.ContextMenuToShow != null) { ContextMenuStrip toolStrip = (ContextMenuStrip)Control.FromHandle(Handle); Point client = toolStrip.PointToClient(Control.MousePosition); SourceItem = toolStrip.GetItemAt(client); previousItemBackColor = SourceItem.BackColor; SourceItem.BackColor = SystemColors.MenuHighlight; e.ContextMenuToShow.Closed -= restoreItemState; e.ContextMenuToShow.Closed += restoreItemState; keepOpen = true; e.ContextMenuToShow.Show(Control.MousePosition); keepOpen = false; } } } protected override void OnHandleChange() { base.OnHandleChange(); ContextMenuStrip toolStrip = Control.FromHandle(Handle) as ContextMenuStrip; if (toolStrip != null) { toolStrip.Closing += toolStripClosing; } } private void restoreItemState(object sender, EventArgs e) { SourceItem.BackColor = previousItemBackColor; SourceItem.Owner.Show(); } private void toolStripClosing(object sender, ToolStripDropDownClosingEventArgs e) { e.Cancel = keepOpen; } } 

用法::重要事件是ShowContextMenu ,挂钩此事件并设置要显示的ContextMenuStrip 。 就这样。 这是详细信息:

 public partial class Form1 : Form { public Form1(){ InitializeComponent(); //suppose you have a main ContextMenuStrip and a sub ContextMenuStrip //try adding some items for both ContextMenuStrip = new ContextMenuStrip(); ContextMenuStrip.Items.Add("Item 1"); ContextMenuStrip.Items.Add("Item 2"); //sub ContextMenuStrip var subMenu = new ContextMenuStrip(); subMenu.Items.Add("Delete"); subMenu.Items.Add("Rename"); ContextMenuStrip.HandleCreated += (s,e) => { nativeMenu.AssignHandle(ContextMenuStrip.Handle); nativeMenu.ShowContextMenu += (ev) => { ev.ContextMenuToShow = subMenu; }; }; } NativeContextMenuStrip nativeMenu = new NativeContextMenuStrip(); } 

要单击显示子ContextMenuStrip ,可以访问NativeContextMenuStripSourceItem

在此处输入图像描述