如何以资源管理器的方式处理WM_MOUSEHWHEEL?

时间:2012-06-28 10:46:23

标签: c# scroll mousewheel

我的Logitech M705鼠标带有滚轮,允许水平滚动。我已经在我的C#程序中成功实现了这个按钮事件的处理程序(按照here所述实现),但到目前为止我只能滚动一次。在资源管理器中,当我向右按下滚轮时,它会向右滚动 直到我松开滚轮。在我的程序中,它只滚动一步。直到我释放并再次按下滚轮才能看到WM_MOUSEHWHEEL消息!

问:如何为WM_MOUSEHWHEEL消息实施连续水平滚动?

2 个答案:

答案 0 :(得分:1)

将此添加到所有控件(表单,子等):

protected override void WndProc(ref System.Windows.Forms.Message m)
{
    base.WndProc(ref m);

    const int WM_MOUSEHWHEEL = 0x020E;
    if (m.Msg == WM_MOUSEHWHEEL)
    {
        m.Result = new IntPtr(HIWORD(m.WParam) / WHEEL_DELTA);
    }
}

关键是为可能处理消息的所有控件返回非零值!

答案 1 :(得分:0)

使用IMessageFilter

    public partial class MyForm: Form, IMessageFilter
...
 public ImageForm(Image initialImage)
        {
            InitializeComponent();            
            Application.AddMessageFilter(this);
        }

/// <summary>
        /// Filters out a message before it is dispatched.
        /// </summary>
        /// <returns>
        /// true to filter the message and stop it from being dispatched; false to allow the message to continue to the next filter or control.
        /// </returns>
        /// <param name="m">The message to be dispatched. You cannot modify this message. </param><filterpriority>1</filterpriority>
        public bool PreFilterMessage( ref Message m )
        {
            if (m.Msg.IsWindowMessage(WindowsMessages.MOUSEWHEEL))  //if (m.Msg == 0x20a)
            {   // WM_MOUSEWHEEL, find the control at screen position m.LParam      
                var pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
                var hWnd = WindowFromPoint(pos);
                if (hWnd != IntPtr.Zero && hWnd != m.HWnd && FromHandle(hWnd) != null)
                {
                    SendMessage(hWnd, m.Msg, m.WParam, m.LParam);
                    return true;
                }
            }

            return false;
        }


        [DllImport("user32.dll")]
        private static extern IntPtr WindowFromPoint(Point pt);

        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

也在表格中关闭添加:

Application.RemoveMessageFilter(this);

这将获取所有窗口消息(尽管此处仅捕获鼠标轮) - 通过使用鼠标定位来查找控件,然后您可以强制窗口将消息发送到该控件,即使它没有焦点。

注意:我使用的是WindowsMessages.MOUSEWHEEL,它来自我列举的消息类,只需替换

if (m.Msg.IsWindowMessage(WindowsMessages.MOUSEWHEEL))

结尾处的注释位

  

if (m.Msg == 0x20a)