Mouse wheel event to work with hovered control

前端 未结 4 1024
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-04 11:37

In my C# 3.5 Windows Forms application, I have a few SplitContainers. There is a list control inside each (dock fill). When the focus is on one of these controls and I move mous

4条回答
  •  谎友^
    谎友^ (楼主)
    2021-02-04 12:05

    It looks like you can use the IMessageFilter and PInvoke to handle this. An example in VB can be found at Redirect Mouse Wheel Events to Unfocused Windows Forms Controls. You should be able to easily convert this to C#.

    Points of Interest

    This class uses the following techniques for the given task:

    • Listen to the control's MouseEnter and MouseLeave events to determine when the mouse pointer is over the control.
    • Implement IMessageFilter to catch WM_MOUSEWHEEL messages in the application.
    • PInvoke the Windows API call SendMessage redirecting the WM_MOUSEWHEEL message to the control's handle.
    • The IMessageFilter object is implemented as a singleton of the MouseWheelRedirector class and accessed by the shared members Attach, Detach, and Active.

    Using a VB.NET to C# converter, this is what you end up with:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    public class MouseWheelRedirector : IMessageFilter
    {
        private static MouseWheelRedirector instance = null;
        private static bool _active = false;
        public static bool Active
        {
           get { return _active; }
           set
           { 
              if (_active != value) 
              {
                 _active = value;
                 if (_active)
                 {
                    if (instance == null)
                    {
                        instance = new MouseWheelRedirector();
                    }
                    Application.AddMessageFilter(instance);
                 }
                 else
                 {
                    if (instance != null)
                    {
                       Application.RemoveMessageFilter(instance);
                    }
                 }
              }
           }
        }
    
        public static void Attach(Control control)
        {
           if (!_active)
              Active = true;
           control.MouseEnter += instance.ControlMouseEnter;
           control.MouseLeave += instance.ControlMouseLeaveOrDisposed;
           control.Disposed += instance.ControlMouseLeaveOrDisposed;
        }
    
        public static void Detach(Control control)
        {
           if (instance == null)
              return;
           control.MouseEnter -= instance.ControlMouseEnter;
           control.MouseLeave -= instance.ControlMouseLeaveOrDisposed;
           control.Disposed -= instance.ControlMouseLeaveOrDisposed;
           if (object.ReferenceEquals(instance.currentControl, control))
              instance.currentControl = null;
        }
    
        private MouseWheelRedirector()
        {
        }
    
    
        private Control currentControl;
        private void ControlMouseEnter(object sender, System.EventArgs e)
        {
           var control = (Control)sender;
           if (!control.Focused)
           {
              currentControl = control;
           }
           else
           {
              currentControl = null;
           }
        }
    
        private void ControlMouseLeaveOrDisposed(object sender, System.EventArgs e)
        {
           if (object.ReferenceEquals(currentControl, sender))
           {
              currentControl = null;
           }
        }
    
        private const int WM_MOUSEWHEEL = 0x20a;
        public bool PreFilterMessage(ref System.Windows.Forms.Message m)
        {
           if (currentControl != null && m.Msg == WM_MOUSEWHEEL)
           {
              SendMessage(currentControl.Handle, m.Msg, m.WParam, m.LParam);
              return true;
           }
           else
           {
              return false;
           }
        }
    
        [DllImport("user32.dll", SetLastError = false)]
        private static extern IntPtr SendMessage(
           IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
     }
    

提交回复
热议问题