.NET 单个 ContextMenuItem 中的多个 ToolStripButton

发布于 2024-10-21 00:50:07 字数 416 浏览 1 评论 0原文

我正在尝试创建一个上下文菜单,其中菜单中的某些项目包含多个项目。您可以将其视为尝试组合 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);

关于如何实现这一点有什么想法吗?

I'm trying to create a ContextMenu where some items in the menu contain more than a single item. You could see it as trying to combine a ToolStrip and ContextMenuItem.
I've tried using a ToolStripControlHost, but this creates problems with the focus. It basically requires you to click everything in the ToolStrip twice..

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

Any thoughts on how to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生生漫 2024-10-28 00:50:07

对于不像上下文菜单的自定义弹出窗口来说,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 不同,只有当您单击应用程序拥有的窗口时,该表单才会弹出。功能,而不是错误。

A ContextMenuStrip is too attractive a target for custom popup windows that don't act like a context menu. It is desirable because it automatically pops down when the user clicks outside of the menu. It has limitations though, it just isn't a very good control host. The click problem is classical one, CMS captures the mouse to detect when the user clicks outside of the window.

This really ought to be a form. To give it the same behavior as a CMS requires a bit of work though. You have to detect mouse clicks that are off the window so you can make the window disappear. Capturing the mouse like CMS does doesn't work. One trick is using IMessageFilter, it lets you take a peek at input messages before they are delivered to the window with the focus. Here's a sample form that implements this:

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;
    }
}

Use the designer as normal to design the form. You want to at least give it a different FormBorderStyle. Use the provided Show() method overload the same way you use it for CMS. Do note that the form pops down only when you click on a window that's owned by the application, unlike a CMS. Feature, not a bug.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文