使用鼠标滚轮的水平滚动(C#和WinAPI)
本文关键字:WinAPI 滚动 水平 鼠标 | 更新日期: 2023-09-27 18:35:11
我正在创建一个逻辑,以便在鼠标位置下滚动控件,而无需在我的窗体中显示焦点(Outlook 样式)。我能够使用IMessageFilter实现此行为。但是,如果按下"SHIFT"键,我很难应用水平滚动。
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;
public partial class UI : Form
{
MouseWheelMessageFilter mouseFilter = null;
public UI()
{
InitializeComponent();
mouseFilter = new MouseWheelMessageFilter();
Application.AddMessageFilter(mouseFilter);
this.FormClosed += (o, e) => Application.RemoveMessageFilter(mouseFilter);
}
}
public class MouseWheelMessageFilter : IMessageFilter
{
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(Point pt);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
public const int MK_CONTROL = 0x0008;
public const int MK_SHIFT = 0x0004;
public const int WM_MOUSEWHEEL = 0x020A;
public const int WM_MOUSEHWHEEL = 0x020E;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEWHEEL)
{
var shiftKeyDown = (char)((Keys)m.WParam) == MK_SHIFT;
//apply the scroll to the control at mouse location
Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
IntPtr hWnd = WindowFromPoint(pos);
if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null)
{
if (shiftKeyDown)
//TODO: Horizontal scroll - Not working WM_MOUSEHWHEEL (0x020E)
//SendMessage(hWnd, WM_MOUSEHWHEEL, m.WParam, m.LParam);
else
//Vertical Scroll - working
SendMessage(hWnd, WM_MOUSEWHEEL, m.WParam, m.LParam);
return true;
}
}
return false;
}
}
我需要在//TODO 部分做什么才能让水平滚动工作?
这只是一个猜测,我自己无法测试,但我注意到你只过滤:
if (m.Msg == WM_MOUSEWHEEL)
是否需要单独筛选WM_MOUSEHWHEEL:
if (m.Msg == WM_MOUSEHWHEEL)
那么也许您不必测试 shift 键?
编辑:这就是我在想的:
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEHWHEEL)
{
//apply the scroll to the control at mouse location
Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
IntPtr hWnd = WindowFromPoint(pos);
if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null)
{
SendMessage(hWnd, m.Msg, m.WParam, m.LParam);
return true;
}
}
return false;
}
抱歉,如果这不起作用,我现在无法编译它来测试它,这只是一个猜测,如果用户按住 SHIFT(取WM_MOUSEHWHEEL,您将不会WM_MOUSEWHEEL