单个ContextMenuItem中的.NET Multiple ToolStripButtons

时间:2011-03-06 00:23:53

标签: .net contextmenu toolstrip toolstripbutton toolstripcontrolhost

我正在尝试创建一个ContextMenu,其中菜单中的某些项目包含多个项目。您可以将其视为尝试组合ToolStrip和ContextMenuItem。 我尝试过使用ToolStripControlHost,但这会产生焦点问题。它基本上要求你单击ToolStrip中的所有内容两次..

ContextMenuStrip m = new ContextMenuStrip();
ToolStrip tStrip = new ToolStrip(new ToolStripDropDownButton(), new ToolStripButton());
ToolStripControlHost tsHost = new ToolStripControlHost(tStrip);
m.Items.Add(tsHost);

有关如何实现这一目标的任何想法?

1 个答案:

答案 0 :(得分:1)

对于不像上下文菜单那样的自定义弹出窗口,ContextMenuStrip太有吸引力了。这是可取的,因为当用户点击菜单外部时它会自动弹出。它有局限性,它不是一个非常好的控制主机。点击问题是经典问题,CMS捕获鼠标以检测用户何时在窗口外点击。

这真的应该是一种形式。为了给它提供与CMS相同的行为,但需要一些工作。您必须检测窗口外的鼠标单击,以便您可以使窗口消失。像CMS一样捕获鼠标不起作用。一个技巧是使用IMessageFilter,它允许您在输入消息传递到具有焦点的窗口之前查看输入消息。这是一个实现此目的的示例表单:

public partial class MyContextMenu : Form, IMessageFilter {
    public MyContextMenu() {
        InitializeComponent();
        Application.AddMessageFilter(this);
    }
    protected override void OnFormClosed(FormClosedEventArgs e) {
        Application.RemoveMessageFilter(this);
        base.OnFormClosed(e);
    }
    public void Show(Control ctl, Point pos) {
        this.StartPosition = FormStartPosition.Manual;
        this.Location = ctl.PointToScreen(pos);
        while (!(ctl is Form)) ctl = ctl.Parent;
        this.Show((Form)ctl);
    }
    public bool PreFilterMessage(ref Message m) {
        // Detect mouse clicks outside of the form
        if (m.Msg == 0x201 || m.Msg == 0x204 || m.Msg == 0x207 || 
            m.Msg == 0xA1  || m.Msg == 0xA4  || m.Msg == 0xA7) {
            Point pos = new Point(m.LParam.ToInt32());
            Control ctl = Control.FromHandle(m.HWnd);
            if (ctl != null) pos = ctl.PointToScreen(pos);
            pos = this.PointToClient(pos);
            if (pos.X < 0 || pos.Y < 0 || pos.X >= this.Width || pos.Y >= this.Height) {
                this.Close();
            }
        }
        return false;
    }
}

正常使用设计器来设计表单。你想至少给它一个不同的FormBorderStyle。使用提供的Show()方法重载与将其用于CMS的方式相同。请注意,只有当您单击应用程序所拥有的窗口时,表单才会弹出,与CMS不同。功能,而不是错误。