簡體   English   中英

鼠標滾輪滾動Toolstrip菜單項

[英]Mouse wheel scrolling Toolstrip menu items

我有一些包含許多菜單項的菜單。 鼠標滾輪不會滾動它們。 我必須使用鍵盤箭頭或單擊頂部和底部的箭頭。 是否可以使用鼠標滾輪滾動工具條菜單項? 謝謝

工作解決方案:

  1. 在窗體的Load事件中注冊表單的MouseWheel事件和根MenuStripItem (此處為rootItem)的DropDownClosed事件

      this.MouseWheel += Form3_MouseWheel; rootItem.DropDownOpened += rootItem_DropDownOpened; rootItem.DropDownClosed += rootItem_DropDownClosed; 
  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); } } 
  3. 添加DropDownOpenedDropDownClosedMouseWheel事件的代碼:

     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(); } } } 

您可以使用此類在應用程序范圍內啟用它:

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);
    }
}

這非常簡單地使用上下文菜單的子菜單ToolStripMenuItem ):

假設使用form1 (或UserControl )和contextMenuStrip1

private void form1_Load( object sender , EventArgs e )
{
    //this.MouseWheel -= When_MouseWheel;
    this.MouseWheel += When_MouseWheel;
}
void When_MouseWheel( object sender , MouseEventArgs e )
{
    if ( this.contextMenuStrip1.IsDropDown ) {
         //this.Focus();
         if ( e.Delta > 0 ) SendKeys.SendWait( "{UP}" );
         else SendKeys.SendWait( "{DOWN}" );         
    }
}

我修改了Mohsen Afshin的答案,單擊向上/向下箭頭而不是向上/向下按鍵發送。 我的應用程序有一個名為ContextMenuStrip menu 這是代碼。

在初始化中:

    menu.VisibleChanged += (s, e) =>
    {
        if (menu.Visible)
        {
            MouseWheel += ScrollMenu;
            menu.MouseWheel += ScrollMenu;
        }
        else
        {
            MouseWheel -= ScrollMenu;
            menu.MouseWheel -= ScrollMenu;
        }
    };

ScrollMenu函數:

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);

private void ScrollMenu(object sender, MouseEventArgs e)
{
    Point origin = Cursor.Position;
    int clicks;

    if (e.Delta < 0)
    {
        Cursor.Position = menu.PointToScreen(new Point(menu.DisplayRectangle.Left + 5, menu.DisplayRectangle.Bottom + 5));
        clicks = e.Delta / -40;
    }
    else
    {
        Cursor.Position = menu.PointToScreen(new Point(menu.DisplayRectangle.Left + 5, menu.DisplayRectangle.Top - 5));
        clicks = e.Delta / 40;
    }

    for (int i = 0; i < clicks; i++)
        mouse_event(0x0006, 0, 0, 0, 0);//Left mouse button up and down on cursor position
    Cursor.Position = origin;
}

我在獲取mouse_event函數以單擊特定位置時遇到問題,因此我移動光標,單擊,然后將光標移回。 它似乎並不是最干凈的,但它確實有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM