In the IMessageFilter
implementation, use the m.HWnd
property to get the
owner control of the clicked ToolStripItem
by calling the Control.FromHandle
method and cast it to a proper strip type. To the base ToolStrip
class or one of its derives.
Get the clicked point from the m.LParam
property to search the strip's Items
collection and find the clicked item whose bounds should contain that point if any.
// +
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;
}
}
If you just need to handle the items of the dropdown menus, then change the type of the owner control from the base ToolStrip
to the derived ToolStripDropDownMenu
.
if (m.Msg == WM_LBUTTONDOWN && FromHandle(m.HWnd) is ToolStripDropDownMenu ts)
{
// The same ...
}
Or check the type of the returned item to also skip types like ToolStripSeparator
.
if (item is ToolStripMenuItem)
{
Console.WriteLine(item.Text);
// ...
}
Find out a different approach here.