I have some menus that contain many menuitems. Mouse wheel doesn\'t scroll them. I have to use the keyboard arrows or click the arrows at top and bottom. Is it possible to u
You can enable it application wide with this class:
public class DropDownMenuScrollWheelHandler : System.Windows.Forms.IMessageFilter
{
private static DropDownMenuScrollWheelHandler Instance;
public static void Enable(bool enabled)
{
if (enabled)
{
if (Instance == null)
{
Instance = new DropDownMenuScrollWheelHandler();
Application.AddMessageFilter(Instance);
}
}
else
{
if (Instance != null)
{
Application.RemoveMessageFilter(Instance);
Instance = null;
}
}
}
private IntPtr activeHwnd;
private ToolStripDropDown activeMenu;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x200 && activeHwnd != m.HWnd) // WM_MOUSEMOVE
{
activeHwnd = m.HWnd;
this.activeMenu = Control.FromHandle(m.HWnd) as ToolStripDropDown;
}
else if (m.Msg == 0x20A && this.activeMenu != null) // WM_MOUSEWHEEL
{
int delta = (short)(ushort)(((uint)(ulong)m.WParam) >> 16);
handleDelta(this.activeMenu, delta);
return true;
}
return false;
}
private static readonly Action ScrollInternal
= (Action)Delegate.CreateDelegate(typeof(Action),
typeof(ToolStrip).GetMethod("ScrollInternal",
System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Instance));
private void handleDelta(ToolStripDropDown ts, int delta)
{
if (ts.Items.Count == 0)
return;
var firstItem = ts.Items[0];
var lastItem = ts.Items[ts.Items.Count - 1];
if (lastItem.Bounds.Bottom < ts.Height && firstItem.Bounds.Top > 0)
return;
delta = delta / -4;
if (delta < 0 && firstItem.Bounds.Top - delta > 9)
{
delta = firstItem.Bounds.Top - 9;
}
else if (delta > 0 && delta > lastItem.Bounds.Bottom - ts.Height + 9)
{
delta = lastItem.Bounds.Bottom - owner.Height + 9;
}
if (delta != 0)
ScrollInternal(ts, delta);
}
}