How to handle multi touch in windows phone 8 app

喜夏-厌秋 提交于 2019-12-07 18:38:54

问题


I can not find an example how to handle multi touch in windows phone 8 app ( in game on c++ and directx ). May be anyone can help me? Thanks!


回答1:


I figured out how to do it. I am a C++ newbie so there may be much better ways to do this, but my way works.

(FYI - I wrote an article about this on Nokia's Developer site: http://developer.nokia.com/Community/Wiki/Multi-touch_handling_using_DirectX_C%2B%2B#PointerPoint )

You need to keep track of the PointerId inside of the PointerPoint. I store the PointerId in the OnPointerPressed event in a std::unordered_map. The key (unsigned int) is the PointerId. You then erase them from the map when you get the OnPointerReleased event. The PointerId will match up. It turns out that for every new finger, you get a new PointerId... even if you release your first finger and put it back down again.

Then, when you get to your OnPointerMoved event handler, you just have to call the size() function on your unordered_map to find out how many touches you currently have on screen.

The reason I'm using the unordered_map is because I needed to keep track of previous point positions. I realize that you can probably get old positions using the GetIntermediatePoints method, but I didn't want to have to troubleshoot something new...

Anyways, hope this helps. Code below:

EDIT: Code updated to handle the x move events you get from each touch for each frame. Like I said, this isn't the best, but it works.

#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);
}



回答2:


The code above greatly shows the idea, but there are some crucial details behind which can be unseen even in practice. OnPointerPressed event comes right from the message queue which is handled by the UI thread. Whereas OnPointerMoved event is called from the other thread NPCtrl.dll!CDirectManipulationServer::ServerThreadStatic. It can easily be seen from the native debugger in VS. This is an open field for race conditions between the two threads which indeed happened in practice in this particular case as my test showed. So obviously this code needs to be improved with synchronization patterns like

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);
}

where eventLock is std::mutex. Same lock should be added to all three events. The other approach is more complex and would involve a concurrent queue which is added to whenever a new event fires.



来源:https://stackoverflow.com/questions/19641199/how-to-handle-multi-touch-in-windows-phone-8-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!