怎样的ContextMenuStrip添加到ToolStripMenuItem [英] How to add ContextMenuStrip to ToolStripMenuItem

查看:356
本文介绍了怎样的ContextMenuStrip添加到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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆