2

我正在使用 Monogame 并且遇到了一个问题,如果我快速将很多手指放在屏幕上然后快速移除它们,最终(经过几次重复)我最终会得到一些从未得到匹配的“已释放”的“按下”事件事件。

我不认为问题出在 Monogame 上,因为我可以使用使用 vs2012 创建的小型“Windows Phone 和 Direct3D”应用程序重现该问题(在我的诺基亚 Lumia 920 上)。

在 C++ 方面,我只是在生成的 Direct3DInterop 类中存储一个向量,该类记录按下事件和释放事件

void Direct3DInterop::OnPointerPressed(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)
{
    uint32 pointerID = args->CurrentPoint->PointerId;

    auto i = std::find (_pressed.begin(), _pressed.end(), pointerID);
    if (i == _pressed.end())
        _pressed.push_back(pointerID);
}
void Direct3DInterop::OnPointerReleased(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)
{
    uint32 pointerID = args->CurrentPoint->PointerId;

    _pressed.erase(std::remove(_pressed.begin(), _pressed.end(), pointerID),       _pressed.end());
}

在我的 XAML 中,我只有一个文本块和一个调度计时器,它定期检查 _pressed 中的元素计数(它应该始终返回 0)。

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent" 
  Margin="0,115,0,0">
<DrawingSurface x:Name="DrawingSurface" Margin="0,-113,0,0" Loaded="DrawingSurface_Loaded"/>
<TextBlock x:Name="LostReleasedCount" Text="Lost released count = 0"   HorizontalAlignment="Left" Margin="0,-113,0,0" VerticalAlignment="Top" Height="113"  Width="480"/>

</Grid>

并在文件后面的代码中

private Direct3DInterop m_d3dInterop = null;
private DispatcherTimer _timer;
private int _seconds;

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    // Creates a new instance of a timer.
    _timer = new DispatcherTimer();

    // Tells the _timer to tick every  second.
    _timer.Interval = TimeSpan.FromSeconds(1);


   _timer.Tick += TimerOnTick;
    _timer.Start();
    _seconds = 0;

}

private void TimerOnTick(object sender, EventArgs eventArgs)
{

    Dispatcher.BeginInvoke(() =>
    {
        _seconds++;
        LostReleasedCount.Text = "Lost released count = " + m_d3dInterop.GetPressedCount().ToString();
    });
}

我在这里遗漏了一些明显的东西吗?您是否应该始终期望按下事件和释放事件匹配?如果我直接将 XAML 与 Touch.FrameReported 事件一起使用,我将无法重现该问题,所以这可能是 DirectX 的一些问题?

如果没有匹配的按下/释放对,我不确定如何将真正的问题与仅将手指放在屏幕上而不移动它的人区分开来。

4

3 回答 3

0

可能还有另一个原因。请在此处查看我的答案:如何在 windows phone 8 应用程序中处理多点触控

可能的原因可能是竞争条件

于 2014-03-12T14:52:43.503 回答
0

来自http://msdn.microsoft.com/library/windows/apps/br208971

其他事件而不是 PointerReleased 可能会在操作结束时触发 - 例如,PointerCanceled 或 PointerCaptureLost。不要依赖 PointerPressed 和 PointerReleased 事件总是成对发生。为了正常运行,您的应用程序必须侦听并处理所有代表 Press 操作可能得出结论的事件。您可能无法获得 PointerReleased 事件的一些原因是:

  • 特定硬件如何处理触摸动作和按下动作的差异
  • 从不同指针捕获的程序化指针
  • 更改显示区域关系的用户操作,例如更改分辨率或显示器设置
  • 输入交互,例如触控笔与先前的触摸动作触摸相同的表面
于 2013-12-31T15:51:30.990 回答
0

在 Direct3DBackground 类中添加此函数

void Direct3DBackground::SetManipulationHost(Windows::Phone::Input::Interop::
             DrawingSurfaceManipulationHost^ manipulationHost)
{
    manipulationHost->PointerPressed +=
                      ref new TypedEventHandler<
              DrawingSurfaceManipulationHost^, PointerEventArgs^>
              (this, &Direct3DBackground::OnPointerPressed);

    manipulationHost->PointerMoved +=
        ref new TypedEventHandler<DrawingSurfaceManipulationHost^, 
         PointerEventArgs^>(this, &Direct3DBackground::OnPointerMoved);

    manipulationHost->PointerReleased +=
        ref new TypedEventHandler<DrawingSurfaceManipulationHost^, 
         PointerEventArgs^>(this, &Direct3DBackground::OnPointerReleased);
}

在 XAML C# 代码中:

DrawingSurfaceBackground.SetBackgroundManipulationHandler(m_d3dBackGround);
于 2014-03-25T03:33:40.860 回答