鼠标滚轮滚动工具条菜单项

Jer*_*rry 3 c# scroll toolstripitem winforms toolstripmenu

我有一些包含许多菜单项的菜单。鼠标滚轮不会滚动它们。我必须使用键盘箭头或单击顶部和底部的箭头。是否可以使用鼠标滚轮滚动工具条菜单项?谢谢

Moh*_*hin 5

一个可行的解决方案:

  1. 注册MouseWheel您的表单事件和DropDownClosed表单事件MenuStripItem中的根(此处为 rootItem)Load事件

        this.MouseWheel += Form3_MouseWheel;
        rootItem.DropDownOpened += rootItem_DropDownOpened;
        rootItem.DropDownClosed += rootItem_DropDownClosed;
    
    Run Code Online (Sandbox Code Playgroud)
  2. Keyboard添加模拟按键的类代码

    public static class Keyboard
    {
        [DllImport("user32.dll")]
        static extern uint keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
    
    
        const byte VK_UP = 0x26; // Arrow Up key
        const byte VK_DOWN = 0x28; // Arrow Down key
    
        const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag, the key is going to be pressed
        const int KEYEVENTF_KEYUP = 0x0002; //Key up flag, the key is going to be released
    
        public static void KeyDown()
        {
            keybd_event(VK_DOWN, 0, KEYEVENTF_EXTENDEDKEY, 0);
            keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
        }
    
        public static void KeyUp()
        {
            keybd_event(VK_UP, 0, KEYEVENTF_EXTENDEDKEY, 0);
            keybd_event(VK_UP, 0, KEYEVENTF_KEYUP, 0);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. DropDownOpened添加, DropDownClosed,事件的代码MouseWheel

    bool IsMenuStripOpen  = false;
    
    void rootItem_DropDownOpened(object sender, EventArgs e)
    {
        IsMenuStripOpen = true;
    }
    
    
    void rootItem_DropDownClosed(object sender, EventArgs e)
    {
        IsMenuStripOpen = false;
    }
    
    void Form3_MouseWheel(object sender, MouseEventArgs e)
    {
        if (IsMenuStripOpen)
        {
            if (e.Delta > 0)
            {
                Keyboard.KeyUp();
            }
            else
            {
                Keyboard.KeyDown();
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


Bry*_*ner 5

您可以使用此类在应用程序范围内启用它:

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<ToolStrip, int> ScrollInternal
        = (Action<ToolStrip, int>)Delegate.CreateDelegate(typeof(Action<ToolStrip, int>),
            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);
    }
}
Run Code Online (Sandbox Code Playgroud)