如何过滤Winforms应用程序中的ToolStripMenuItem鼠标事件?

ipakzgxi  于 2023-03-31  发布在  其他
关注(0)|答案(1)|浏览(122)

我有一个.Net Winforms应用程序,它的ToolStrip包含几个ToolStripMenuItem。
我希望能够拦截ToolStripMenuItems上的鼠标按下事件。我已经定义了PreFilterMessage。我假设我应该能够捕获该过滤器中的事件。

bool IMessageFilter.PreFilterMessage(ref Message message)
{
    switch (message.Msg)
    {
    }
}

我该怎么做?
是否使用了自定义消息?
捕获消息后,如何使用Message数据来获取被单击的实际ToolStripMenuItem?

k2arahey

k2arahey1#

IMessageFilter实现中,使用m.HWnd属性通过调用Control.FromHandle方法获取单击的ToolStripItem的所有者控件,并将其转换为适当的条带类型。转换为基类ToolStrip或其派生类之一。
m.LParam属性中获取点击点,以搜索条带的Items集合,并找到其边界应包含该点(如果有的话)的点击项。

// +
using System.Linq;

public partial class SomeForm : Form, IMessageFilter
{
    const int WM_LBUTTONDOWN = 0x0201;

    public SomeForm()
    {
        InitializeComponent();
        // ...
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        Application.AddMessageFilter(this);
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        Application.RemoveMessageFilter(this);
        base.OnFormClosing(e);
    }

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_LBUTTONDOWN && FromHandle(m.HWnd) is ToolStrip ts)
        {
            var p = PointToClient(PointToScreen(new Point(m.LParam.ToInt32())));
            var item = ts.Items.Cast<ToolStripItem>()
                .FirstOrDefault(x => x.Bounds.Contains(p));

            if (item != null)
            {
                Console.WriteLine(item.Text);
                // ...
            }
        }

        return false;
    }
}

如果您只需要处理下拉菜单的项,则将所有者控件的类型从基ToolStrip更改为派生ToolStripDropDownMenu

if (m.Msg == WM_LBUTTONDOWN && FromHandle(m.HWnd) is ToolStripDropDownMenu ts)
{
    // The same ...
}

或者检查返回项的类型以跳过ToolStripSeparator等类型。

if (item is ToolStripMenuItem)
{
    Console.WriteLine(item.Text);
    // ...
}

找出不同的方法here

相关问题