我希望当我单击一个菜单项时,显示一个上下文菜单,其中包含“删除”、“重命名”等项目。
右键单击菜单项时如何为自己绑定上下文菜单?
我脑海中闪现的第一个想法是在屏幕坐标系上连接一些MouseDown
事件ToolStripMenuItem
并在鼠标位置显示第二个事件。ContextMenuStrip
但这并不是那么简单。问题是这样做需要为每个项目连接事件,在该事件上以某种方式显示第二个ContextMenuStrip
将关闭当前的 ContextMenuStrip (即使我们添加一些Closing
事件处理程序并设置e.Cancel = true;
)。这里有点棘手。我们可以想到MouseDown
current 的事件,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
,您可以访问SourceItem
的NativeContextMenuStrip
。