【问题标题】:Long Touch with Delphi VCL on Windows Tablet在 Windows 平板电脑上使用 Delphi VCL 进行长触
【发布时间】:2016-08-11 09:11:46
【问题描述】:

我为在 Windows 8.1 平板电脑上运行的 VCL 应用程序创建了一个 TCustomControl 派生类。

我正在使用 OnMouseDown / OnMouseUp 事件,尽管这显然是基于触摸的。

我想做的是检测长按 - 即触摸并按住 1 秒钟。所以在OnMouseDown事件中,我记录了向下的时间戳,设置一个标志来指示鼠标处于关闭状态,并创建一个休眠1秒的匿名线程,然后检查该标志。

OnMouseUp 中,我将标志设置为 false。

只要您在控件上摆动手指,此方法就可以工作。否则,如果您只是触摸并按住鼠标按下事件,则在您松开手指之前不会调用。

我看过手势,但这看起来完全是矫枉过正,据我所知,无论如何都不支持长按。

感谢您的任何建议。

理查德

【问题讨论】:

  • 如何在 MouseDown 发生时以 1000 毫秒的间隔激活一个计时器,并在 MouseUp 上取消它。将您的代码放入 OnTimer 事件中。只有在他们按住鼠标超过一秒钟后才会触发它。只要您保存启动它的控件,您就可以为整个表单使用一个计时器。不要忘记在 OnTimer 事件中立即禁用计时器。
  • 谢谢,但这与匿名线程的原因不同,除非您摆动手指或抬起手指,否则 MouseDown 不会触发。
  • 我没有 Windows 平板电脑,但我只是在新的 VCL 表单(柏林)中添加了一个 TButton 和一个 TMemo,并添加了代码以在 MouseDown 和 MouseUp 事件中向备忘录添加一行处理程序,这两个事件清楚地单独触发并与鼠标单击同步。平板电脑从标准 PC 鼠标触发事件的方式肯定有所不同。
  • 谢谢 - 是的,它与标准鼠标处理不同。如果我在台式 PC 上运行该应用程序并使用鼠标而不是手指,它会按预期运行。

标签: delphi touch windows-8.1 vcl


【解决方案1】:

您面临的是带有触摸输入设备的 Windows 的“正常”但可笑的愚蠢行为。我们现在面临同样的问题一段时间,并在过去几周内积极尝试解决它。 诀窍是,Windows 将触摸输入设备处理为“鼠标,可以用单指完全控制”。因此,它有几个状态,不仅仅是事件:

事件是:触摸开始(向下)、移动、向上、右键单击,如果您真的想注册回调,您将保持静止(自上次报告以来没有移动,但仍然向下)。

同时,还有更多的状态。首先,当您按下手指时,它会在内部检测到“Touch down!”事件。然后它会等待一定的时间(这可能会或可能不会被黑客更改,取决于驱动程序等...),以确定您想要的是否是右键单击(在 x 时间之后,在发布时!在 Y 时间之前!它会触发 右键单击 事件) 或者是否是左键单击 (触发事件 TouchBegin - 之后y 时间,比 x 时间长,在 y 过期后,会触发 left down 事件(不是点击!))。
同时,如果第一次触地被移动或-!等待 x 时间 过期!!在x时间用完之前松开手指,它会自动触发left down (on move)left click (on释放)。在 Y 时间到期或触发 MOVE 后的任何时间也是如此。

为了更简单易懂,我举个例子:

假设你有触控设备,时间安排如下: B 点开始,位于我们时间线的 0 秒处。 X 点是第一个触发断点,位于我们时间线的 5 秒处。 Y 点是第二个触发断点,位于我们时间轴的 10 秒处。

您将手指放在触摸上,时间线就开始了。 可能的场景: - 在 X 点之前随时释放它 -> 左键单击被触发(触地和向上事件,依次依次排列) - 在 X 点之后但在 Y 点之前释放它 -> 触发右键单击(触摸向下和向上事件,带有右键单击标志) - 你到达 Y 点 - 左下被触发! - 你在 Y 点之后随时释放它,无论是否在释放之间触发移动(但在时间线中到达此点之前不会触发移动)-> 触发左上。

  • 在到达 X 点之前触发(执行)移动事件 -> 左下被触发,然后是它检测到的尽可能多的移动事件,直到你释放它 -> 然后左上被触发
  • 您在 X 之后但在 Y 之前触发(执行)移动事件 -> 同上!
  • 您到达 Y 点并随后将其移动 -> 检查上方的第 4 点。

希望这对你有意义。

现在跳到可能的解决方案:自定义驱动程序是一种选择,但我们还没有,所以我们仍在尝试其他选择。目前最有希望的似乎是使用 RAW_INPUT 和 Touch 钩子,看起来我们必须将它们结合起来才能得到我们想要的东西。 好的一面是,Windows 本身确实会检测手指何时触摸设备,而不管它想要检测、确定然后转发给应用程序的时间和事件,但它们由于某种原因使其难以在这种性质下使用。作为证明,您可以简单地检查在您第一次触摸屏幕时出现在手指下方的透明点。

与此同时,Android 更好地处理这些事情......

希望它有所帮助,一旦我们完成并获得足够好使用的东西,我很高兴能够提供完整的解决方案。

M.*

【讨论】:

    【解决方案2】:

    如果 MouseDown 事件没有被触发并且你想让你的延迟计数器依赖于它,那么你基本上就完蛋了。也就是说,我假设您对概念的微小变化持开放态度。 :)

    我认为如果您将按钮更改为类似翻转开关的东西,它仍然可以完成。用户必须“抓住”(触摸)它,“拉起”(拖动,应该触发 StartDrag 事件)并在那里保持所需的时间。释放开关(MouseDown 事件)后,它会弹回。

    要设计这样一个按钮,您可以使用一个小的 TPanel 作为旋钮,并使用一个稍大的 TPanel 来允许在其上进行有限的垂直移动。将 BevelInner 属性设置为 bvLowered,将 BevelOuter 设置为 bvRaised,使其看起来像一个框架,旋钮面板是它的子项。或者使用 TImage 在它的向上/向下位置显示旋钮。在任何情况下,将旋钮元素的 DragKind 属性设置为 dkDrag 否则 StartDrag 事件将不会发生。如果仍然没有触发任何事件,请尝试detect touch input capabilities 并报告您的发现..

    不确定这是否有资格获得答案,但也许值得一试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-31
      • 1970-01-01
      • 1970-01-01
      • 2022-12-12
      • 1970-01-01
      • 1970-01-01
      • 2014-11-20
      相关资源
      最近更新 更多