我使用的是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的一些问题?
如果没有匹配的按下/释放对,我不确定如何区分真正的问题与仅仅是将手指放在屏幕上而不是移动它的人。
答案 0 :(得分:0)
来自http://msdn.microsoft.com/library/windows/apps/br208971:
其他事件而不是PointerReleased可能会在操作结束时触发 - 例如,PointerCanceled或PointerCaptureLost。不要依赖PointerPressed和PointerReleased事件,这些事件总是成对出现。要正常运行,您的应用必须倾听并处理所有可能对Press操作产生结论的事件。您可能无法获得PointerReleased事件的一些原因是:
答案 1 :(得分:0)
可能还有另一个原因。请在此处查看我的回答:How to handle multi touch in windows phone 8 app
可能的原因可能是竞争条件。
答案 2 :(得分: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);