【发布时间】:2014-09-04 05:43:22
【问题描述】:
我正在尝试解决电容式触摸屏的灵敏度问题,如果用户的手指太靠近屏幕表面,则会触发 WPF 按钮。
此问题是,许多用户最终将手指或手的一部分(而不是他们的主要触摸手指)靠近屏幕表面,这会导致触发不正确的按钮。
调整屏幕的灵敏度似乎没什么区别,我想我可以尝试修改按钮按下事件,仅在按下按钮超过一定时间时才触发点击。
谁能解释我如何创建一个自定义按钮,该按钮在触发 Clicked 事件之前具有可调整的“按下”时间。
如果可能的话,也许您会很乐意包含一个非常简单的 C#/WPF 应用程序和这样一个自定义按钮。
编辑
好的,所以我使用下面的代码创建了一个子类 Button,根据 @kidshaw 的回答,但我认为我一定遗漏了一些东西,因为除了默认的 Click 事件之外什么都没有被调用。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
namespace AppName
{
public class TouchButton : Button
{
DoubleAnimationUsingKeyFrames _animation;
public static readonly DependencyProperty DelayElapsedProperty =
DependencyProperty.Register("DelayElapsed", typeof(double), typeof(TouchButton), new PropertyMetadata(0d));
public static readonly DependencyProperty DelayMillisecondsProperty =
DependencyProperty.Register("DelayMilliseconds", typeof(int), typeof(TouchButton), new PropertyMetadata(100));
public double DelayElapsed
{
get { return (double)this.GetValue(DelayElapsedProperty); }
set { this.SetValue(DelayElapsedProperty, value); }
}
public int DelayMilliseconds
{
get { return (int)this.GetValue(DelayMillisecondsProperty); }
set { this.SetValue(DelayMillisecondsProperty, value); }
}
private void BeginDelay()
{
this._animation = new DoubleAnimationUsingKeyFrames() { FillBehavior = FillBehavior.Stop };
this._animation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)), new CubicEase() { EasingMode = EasingMode.EaseIn }));
this._animation.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(this.DelayMilliseconds)), new CubicEase() { EasingMode = EasingMode.EaseIn }));
this._animation.Completed += (o, e) =>
{
this.DelayElapsed = 0d;
//this.Command.Execute(this.CommandParameter); // Replace with whatever action you want to perform
Console.Beep();
this.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
};
this.BeginAnimation(DelayElapsedProperty, this._animation);
}
private void CancelDelay()
{
// Cancel animation
this.BeginAnimation(DelayElapsedProperty, null);
}
private void TouchButton_TouchDown(object sender, System.Windows.Input.TouchEventArgs e)
{
this.BeginDelay();
}
private void TouchButton_TouchUp(object sender, System.Windows.Input.TouchEventArgs e)
{
this.CancelDelay();
}
}
}
TouchButton_TouchDown 方法是如何被调用的?我不必以某种方式将其分配给 TouchDown 偶数处理程序吗?
好的,我添加了一个构造函数并设置了 TouchDown/Up 事件处理程序,以便可以正常工作,但 CancelDelay() 不会阻止事件被触发。它似乎工作正常,并在用户抬起手指时被调用,但不会阻止事件被触发。
【问题讨论】:
-
你能不能用一个按钮创建一个用户控件,它会在按下时启动一个计时器,并在 100 毫秒后手动触发点击事件?
-
问题在于 Windows 触摸驱动程序似乎无法区分轻触或长触。因此,我需要该按钮仅在长按按钮时触发事件(并且需要进行一些实验来确定可用性的最佳持续时间)。我的猜测是按下大约 200 - 300 毫秒,而传递的触发器会少于 200。我想我可以在 Press 上启动计时器并在 Release 上停止它,如果 > X 触发事件。
-
这就是我的意思;)
-
与其使用 ClickEvent - 创建一个新的并引发它,比如说 DeferredClickEvent。 ClickEvent 将在第一次单击时由按钮触发,通过将其分离到自己的事件中,您只处理延迟后的延迟触发。
-
谢谢我已经这样做了,但是我必须添加一个标志
IsCancelled,它会在收到TouchUp事件时设置。因此,当动画完成时,它会检查IsCancelled = true是否会引发IsTouched事件。然后我必须在引发事件后将 IsTouched 属性重置为 false,因为它必须是一个瞬时属性,我用它来为颜色渐变设置动画。现在在真正的触摸屏上与用户一起测试它!
标签: c# wpf multi-touch