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

时间:2012-01-25 10:21:57

标签: c# wpf touch

我发布了另一个关于如何手动'通过监控TouchDown事件触摸之间的时间跨度捕获双击,但它非常错误。有没有人知道在多点触摸屏上捕获双击的标准Microsoft方式/事件?

非常感谢,

4 个答案:

答案 0 :(得分:10)

我检查了水龙头位置和秒表的组合,它完美无缺!

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是否为DoubleTap。

答案 1 :(得分:3)

Jowens的答案对我有很大的帮助(如果我的名声会让我,我会支持它;)) 但我必须调整它,所以它只使用双击。原始代码确实认为任何高于2的点击都是双击。将_lastTapLocation更改为可为空,并在双击时重置它。

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;
    }

答案 2 :(得分:1)

我认为使用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
            }
        }
    }

答案 3 :(得分:1)

添加到Andreas的回答中,您也可以删除与秒表相关的代码。

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;
    }
}