【发布时间】:2014-02-04 10:32:21
【问题描述】:
操作系统是 Retina Macbook PRO 上的 Windows 8。
我需要在我的应用程序中同时支持使用触控板的垂直滚动和水平滚动。
我想根据上下(垂直滚动)和左右(水平滚动)的两个手指滑动来移动 WPF 滚动查看器的位置。
据我所知,触控板上的垂直滚动被转换为框架中的鼠标滚轮事件。但是,我发现无法识别鼠标滚轮事件是否为水平滚动。
我应该在 WPF 中处理哪些事件才能实现这一点?
【问题讨论】:
操作系统是 Retina Macbook PRO 上的 Windows 8。
我需要在我的应用程序中同时支持使用触控板的垂直滚动和水平滚动。
我想根据上下(垂直滚动)和左右(水平滚动)的两个手指滑动来移动 WPF 滚动查看器的位置。
据我所知,触控板上的垂直滚动被转换为框架中的鼠标滚轮事件。但是,我发现无法识别鼠标滚轮事件是否为水平滚动。
我应该在 WPF 中处理哪些事件才能实现这一点?
【问题讨论】:
我专门为您写了一篇文章,让您了解如何在 WPF 应用程序中处理触摸板的水平滚动。那是Support Horizontal Scrolling of TouchPad in WPF Application - walterlv
我们需要从 WPF 窗口中获取 WM_MOUSEHWHEEL 消息。是的!那个鼠标滚轮消息。我们之前从它获取垂直数据,但现在我们从它获取水平数据。
首先,我们应该挂钩窗口消息。
protected override void OnSourceInitialized(EventArgs e)
{
var source = PresentationSource.FromVisual(_board);
((HwndSource) source)?.AddHook(Hook);
}
private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle window message here.
return IntPtr.Zero;
}
接下来,处理WM_MOUSEHWHEEL:
const int WM_MOUSEHWHEEL = 0x020E;
private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_MOUSEHWHEEL:
int tilt = (short) HIWORD(wParam);
OnMouseTilt(tilt);
return (IntPtr) 1;
}
return IntPtr.Zero;
}
/// <summary>
/// Gets high bits values of the pointer.
/// </summary>
private static int HIWORD(IntPtr ptr)
{
var val32 = ptr.ToInt32();
return ((val32 >> 16) & 0xFFFF);
}
/// <summary>
/// Gets low bits values of the pointer.
/// </summary>
private static int LOWORD(IntPtr ptr)
{
var val32 = ptr.ToInt32();
return (val32 & 0xFFFF);
}
private void OnMouseTilt(int tilt)
{
// Write your horizontal handling codes here.
}
您可以在OnMouseTilt方法中编写水平滚动代码。
更好的是,您可以将上述所有代码打包到一个更通用的类中,并引发 MouseTilt 事件,就像引发 MouseWheel 事件一样。
【讨论】:
完成答案walterlv
private void OnMouseTilt(int tilt)
{
UIElement element = Mouse.DirectlyOver as UIElement;
if (element == null) return;
ScrollViewer scrollViewer = element is ScrollViewer viewer ? viewer : FindParent<ScrollViewer>(element);
if (scrollViewer == null)
return;
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + tilt);
}
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
T parent = parentObject as T;
if (parent != null)
return parent;
else
return FindParent<T>(parentObject);
}
【讨论】:
改进walterlv的答案并修复64位系统向左滚动时的算术溢出:
/// <summary>
/// Gets high bits values of the pointer.
/// </summary>
private static int HIWORD(IntPtr ptr)
{
unchecked
{
if (Environment.Is64BitOperatingSystem)
{
var val64 = ptr.ToInt64();
return (short) ((val64 >> 16) & 0xFFFF);
}
var val32 = ptr.ToInt32();
return (short) ((val32 >> 16) & 0xFFFF);
}
}
/// <summary>
/// Gets low bits values of the pointer.
/// </summary>
private static int LOWORD(IntPtr ptr)
{
unchecked
{
if (Environment.Is64BitOperatingSystem)
{
var val64 = ptr.ToInt64();
return (short)(val64 & 0xFFFF);
}
var val32 = ptr.ToInt32();
return (short)(val32 & 0xFFFF);
}
}
【讨论】: