WPF에서 Multi Touch

아…깝깝합니다. 회사에서 WPF를 처음 접하는데, WPF로 Multi Touch 지원하는 앱을 만드라고 합니다.
일단 한 손가락, 두 손가락 까지는 이벤트가 발생하는것을 확인했습니다.
하지만, 이상한게 있습니다.
private void Window_TouchDown(object sender, TouchEventArgs e)
{
TouchPointCollection touchPoints = e.GetIntermediateTouchPoints(this);
if (touchPoints.Count == 3)
{
Trace.WriteLine(“세 손가락 터치 감지”);
}
}
이렇게 하면 Count가 한 손가락 터치할 때 3, 두손가락 터치할 때 1이됩니다.
미치고 환장하겠습니다.

그리고 세손가락 터치하면 이벤트도 발생을 안해요. 그냥 윈도우에 서 이벤트 받아서 처리하나봐요.

이걸 어디다가 물어봐야지 하다가 글 남겨 봅니다.

아…세손가락 제스처는 지원하지 않는게 맞나보네요…링크에 지원하지 않는다고…ㅜ.ㅜ

제스쳐랑 터치는 구현방식 자체가 다릅니다.
일단 제스쳐는 사용하시는 터치 패널로 윈도우에서 동작하는 것만 된다고 보시면 되고요.

터치는 패널만 지원하면 10지원을 했던걸로 기억을 하고요.
다만… 이게 패널 영향을 크게 받아서 3손가락 4손가락 이런건 패널에서 확실하게 이벤트를 줘야 합니다.

참고로 제가 작업했던건 대형 모니터 4개를 연결해서 보여주는 디지털 사이니지였는데요. 한대의 PC로 제어했고요.
두명 이상이 동시에 컨텐츠를 확대 축소 회전 이동 다 가능하게 만들었습니다.
10포인트 지원하는 패널이었고요.

멀티 터치에 대한 컨트롤은 TouchDown 이벤트 이용이 아닌,
StylusDown / StylusMove 이벤트를 사용하셔야 합니다.

StylusDown 이벤트 핸들러의 시그니처를 보면 StylusDownEventArgs클래스를 파라메터로 받을 수 있습니다.

위 클래스의 StylusDevice 속성으로 터치된 디바이스 정보를 가져올 수 있고,
StylusMove에서 파라메터 StylusEventArgs클래스로 위치 정보를 가져 올 수 있습니다.

private void MainCanvas_StylusDown(object sender, StylusDownEventArgs e)
{
    var device = e.StylusDevice;
    if (device.IsValid is false)
    {
        // 디바이스 이용 불가능
        return;
    }

    // 여기서 device.Id 로 배열 같은 자료 구조로 터치 디바이스를 개별 관리.
    // device.Id는 터치된 순서대로 index가 반환 됩니다.
    // 대충 이런식으로..?
    _touchPointer.Add(device != null ? device.Id : _touchPointer.Count);
}

터치의 위치는 Move에서 처리 할 수 있습니다.

private void MainCanvas_StylusMove(object sender, StylusEventArgs e)
{
    // 대략 이렇게
    var device = e.StylusDevice;
    var devicePoint = e.GetStylusPoints(this.xMainCanvas).Last();
    var movePoint = new Point(devicePoint.X, devicePoint.Y);
}

위 코드 조각들의 힌트로 원하시는 멀티 터치 구현을 하실 수 있을거에요!

1 Like

아 제가 질문을 잘못 파악하고 답글을 작성한 것 같군요.
멀티 터치 포인트에 대한 컨트롤이 아닌
한번에 두 손가락 터치 / 세 손가락 터치 에 대한 제스처에 대한 질문이었군요.

질문 글에 작성하신 코드로 동작이 안된다면
StylusDown 에서 터치에 발생된 디바이스 별로 이벤트가 발생되는데
여기서 디바이스를 별도 관리하여 갯수별로 처리 하면 되지 않을까 합니다.

private void MainCanvas_StylusDown(object sender, StylusDownEventArgs e)
{
    var device = e.StylusDevice;
    if (device.IsValid is false)
    {
        // 디바이스 이용 불가능
        return;
    }

    // 터치된 포인터 시간이 0.1초 이하인 디바이스 추출
    var multiTouchPointer =
        _touchPointerTime.Where(x => _touchPointerTime.Any(y => x.Key != y.Key && Math.Abs((x.Value - y.Value).TotalSeconds) <= 0.1));

    if(multiTouchPointer.Count() >= 2)
    {
        // 두손가락 터치
    }
    else if(multiTouchPointer.Count() >= 3)
    {
        // 세손가락 터치
    }
    else if(multiTouchPointer.Count() > 3)
    {
        thorw new Exception("지원하지 않은 제스처");
    }
    else
    {
        // Dictionary 자료구조
        _touchPointerTime.Add(device.Id, DateTime.Now);
    }
}

※ 알맞은 상황에 _touchPointerTime 초기화 처리

4 Likes

답변 감사합니다.
하지만 특이한 문제가 나타났습니다.
private void Window_StylusButtonDown(object sender, StylusButtonEventArgs e)
{
var device = e.StylusDevice;
var devicePoints = e.GetStylusPoints(this);

Trace.WriteLine("device Points Count : " + devicePoints.Count.ToString());

코드를 이렇게 짰는데, 항상 1로 나타 나더군요(터치를 1손가락으로 해도, 2손가락으로 해도…)…이상한 일입니다. 뭔가를 잘못하고있는것 같은데…뭔지를 모르겠습니다.
깝깝합니다. 아…3손가락 터치는 윈도우에서 끌고 가는게 맞는것 같습니다. 링크를 참고 해보면 “ 일부 3-4-손가락 터치 조작은 기본적으로 Windows 앱에서 더 이상 작동하지 않습니다.” 라고 하고 있습니다.

devicePoints 가 무엇인가요?
보여주신 코드에는 안보입니다.
참고로 제가 상용 서비스중인 멀티 터치를 WPF로 위와 비슷하게 해서 사용하고 있습니다.

devicePoints는 지역변수입니다. 테스트로 만든 코드라…

아…두손가락 터치 입력받았습니다.
한 손가락, 한 손가락 연속해서 들어오는군요…
이걸 몰라서 이틀동안 고생했네요…
음…이걸 활용해서 개발을 해야…으…이벤트가 이렇게 들어오리라고는 생각을 못해서…당황스럽네요…

1 Like