2

我找不到如何在 windows phone 8 应用程序中处理多点触控的示例(在 c++ 和 directx 上的游戏中)。可能有人可以帮助我吗?谢谢!

4

2 回答 2

1

我想出了怎么做。我是一个 C++ 新手,所以可能有更好的方法来做到这一点,但我的方法有效。

(仅供参考 - 我在诺基亚的开发者网站上写了一篇关于此的文章:http: //developer.nokia.com/Community/Wiki/Multi-touch_handling_using_DirectX_C%2B%2B#PointerPoint

您需要跟踪 PointerPoint 内的 PointerId。我将 PointerId 存储在 std::unordered_map 中的 OnPointerPressed 事件中。键(无符号整数)是 PointerId。然后,当您收到 OnPointerReleased 事件时,您将它们从地图中删除。PointerId 将匹配。事实证明,对于每一个新手指,您都会获得一个新的 PointerId……即使您松开第一根手指并再次放下它。

然后,当您到达 OnPointerMoved 事件处理程序时,您只需调用 unordered_map 上的 size() 函数即可了解您当前在屏幕上进行了多少次触摸。

我使用 unordered_map 的原因是因为我需要跟踪以前的点位置。我意识到您可能可以使用 GetIntermediatePoints 方法获得旧职位,但我不想对新事物进行故障排除......

无论如何,希望这会有所帮助。下面的代码:

编辑:更新代码以处理您从每帧的每次触摸中获得的 x 移动事件。就像我说的,这不是最好的,但它有效。

#include <unordered_map>
std::unordered_map<unsigned int, Windows::UI::Input::PointerPoint^> m_pointerIds;
std::unordered_map<unsigned int, Windows::UI::Input::PointerPoint^> m_oldPoints;

void Direct3DBackground::OnPointerPressed(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)
{   
    m_pointerIds.emplace(args->CurrentPoint->PointerId, args->CurrentPoint);
    m_oldPoints.emplace(args->CurrentPoint->PointerId, args->CurrentPoint);
}

void Direct3DBackground::OnPointerMoved(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)
{
    if (m_pointerIds.size() == 1)
    {
        DoSomethingForOneTouch(args);
    }
    else if (m_pointerIds.size() == 2)
    {
        UINT changedPointId = args->CurrentPoint->PointerId;
        UINT frameId = args->CurrentPoint->FrameId;

        UINT otherPointId;
        for (auto it = m_pointerIds.begin(); it != m_pointerIds.end(); ++it)
        {
            if (it->first != changedPointId)
            {
                otherPointId = it->first;
                break;
            }
         }

         m_oldPoints[changedPointId] = m_pointerIds[changedPointId];
         m_pointerIds[changedPointId] = args->CurrentPoint;

         if (m_pointerIds[otherPointId]->FrameId == frameId)
         {  
                  //DO YOUR CALCULATION using new points and old points 
                  //as both touches have been updated for the current frame.
         }
    }
}

void Direct3DBackground::OnPointerReleased(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)
{
    m_pointerIds.erase(args->CurrentPoint->PointerId);
        m_oldPoints.erase(args->CurrentPoint->PointerId);
}
于 2013-11-13T05:39:26.717 回答
0

上面的代码很好地展示了这个想法,但是即使在实践中也看不到背后的一些关键细节。OnPointerPressed事件来自由 UI 线程处理的消息队列。而 OnPointerMoved从另一个线程调用事件NPCtrl.dll!CDirectManipulationServer::ServerThreadStatic。从 VS 中的本机调试器可以很容易地看出这一点。这是两个线程之间的竞争条件的开放领域,正如我的测试所示,在这种特殊情况下实际上确实发生了这种情况。所以很明显,这段代码需要用同步模式来改进,比如

void Direct3DBackground::OnPointerPressed(DrawingSurfaceManipulationHost^ sender, PointerEventArgs^ args)
{ 
    std::unique_lock<std::mutex> l(eventLock);
    m_pointerIds.emplace(args->CurrentPoint->PointerId, args->CurrentPoint);
    m_oldPoints.emplace(args->CurrentPoint->PointerId, args->CurrentPoint);
}

eventLock在哪里std::mutex。应该为所有三个事件添加相同的锁。另一种方法更复杂,并且会涉及一个并发队列,每当触发新事件时都会添加该队列。

于 2014-03-12T14:39:36.360 回答