怎样的ContextMenuStrip添加到ToolStripMenuItem [英] How to add ContextMenuStrip to ToolStripMenuItem
问题描述
我想,当我点击菜单项,显示与项目,如删除,重命名,等等。
I want that when I click on a menu item, display a context menu with items such as "delete", "rename", etc.
如何把自己绑定上下文菜单,当你在菜单项上单击鼠标右键?
How to bind itself a context menu when you right-click on the menu item?
推荐答案
在我脑海的第一个念头跳了挂钩上的的MouseDown
事件> ToolStripMenuItem 并显示在第二个的ContextMenuStrip
在屏幕坐标中的鼠标位置。但它不是这么简单的。问题是这样做将需要连接事件对于每个的项目,该事件在某种程度上显示了第二个的ContextMenuStrip
将关闭目前的ContextMenuStrip(即使我们增加一些结束
事件处理程序,并设置 e.Cancel = TRUE;
)。这是一个有点棘手这里。我们可以认为目前的的MouseDown
事件的ContextMenuStrip
其实这个事件很难解雇了,因为所有的项目说谎在的ContextMenuStrip
的顶部。这让我觉得更深层次的阶段,我们可以赶上 WM_RBUTTONDOWN
并运行code那里。我们可以自定义的ContextMenuStrip
来捕捉的WndProc
该消息,或者我们可以使用自定义的的NativeWindow
。我想用一个的NativeWindow
在这里。现在是时候为code(工作完美):
The first idea jumping in my mind was hook up some MouseDown
event on the ToolStripMenuItem
and show the second ContextMenuStrip
at the mouse position in screen coordinates. But it's not such simple. The problem is doing so will require hooking up the event for every items, on that event somehow showing the second ContextMenuStrip
will close the current ContextMenuStrip (even we add some Closing
event handler and set e.Cancel = true;
). It's a little tricky here. We could think of the MouseDown
event of the current ContextMenuStrip
but in fact this event is hardly fired because all the items lie on top of the ContextMenuStrip
. That made me think of the deeper stage where we can catch the WM_RBUTTONDOWN
and run code there. We can customize the ContextMenuStrip
to catch that message in WndProc
or we can use a custom NativeWindow
. I would like to use a NativeWindow
here. It's time for the code (working perfectly):
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
要显示。就这样。下面是详细信息:
Usage:: The important event is ShowContextMenu
, hook up this event and set the ContextMenuStrip
you want to show. That's all. Here is the detail:
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
,您可以访问的 SourceItem
的 NativeContextMenuStrip
。
To get the item clicking on which shows the sub ContextMenuStrip
, you can access the SourceItem
of the NativeContextMenuStrip
.
这篇关于怎样的ContextMenuStrip添加到ToolStripMenuItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!