在多点触摸屏上捕捉双击触摸

本文关键字:双击 触摸 多点 触摸屏 | 更新日期: 2023-09-27 18:21:17

我发布了另一个问题,即如何通过监控TouchDown事件上触摸之间的时间跨度来"手动"捕获双击,但这很有问题。有人知道微软在多点触摸屏上捕捉双击的标准方式/事件吗?

非常感谢

Dan

在多点触摸屏上捕捉双击触摸

我检查了敲击位置和秒表的组合,它非常完美!

private readonly Stopwatch _doubleTapStopwatch = new Stopwatch();
private Point _lastTapLocation;
public event EventHandler DoubleTouchDown;
protected virtual void OnDoubleTouchDown()
{
    if (DoubleTouchDown != null)
        DoubleTouchDown(this, EventArgs.Empty);
}
private bool IsDoubleTap(TouchEventArgs e)
{
    Point currentTapPosition = e.GetTouchPoint(this).Position;
    bool tapsAreCloseInDistance = currentTapPosition.GetDistanceTo(_lastTapLocation) < 40;
    _lastTapLocation = currentTapPosition;
    TimeSpan elapsed = _doubleTapStopwatch.Elapsed;
    _doubleTapStopwatch.Restart();
    bool tapsAreCloseInTime = (elapsed != TimeSpan.Zero && elapsed < TimeSpan.FromSeconds(0.7));
    return tapsAreCloseInDistance && tapsAreCloseInTime;
}
private void OnPreviewTouchDown(object sender, TouchEventArgs e)
{
    if (IsDoubleTap(e))
        OnDoubleTouchDown();
}

它在PreviewTouchDown中检查它是否为双击。

Jowens的回答对我帮助很大(如果我的声誉允许的话,我会投赞成票;)但我不得不调整它,所以它只适用于双击。原始代码确实认为2以上的任何抽头都是双击。将_lastTapLocation更改为可为null并在双击时将其重置有帮助。

private Point? _lastTapLocation;
private bool IsDoubleTap(TouchEventArgs e)
    {
        Point currentTapPosition = e.GetTouchPoint(this).Position;
        bool tapsAreCloseInDistance = false;
        if (_lastTapLocation != null)
        {
            tapsAreCloseInDistance = GetDistanceBetweenPoints(currentTapPosition, (Point)_lastTapLocation) < 70;
        }
        _lastTapLocation = currentTapPosition;
        TimeSpan elapsed = _doubleTapStopwatch.Elapsed;
        _doubleTapStopwatch.Restart();
        bool tapsAreCloseInTime = (elapsed != TimeSpan.Zero && elapsed < TimeSpan.FromSeconds(0.7));
        if (tapsAreCloseInTime && tapsAreCloseInDistance)
        {
            _lastTapLocation = null;
        }
        return tapsAreCloseInDistance && tapsAreCloseInTime;
    }

我认为使用StylusSystemGesture事件更合适。这是我的密码。

    public static class ext
{
private static Point? _lastTapLocation;
        private static readonly Stopwatch _DoubleTapStopwatch = new Stopwatch();
        public static bool IsDoubleTap(this StylusSystemGestureEventArgs e, IInputElement iInputElement)
        {
            Point currentTapPosition = e.GetPosition(iInputElement);
            bool tapsAreCloseInDistance = false;
            if (_lastTapLocation != null)
            {
                tapsAreCloseInDistance = GetDistanceBetweenPoints(currentTapPosition, (Point)_lastTapLocation) < 70;
            }
            _lastTapLocation = currentTapPosition;
            TimeSpan elapsed = _DoubleTapStopwatch.Elapsed;
            _DoubleTapStopwatch.Restart();
            bool tapsAreCloseInTime = (elapsed != TimeSpan.Zero && elapsed < TimeSpan.FromSeconds(0.7));
            if (tapsAreCloseInTime && tapsAreCloseInDistance)
            {
                _lastTapLocation = null;
            }
            return tapsAreCloseInDistance && tapsAreCloseInTime;
        }
}

用法:

 private void UIElement_OnStylusSystemGesture(object sender, StylusSystemGestureEventArgs e)
    {
        if (e.SystemGesture == SystemGesture.Tap)
        {
            if (e.IsDoubleTap(sender as IInputElement))
            {
               // Do your stuff here
            }
        }
    }

添加到Andreas的答案中,您还可以删除与Stopwatch相关的代码。

StylusSystemGestureEventArgs还附带了一个Timestamp属性,我相信它以毫秒为单位。

因此,不要使用秒表根据TimeSpan进行计算,而是添加一个int _lastTimestamp字段并减去时间戳。

public static class ext
{
    private static Point? _lastTapLocation;
    // Stopwatch changed to int
    private int _lastTimestamp = 0;
    public static bool IsDoubleTap(this StylusSystemGestureEventArgs e, IInputElement iInputElement)
    {
        Point currentTapPosition = e.GetPosition(iInputElement);
        bool tapsAreCloseInDistance = false;
        if (_lastTapLocation != null)
        {
            tapsAreCloseInDistance = GetDistanceBetweenPoints(currentTapPosition, (Point)_lastTapLocation) < 70;
        }
        _lastTapLocation = currentTapPosition;
        // This replaces the previous TimeSpan calculation
        bool tapsAreCloseInTime = ((e.Timestamp - _lastTimestamp) < 700);
        if (tapsAreCloseInTime && tapsAreCloseInDistance)
        {
            _lastTapLocation = null;
        }
        _lastTimestamp = e.Timestamp;
        return tapsAreCloseInDistance && tapsAreCloseInTime;
    }
}