Reaktion auf Fingereingabe
Inhaltsverzeichnis reduzieren
Inhaltsverzeichnis erweitern

Reagieren auf Toucheingaben (DirectX und C++)

[ Dieser Artikel richtet sich an Windows 8.x- und Windows Phone 8.x-Entwickler, die Windows-Runtime-Apps schreiben. Wenn Sie für Windows 10 entwickeln, finden Sie weitere Informationen unter neueste Dokumentation ]

Toucheingabeereignisse werden auf dieselbe Weise wie Maus- und Tabletstiftereignisse behandelt: mithilfe eines generischen Eingabetyps, der als Zeiger bezeichnet wird. Ein Zeiger stellt die Daten zur Bildschirmposition für die aktuell aktive Eingabequelle dar. Hier geht es darum, Toucheingaben in Windows-Runtime-Apps mit DirectX und C++ zu unterstützen.

Einführung

Unten sind die vier grundlegenden Zeigerereignisse für CoreWindow aufgeführt, die die App behandeln kann. Für die Zwecke dieses Themas werden hier Toucheingabeereignisse als Zeigerereignisse angenommen.

  • PointerMoved. Der Benutzer hat den Finger über die Eingabeoberfläche bewegt.
  • PointerPressed. Der Benutzer hat die Eingabeoberfläche mit dem Finger berührt.
  • PointerReleased. Der Benutzer berührt die Eingabeoberfläche nicht mehr.
  • PointerExited. Der Benutzer hat den Finger aus dem Begrenzungsrahmen des Fensters bewegt.

Verwenden Sie beim Arbeiten mit Interoperabilität von DirectX und XAML die vom XAML-Framework bereitgestellten Toucheingaben für die einzelnen XAML-Elemente. Diese Ereignisse werden als Teil des Windows::UI::Xaml::UIElement-Typs bereitgestellt.

In Windows::UI::Input sind außerdem erweiterte Eingabetypen für Gesten und Manipulationen definiert, bei denen es sich um Ereignisabfolgen handelt, die vom GestureRecognizer-Typ interpretiert werden. Zu diesen Eingabetypen zählen Gesten zum Ziehen, Streichen, Querstreichen und Halten.

Behandeln grundlegender Toucheingabeereignisse

Hier stellen wir Ihnen die Handler für die drei häufigsten grundlegenden Toucheingabeereignisse vor:

Wir gehen für diesen Abschnitt davon aus, dass Sie einen Ansichtsanbieter für Ihre Windows-Runtime-App mit DirectX erstellt haben. Sollte dies nicht zutreffen, finden Sie unter So wird's gemacht: Einrichten der Windows-Runtime-App zum Anzeigen einer DirectX-Ansicht weitere Informationen.

Als Erstes füllen wir die Ereignishandler für den Toucheingabezeiger auf. Im ersten Ereignishandler OnPointerPressed rufen wir die X- und Y-Koordinaten des Zeigers vom CoreWindow-Objekt ab, das die Anzeige verwaltet, wenn der Benutzer den Bildschirm berührt oder mit der Maus klickt. Definieren Sie die Handler in den Implementierungen von IFrameworkView::Initialize oder IFrameworkView::SetWindow. (Für dieses Beispiel wurde SetWindow verwendet.)


void MyTouchApp::SetWindow(
    _In_ CoreWindow^ window
    )
{
    // .. Other window event initialization here ...

    window->PointerPressed +=
        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &CoreWindowEvents::OnPointerPressed);
    window->PointerReleased +=
        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &CoreWindowEvents::OnPointerReleased);
    window->PointerMoved +=
        ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &CoreWindowEvents::OnPointerMoved);
    
        }

Hinweis  Wenn Sie mit Interoperabilität von DirectX und XAML arbeiten, stellt XAML eine eigene Ansicht (FrameworkView) bereit. Führen Sie stattdessen die Registrierung für die Zeigerereignisse aus, die mit den UIElement-Typen für die XAML-Elemente im Layout bereitgestellt werden. Weitere Informationen finden Sie unter Schnellstart: Behandeln von Zeigereingaben.
 

Erstellen Sie jetzt die entsprechenden Rückrufe, um die Zeigerdaten abzurufen und zu behandeln. Verfolgen Sie die Zeiger-ID-Werte nach, wenn die App die Zeigerereignisse und -daten nicht mit GestureRecognizer interpretiert, um Zeiger von Multitoucheingabegeräten unterscheiden zu können. (Die Mehrzahl der Oberflächen unterstützt die Multitoucheingabe. Das bedeutet, dass möglicherweise viele Zeiger zugleich nebeneinander bestehen.) Verfolgen Sie ID und Position des Zeigers für jedes Ereignis nach, damit Sie die passende Aktion für die Bewegung oder Geste verwenden, die dem betreffenden Zeiger zugeordnet ist.

OnPointerPressed


void MyTouchApp::OnPointerPressed(
                                           _In_ CoreWindow^ sender,
                                           _In_ PointerEventArgs^ args)
{
    // get the current pointer position
    uint32 pointerID = args->CurrentPoint->PointerId;
    XMFLOAT2 position = XMFLOAT2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

    auto device = args->CurrentPoint->PointerDevice;
    auto deviceType = device->PointerDeviceType;
    

	   // If the pointer press event is in a specific control, set the control to active 
    // if the control is activated by a press.
    // Set the tracking variables for this control to the pointer ID and starting position.

}
        

Hinweis  XMFLOAT2 wird in „DirectXMath.h“ definiert.
 

Der OnPointerMoved-Ereignishandler wird bei jeder Bewegung des Zeigers ausgelöst – bei jedem Teilstrich, um den der Benutzer den Zeiger auf dem Bildschirm bewegt. Mit dem folgenden Codebeispiel erreichen Sie, das die App stets über die aktuelle Position des Zeigers in Bewegung informiert ist:

OnPointerMoved


void MyTouchApp::OnPointerMoved(
                                        _In_ CoreWindow ^sender,
                                        _In_ PointerEventArgs ^args)
{
    uint32 pointerID = args->CurrentPoint->PointerId;
    XMFLOAT2 position = XMFLOAT2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

    // Update the position in any tracking variables for this pointer ID. 
}

Schließlich muss die Erfassung der Toucheingabe beendet und ggf. die Bewegung interpretiert werden, wenn der Benutzer den Bildschirm nicht mehr berührt.

OnPointerReleased


void MyTouchApp::OnPointerReleased(
                                             _In_ CoreWindow ^sender,
                                             _In_ PointerEventArgs ^args)
{
    uint32 pointerID = args->CurrentPoint->PointerId;
    XMFLOAT2 position = XMFLOAT2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

    // Process the touch input results here. Set the tracking variable pointer ID value 
    // to 0 when you're done.
   
}

In diesem Beispiel ruft der Code einfach den aktuellen Zeiger-ID-Wert und die Position für diesen Zeiger ab. Es liegt an Ihnen, die Daten zu interpretieren. Für die Aktivierung des Steuerelements reicht es, das PointerPressed-Ereignis zu behandeln. Für komplexere Touchaktionen müssen Sie einige Variablen oder Methoden erstellen, um Zeiger-ID und Anfangsposition für die Geste zu erfassen und mit dem Bewegen und Loslassen des Zeigers die Variablen zu aktualisieren bzw. die Methoden aufzurufen.

Umwandlung von Touchereignissen in Gesten

Ihre App erkennt jetzt Toucheingaben mit Rückrufen für die grundlegenden Toucheingabeereignisse. Diese Ereignisse müssen nun von der App interpretiert werden. Eine Möglichkeit dafür ist die Verwendung der GestureRecognizer-Klasse. Ein GestureRecognizer-Objekt verarbeitet Ereignisse wie PointerPressed, PointerMoved und PointerReleased und stellt eigene Ereignisse wie Tapped, Holding oder Dragging bereit. Diese Ereignisse höherer Ebene werden als Gesten bezeichnet und dienen dazu, die häufigsten Benutzerinteraktionsanforderungen von Apps zu erfüllen.

Hinweis  Für Szenen mit mehreren Objekten oder Steuerelementen, die unabhängig voneinander und gleichzeitig manipuliert werden müssen, können Sie jeweils einen eigenen GestureRecognizer verwenden.
 

Nachfolgend ist beschrieben, wie Sie GestureRecognizer mit den im vorangehenden Schritt verarbeiteten Touchereignissen verwenden.

  1. Erstellen Sie mindestens ein GestureRecognizer-Objekt für die App, und initialisieren Sie GestureSettings für jede Geste, die unterstützt werden soll. Gesten sind beispielsweise:

    • Tippen. Der Benutzer tippt einmal oder doppelt auf dieToucheingabeoberfläche.
    • Halten. Der Benutzer hält den Finger für eine bestimmte Zeit auf der Oberfläche gedrückt.
    • Ziehen. Der Benutzer bewegt den auf die Oberfläche gedrückten Finger in eine Richtung.
    • Manipulieren. Der Benutzer führt eine Geste wie Streichen, Zusammendrücken oder Aufziehen aus, um die Anzeige oder ein Objekt zu skalieren, zu zoomen oder zu drehen.

    Für GestureRecognizer gibt es einen Satz von Ereignissen, die Sie für diese Gesten behandeln können, darunter:

    Im Folgenden erfahren Sie, wie Sie die Registrierung für diese Ereignisse durchführen und wie Sie für GestureRecognizer die Toucheingabedaten bereitstellen, die zur Identifizierung dieser Ereignisse erforderlich sind. In diesem Beispiel wird der IFrameworkView::SetWindow-Implementierung der folgende Code hinzugefügt, um einen GestureRecognizer für die Doppeltippbewegung zu erstellen und einen Handler für das GestureRecognizer::Tapped-Ereignis zu registrieren. Die Gestikerkennung wird wie folgt deklariert:

    Platform::Agile<Windows::UI::Input::GestureRecognizer> m_gestureRecognizer;
    
    m_gestureRecognizer = ref new GestureRecognizer(); 
    
    m_gestureRecognizer->GestureSettings = 
            GestureSettings::DoubleTap; 
     
    m_gestureRecognizer->Tapped += 
            ref new TypedEventHandler<GestureRecognizer^, TappedEventArgs^>(this, &CommandListRenderer::OnTapped); 
     
    
    
    
    
  2. Erstellen Sie in der App Handler für die zu interpretierenden Gesten, und verbinden Sie diese mit den Ereignissen für den GestureRecognizer. In unserem Beispiel erstellen Sie einen einzigen Handler für die Ansichtsanbieterklasse OnTapped, um das Tippereignis zu behandeln:

    
    void MyTouchApp::OnTapped( 
        _In_ GestureRecognizer^ gestureRecognizer, 
        _In_ TappedEventArgs^ args 
        ) 
    { 
        if (args->TapCount == 2) // the tap event is a double tap
        { 
            HandlePointerDoubleTapped(args->Position); 
        } 
    } 
    
    void MyTouchApp::HandlePointerDoubleTapped(Point position) 
    { 
        // Recenter the object around the screen location of the first tap of the 
        //double tap gesture.
        m_recenter = true; 
        m_recenterStartPosition.x = m_viewPosition.X; 
        m_recenterStartPosition.y = m_viewPosition.Y; 
        m_recenterStartZoom = m_zoom; 
    } 
    
    
    
    

  3. Damit das GestureRecognizer-Objekt die Toucheingabedaten für diese Ereignisse abruft, müssen Sie diese per Übergabe der Zeigerdaten von den Handlern für die grundlegenden Toucheingabeereignisse bereitstellen (wie OnPointerPressed im vorherigen Beispiel).

    Dazu müssen Sie die App-Handler für die grundlegenden Eingabeereignisse anweisen (PointerPressed, PointerReleased und PointerMoved), die entsprechenden Methoden ProcessDownEvent, ProcessUpEvent und ProcessMoveEvents von GestureRecognizer aufzurufen.

    
    void MyTouchApp::OnPointerPressed( 
        _In_ CoreWindow^ window, 
        _In_ PointerEventArgs^ args 
        ) 
    { 
        m_gestureRecognizer->ProcessDownEvent(args->CurrentPoint); 
    } 
    
    void MyTouchApp::OnPointerReleased( 
        _In_ CoreWindow^ window, 
        _In_ PointerEventArgs^ args 
        ) 
    { 
        m_gestureRecognizer->ProcessUpEvent(args->CurrentPoint); 
    } 
     
    // We don't need to provide pointer move event data if we're just looking for double
    // taps, but  we'll do so anyhow just because many apps will need this data.
    void MyTouchApp::OnPointerMoved( 
        _In_ CoreWindow^ window, 
        _In_ PointerEventArgs^ args 
        ) 
    { 
        m_gestureRecognizer->ProcessMoveEvents(args->GetIntermediatePoints()); 
    } 
     
    
    
    

    Jetzt kann GestureRecognizer die Eingabesequenz nachverfolgen und bei Erkennung eines Satzes an Eingaben, die mit einer Geste übereinstimmen, ein Ereignis auslösen (hier das GestureRecognizer::Tapped-Ereignis).

In Szenarien höherer Komplexität, insbesondere solchen mit mehreren GestureRecognizer, müssen Sie anhand von Toucheingabe-Treffertests bestimmen, welche Instanzen von GestureRecognizer aktiv sind.

Verteilen von Ereignismeldungen

Sie haben in der IFrameworkView::Run-Methode, die Sie im Ansichtsanbieter der App implementiert haben, die Hauptverarbeitungsschleife erstellt. Rufen Sie in dieser Schleife wie folgt CoreEventDispatcher::ProcessEvents für den Ereignisverteiler für das App-CoreWindow auf:

CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);

Der CoreProcessEventsOption::ProcessAllIfPresent-Enumerationswert weist ProcessEvents an, Bei Aufruf von ProcessEvents die Rückrufe für die einzelnen Ereignisse in der Meldungswarteschlange zu verteilen. Damit behandelt die App die Änderungen der Toucheingaben, die der Benutzer ausführt, und aktualisiert die Zeigerdaten so, dass diese mit dem Rendering synchronisiert werden und die Rückmeldung nahtlos erfolgt. Verwenden Sie diesen CoreProcessEventsOption-Wert, wenn die App eine kontinuierlich ausgeführte timergesteuerte Renderingschleife aufweist und Sie die Eingabeereignisse mit einem Timer oder mit jeder Schleifeniteration verarbeiten möchten. Auch hier muss der Aufruf mit jeder Schleifeniteration bzw. zu jedem Timerintervall erfolgen.

Alternativ kann die App bei angehaltenem Rendering auch selbst angehalten werden oder in den Hintergrund wechseln. In diesem Fall rufen Sie bei Wechsel in diesen Status ProcessEvents mit CoreProcessEventsOption::ProcessOneAndAllPending auf. Dadurch werden alle aktuellen und ausstehenden Ereignismeldungen verarbeitet, wenn die App angehalten wird.

Bei dem folgenden Codebeispiel für eine Implementierung von IFrameworkView::Run wird einer der beiden CoreProcessEventsOption-Werte für ProcessEvents anhand des App-Status ausgewählt:


void MyTouchApp::Run()
{
	while (!m_coreWindowClosed)
	{
		switch (m_updateState)
		{
			case UpdateEngineState::Deactivated: // the app's process is not active (it's suspended)
			case UpdateEngineState::Snapped: // the app's window is snapped
				if (!m_renderNeeded)
				{
					CoreWindow::GetForCurrentThread()->Dispatcher->
						ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
					break;
				}
			default: // the app is active and not snapped
					CoreWindow::GetForCurrentThread()->Dispatcher->
						ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
					m_myGameObject->Render();
					m_myGameObject->PresentSwapChain(); // calls IDXGISwapChain::Present()
					m_renderNeeded = false;
				}
		}
	}
}

Weitere Informationen zum Verteilen von Ereignismeldungen finden Sie unter Arbeiten mit Ereignismeldungen und CoreWindow (DirectX und C++).

DirectX-Beispiele für Toucheingaben

Hier finden Sie eine Reihe umfassender Codebeispiele zur Unterstützung von Toucheingaben und Gesten für Windows-Runtime-Apps mit DirectX.

Verwandte Themen

Schnellstart: Behandeln von Zeigereingaben
Reagieren auf Benutzerinteraktionen (DirectX und C++)
Arbeiten mit Ereignismeldungen und CoreWindow (DirectX und C++)

 

 

Anzeigen:
© 2017 Microsoft