我希望当我点击一个菜单项时,显示一个上下文菜单,其中包含“删除”,“重命名”等项目。
右键单击菜单项时如何绑定自身的上下文菜单?
答案 0 :(得分:2)
我想到的第一个想法就是在MouseDown
上挂上一些ToolStripMenuItem
事件,并在屏幕坐标中的鼠标位置显示第二个ContextMenuStrip
。但事情并非如此简单。问题是这样做将需要连接事件对于每一的项目,该事件在某种程度上显示了第二ContextMenuStrip
将关闭目前的ContextMenuStrip(即使我们增加一些Closing
事件处理程序并设置e.Cancel = true;
)。这里有点棘手。我们可以想到当前MouseDown
的{{1}}事件,但实际上这个事件几乎没有被触发,因为所有项目都位于ContextMenuStrip
之上。这让我想到了我们可以捕获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
的{{1}}。