UserControl: How to add MouseWheel Listener?

后端 未结 4 1531
既然无缘
既然无缘 2021-01-21 01:34

I\'m creating an UserControl that should react if the mouse is over the control and MouseWheel gets rotated.

Currently i\'m doing this as shown here:

            


        
4条回答
  •  清酒与你
    2021-01-21 02:20

    having the same problem, I finally implemented a mix of both solution by @Paul_Westcott and @nr1. This is a local solution like solution of @Paul_Westcott (only applies to the winforms control that subscribes to). It is multiple monitor safe and MDI safe (overlapping by other windows within the application)

    public static class MouseWheelHandlerForWinformsControl
    {
        private class MouseWheelMessageFilter : IMessageFilter
        {
            [DllImport("user32.dll")]
            private static extern IntPtr WindowFromPoint(Point pt);
    
            private readonly Control mCtrl;
            private readonly Action mOnMouseWheel;
    
            public MouseWheelMessageFilter(Control ctrl, Action onMouseWheel)
            {
                mCtrl = ctrl;
                mOnMouseWheel = onMouseWheel;
            }
    
            public bool PreFilterMessage(ref Message m)
            {
                // handle only mouse wheel messages
                if (m.Msg != 0x20a)
                    return false;
    
                Point mouseAbsolutePosition = new Point(m.LParam.ToInt32());
                Point mouseRelativePosition = mCtrl.PointToClient(mouseAbsolutePosition);
    
                IntPtr hControlUnderMouse = WindowFromPoint(mouseAbsolutePosition);
                Control controlUnderMouse = Control.FromHandle(hControlUnderMouse);
    
                if (controlUnderMouse != mCtrl)
                    return false;
    
                MouseButtons buttons = GetMouseButtons(m.WParam.ToInt32());
                int delta = m.WParam.ToInt32() >> 16;
    
                var e = new MouseEventArgs(buttons, 0, mouseRelativePosition.X, mouseRelativePosition.Y, delta);
    
                mOnMouseWheel(e);
    
                return true;
            }
    
            private static MouseButtons GetMouseButtons(int wParam)
            {
                MouseButtons buttons = MouseButtons.None;
    
                if(HasFlag(wParam, 0x0001)) buttons |= MouseButtons.Left;
                if(HasFlag(wParam, 0x0010)) buttons |= MouseButtons.Middle;
                if(HasFlag(wParam, 0x0002)) buttons |= MouseButtons.Right;
                if(HasFlag(wParam, 0x0020)) buttons |= MouseButtons.XButton1;
                if(HasFlag(wParam, 0x0040)) buttons |= MouseButtons.XButton2;
    
                return buttons;
            }
    
            private static bool HasFlag(int input, int flag)
            {
                return (input & flag) == flag;
            }
        }
    
        public static void MemorySafeAdd(Control ctrl, Action onMouseWheel)
        {
            if (ctrl == null || onMouseWheel == null)
                throw new ArgumentNullException();
    
            var filter = new MouseWheelMessageFilter(ctrl, onMouseWheel);
            Application.AddMessageFilter(filter);
            ctrl.Disposed += (s, e) => Application.RemoveMessageFilter(filter);
        }
    }
    

    Once you have added this helper class into your solution, you subscribe a control myControl to the mouse-wheel, in one line, as following:

    public void Init() {
        MouseWheelHandlerForWinformsControl.MemorySafeAdd(myControl, OnMouseWheelEvent);
    }
    
    void OnMouseWheelEvent(MouseEventArgs args) {
        // do what you need here
    }
    

提交回复
热议问题