I have a .Net Winforms application with a ToolStrip that contains several ToolStripMenuItems.
I would like to be able to intercept Mouse LButton down events on the ToolStripMenuItems. I have PreFilterMessage defined. I assume I should be able to capture the event in that filter.
bool IMessageFilter.PreFilterMessage(ref Message message)
{
switch (message.Msg)
{
}
}
How would I do that?
Is there a custom message being used?
Once I capture the message, how can I use the Message data to get the actual ToolStripMenuItem that was clicked?
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.