【问题标题】:Detect scroll is completed with PointerWheelChanged使用 PointerWheelChanged 检测滚动完成
【发布时间】:2012-12-11 08:33:22
【问题描述】:

我在 WinRT 中使用 PointerWheelChanged 事件检测到鼠标滚轮滚动。我使用PointerPoint.Properties.MouseWheelDelta 来检测滚动的数量和方向:

PointerPoint mousePosition = e.GetCurrentPoint(_control);
var delta = mousePosition.Properties.MouseWheelDelta;

现在有一些设备可以模拟鼠标滚动(触摸板或触摸鼠标等)。 他们倾向于每个“滚动”发布数十或数百(原文如此!)PointerWheelChanged 事件。旧版鼠标滚轮每次点击鼠标滚轮都会发出一个事件,增量为 +-120 个单位。

一旦用户滚动到某个位置,我需要进行一些繁重的处理。

有没有办法理解“新”滚动已完成?

仅供参考,这是使用 Microsoft TouchMouse 单指轻弹的鼠标滚轮增量(对不起数量,我只是想说明问题)。

15 15 164 164 304 304 658 658 773 773 887 887 1000 1000 1111 1111 1221 1221 1330 1330 108 108 107 107 106 106 105 105 104 104 103 103 102 102 203 203 100 100 99 99 98 98 97 97 96 96 95 95 94 94 93 93 92 92 91 91 90 90 89 89 88 88 88 88 87 87 86 86 85 85 84 84 83 83 82 82 82 82 81 81 80 80 79 79 78 78 78 78 77 77 76 76 75 75 75 75 74 74 73 73 72 72 72 72 71 71 70 70 70 70 69 69 68 68 67 67 67 67 66 66 65 65 65 65 64 64 63 63 63 63 62 62 62 62 61 61 60 60 60 60 59 59 59 59 58 58 57 57 57 57 56 56 56 56 55 55 55 55 54 54 54 54 53 53 52 52 52 52 51 51 51 51 50 50 50 50 49 49 49 49 48 48 48 48 47 47 47 47 46 46 46 46 46 46 45 45 45 45 44 44 44 44 43 43 43 43 42 42 42 42 42 42 41 41 41 41 40 40 40 40 40 40 39 39 39 39 38 38 38 38 38 38 37 37 37 37 37 37 36 36 36 36 35 35 35 35 35 35 34 34 34 34 34 34 33 33 33 33 33 33 32 32 32 32 32 32 31 31 31 31 31 31 30 30 30 30 30 30 30 30 29 29 29 29 29 29 28 28 28 28 28 28 28 28 27 27 27 27 27 27 26 26 26 26 26 26 26 26 25 25 25 25 25 25 25 25 24 24 24 24 24 24 24 24 23 23 23 23 23 23 23 23 23 23 22 22 22 22 22 22 22 22 21 21 21 21 21 21 21 21 21 21 20 20 20 20 20 20 20 20 20 20 19 19 19 19 19 19 19 19 19 19 18 18 18 18 18 18 18 18 18 18 18 18 17 17 17 17 17 17 17 17 17 17 17 17 16 16 16 16 16 16 16 16 16 16 16 16 15 15 15 15 15 15 15 15 15 15 15 15 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 13 13 13 13 13 13 13 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 15 15 22 22 7 7 7 7 14 14 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 8 8 12 12 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 9 9 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

编辑: 现在我做了这个 hack,但它远非完美

// interval between mouse deltas
private readonly TimeSpan _wheelDeltaThrottleInterval = TimeSpan.FromMilliseconds(8);

// interval to wait until scroll is complete
private readonly TimeSpan _wheelDeltaCompleteInterval = TimeSpan.FromMilliseconds(600);

// create smart wheel handler
IObservable<PointerPoint> pointerWheelObservable = 
    System.Reactive.Linq.Observable
        .FromEventPattern<PointerEventHandler, PointerRoutedEventArgs>(
            handler => _control.PointerWheelChanged += handler,
            handler => _control.PointerWheelChanged -= handler)
        .Select(eventPattern =>
            {
                PointerRoutedEventArgs e = eventPattern.EventArgs;
                PointerPoint mousePosition = e.GetCurrentPoint(_control);
                return mousePosition;
            })
        .Where(mousePosition => Math.Abs(mousePosition.Properties.MouseWheelDelta) > MouseWheelDeltaThreshold);

// subscribe to wheel changes
pointerWheelObservable
    .Throttle(_wheelDeltaThrottleInterval)
    .ObserveOnDispatcher()
    .Subscribe(
        OnPointerWheelChanged,
        Logger.TrackException);

pointerWheelObservable
    .Throttle(_wheelDeltaCompleteInterval)
    .Subscribe(
        OnPointerWheelCompleted,
        Logger.TrackException);

EDIT2 GestureRecognizer 类没有帮助

请参阅这篇关于 Windws 8 操作处理的精彩博文。 http://blogs.msdn.com/b/windowsappdev/archive/2012/07/02/modernizing-input-in-windows-8.aspx

不幸的是,在我的实验之后,我看到GestureRecognizer 无法检测到鼠标滚轮事件洪水 已经结束。它在每次调用 .ProcessMouseWheelEvent() 后触发 ManipulationCompleted 事件

【问题讨论】:

  • 你用这个做什么?你说你想在用户滚动到某个位置时进行一些处理,在列表中,还是?如果是这样的话,我认为检测列表上的滚动位置而不是鼠标/垫会更容易......
  • 用户正在放大或缩小我们自己的地图实现

标签: windows-8 windows-runtime mouse mousewheel


【解决方案1】:

您可以在 WheelChangedEvent 上使用 Reactive Extension 库和 throttle,这样您将始终收到指定节流时间段的最后通知

【讨论】:

  • 一个已经做了 Throttle 的事情,但它并不完美。总的来说,这是一个 hack
  • 但是我们还可以使用什么其他技术呢?翻转轮子是计算机生成的事件,源是动态的,由于您的操作成本很高,因此您希望通过节流来尽可能地延迟。
  • 限制不好,因为当滚动完成时,用户必须等待一秒钟才能开始我的操作。如果有办法确定鼠标已完成滚动,我会很高兴
  • 您不必节流到一秒钟 - 您所描述的可能等待 0.05 秒可能就足够了,没有人会注意到延迟。
  • 不幸的是,滚动事件最终会增加间隔。在确定滚动完成之前,我无法进行操作。
【解决方案2】:

使用 GestureRecognizer 可以更好地检测低级别的操作,包括鼠标滚轮。 所有输入(鼠标、触摸、笔等)都包含在此处,并且比传统的操作事件得到更好的支持。 (它们不支持单点触控旋转、鼠标滚轮等)

http://code.msdn.microsoft.com/windowsapps/Input-Windows-8-gestures-62c6689b#content

这比从头开始实施一切都更加高效、灵活和安全。

【讨论】:

  • 非常感谢。您的消息使我阅读了 Microsoft 的这篇有用的博客文章:blogs.msdn.com/b/windowsappdev/archive/2012/07/02/…
  • 不幸的是,很酷的 GestureRecognizer 并没有解决我的问题,即来自这些触摸面板的大量滚动事件。看来我现在必须使用 Throttle 代码
猜你喜欢
  • 1970-01-01
  • 2021-03-11
  • 2010-11-02
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 2015-08-15
  • 1970-01-01
相关资源
最近更新 更多