Freigeben über


Treffertests in der visuellen Ebene

Aktualisiert: November 2007

Dieses Thema enthält eine Übersicht über die Treffertestfunktionen der visuellen Ebene. Der Treffertest ermöglicht Ihnen, zu bestimmen, ob ein Geometrie- oder Punktwert im Bereich des gerenderten Inhalts eines Visual liegt, und erlaubt Ihnen die Implementierung von Benutzeroberflächenverhalten wie einem Positionierungsrechteck zum Auswählen mehrerer Objekte.

Dieses Thema enthält folgende Abschnitte.

  • Treffertestszenarien
  • Unterstützung für den Treffertest
  • Treffertest und Z-Reihenfolge
  • Verwenden des Standardtreffertests
  • Verwenden eines Treffertest-Ergebnisrückrufs
  • Verwenden eines Treffertestfilter-Rückrufs
  • Überschreiben des Standardtreffertests
  • Verwandte Abschnitte

Treffertestszenarien

Die UIElement-Klasse stellt die InputHitTest-Methode zur Verfügung, die Ihnen gestattet, einen erneuten Treffertest für ein Element mithilfe eines bestimmten Koordinatenwerts durchzuführen. In vielen Fällen stellt die InputHitTest-Methode die gewünschte Funktionalität zum Implementieren des Treffertests für Elemente bereit. Es gibt jedoch mehrere Szenarien, bei denen es möglicherweise erforderlich ist, den Treffertest auf der visuellen Ebene zu implementieren.

  • Treffertest für Nicht-UIElement-Objekte: Gilt beim Treffertest für Nicht-UIElement-Objekte wie DrawingVisual oder Grafikobjekte.

  • Treffertest unter Verwendung einer Geometrie: Gilt beim Treffertest unter Verwendung eines Geometrieobjekts statt des Koordinatenwerts eines Punkts.

  • Treffertest für mehrere Objekte: Gilt beim Treffertest für mehrere Objekte wie überlappende Objekte. Sie können Ergebnisse für alle grafischen Elemente abrufen, die eine Geometrie oder einen Punkt kreuzen, nicht nur für das erste.

  • Ignorieren der Richtlinie für den UIElement-Treffertest: Gilt beim Ignorieren der Richtlinie für den UIElement-Treffertest, wobei Faktoren wie die Tatsache, ob ein Element deaktiviert oder ausgeblendet ist, berücksichtigt werden.

Tipp

Ein vollständiges Codebeispiel, in dem der Treffertest in der visuellen Ebene veranschaulicht wird, finden Sie unter Beispiel für Treffertests mit "DrawingVisuals" und Beispiel für Treffertests mit Win32-Interoperabilität.

Unterstützung für den Treffertest

Der Zweck der HitTest-Methoden in der VisualTreeHelper-Klasse besteht darin, zu bestimmen, ob eine Geometrie oder ein Punktkoordinatenwert sich im Bereich des gerenderten Inhalts eines bestimmten Objekts, z. B. eines Steuerelements oder eines grafischen Elements, befindet. Sie können beispielsweise den Treffertest verwenden, um zu bestimmen, ob ein Mausklick innerhalb des umgebenden Rechtecks eines Objekts in die Geometrie eines Kreises fällt. Sie können auch die Standardimplementierung für den Treffertest überschreiben, um Ihre eigenen benutzerdefinierten Treffertestberechnungen durchzuführen.

Die folgende Abbildung zeigt die Beziehung zwischen dem Bereich eines nicht rechteckigen Objekts und seinem umschließenden Rechteck.

Diagramm des gültigen Treffertestbereichs

Diagramm eines gültigen Treffertestbereichs

Treffertest und Z-Reihenfolge

Die visuelle Ebene für Windows Presentation Foundation (WPF) unterstützt den Treffertest für alle Objekte unter einem Punkt oder einer Geometrie und nicht nur für das oberste Objekt. Ergebnisse werden in Z-Reihenfolge zurückgegeben. Das visuelle Objekt, das Sie als Parameter an die HitTest-Methode weitergeben, bestimmt jedoch, welcher Bereich der visuellen Struktur dem Treffertest unterzogen wird. Sie können einen Treffertest für die ganze visuelle Struktur oder einen beliebigen Teil davon durchführen.

In der folgenden Abbildung befindet sich das Kreisobjekt sowohl auf dem Quadrat als auch auf dem Dreieck. Wenn Sie nur einen Treffertest für das visuelle Objekt vornehmen möchten, dessen Wert für die Z-Reihenfolge der oberste ist, können Sie die Enumeration für den visuellen Treffertest so festlegen, dass er Stop von HitTestResultCallback zurückgibt, um das Durchlaufen des Treffertests nach dem ersten Element zu beenden.

Diagramm der Z-Reihenfolge einer visuellen Struktur

Diagramm der Z-Reihenfolge einer visuellen Struktur

Wenn Sie alle visuellen Objekte unter einem bestimmten Punkt oder einer Geometrie auflisten möchten, geben Sie Continue von HitTestResultCallback zurück. Das heißt, dass Sie den Treffertest für visuelle Objekte durchführen können, die unter anderen Objekten liegen, selbst wenn sie vollständig verdeckt werden. Weitere Informationen finden Sie im Beispielcode im Abschnitt "Verwenden eines Treffertest-Ergebnisrückrufs".

Tipp

Auch für transparente visuelle Objekte kann der Treffertest durchgeführt werden.

Verwenden des Standardtreffertests

Sie können feststellen, ob sich ein Punkt innerhalb der Geometrie eines Objekts befindet, indem Sie die HitTest-Methode verwenden, um ein visuelles Objekt und einen Punktkoordinatenwert für den Test anzugeben. Der visuelle Objektparameter identifiziert den Ausgangspunkt in der visuellen Struktur für die Treffertestsuche. Wenn in der visuellen Struktur ein visuelles Objekt entdeckt wird, dessen Geometrie die Koordinaten aufweist, wird es auf die VisualHit-Eigenschaft eines HitTestResult-Objekts festgelegt. Das HitTestResult wird dann von der HitTest-Methode zurückgegeben. Wenn der Punkt in der visuellen Teilstruktur nicht enthalten ist, für die Sie den Treffertest durchführen, gibt HitTestnull zurück.

Tipp

Der Standardtreffertest gibt immer das oberste Objekt in der Z-Reihenfolge zurück. Wenn Sie alle visuellen Objekte identifizieren möchten (auch diejenigen, die teilweise oder vollständig verdeckt sind), verwenden Sie einen Treffertest-Ergebnisrückruf.

Der Koordinatenwert, den Sie als Punktparameter für die HitTest-Methode übergeben, muss relativ zum Koordinatenraum des visuellen Objekts sein, für das Sie den Treffertest durchführen. Wenn Sie beispielsweise visuelle Objekte geschachtelt haben, die im übergeordneten Koordinatenraum bei (100, 100) definiert sind, entspricht der Treffertest eines untergeordneten visuellen Objekts bei (0, 0) dem Treffertest bei (100, 100) im übergeordneten Koordinatenraum.

Der folgende Code veranschaulicht, wie Mausereignishandler für ein UIElement-Objekt eingerichtet werden, das zum Aufzeichnen von Ereignissen für den Treffertest dient.

// Respond to the left mouse button down event by initiating the hit test.
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    // Retrieve the coordinate of the mouse position.
    Point pt = e.GetPosition((UIElement)sender);

    // Perform the hit test against a given portion of the visual object tree.
    HitTestResult result = VisualTreeHelper.HitTest(myCanvas, pt);

    if (result != null)
    {
        // Perform action on hit visual object.
    }
}

So beeinflusst die visuelle Struktur den Treffertest

Der Startpunkt in der visuellen Struktur bestimmt, welche Objekte während der Treffertestenumeration der Objekte zurückgegeben werden. Wenn Sie für mehrere Objekte einen Treffertest durchführen möchten, muss das in der visuellen Struktur als Startpunkt verwendete Objekt das gemeinsame übergeordnete Element aller betroffenen Objekte sein. Wenn Sie beispielsweise sowohl für das Schaltflächenelement als auch für das visuelle Zeichnungsobjekt im folgenden Diagramm einen Treffertest durchführen möchten, müssen Sie den Startpunkt in der visuellen Struktur auf das gemeinsame übergeordnete Objekt für diese beiden Elemente festlegen. In diesem Fall ist das Canvas-Element das übergeordnete Objekt für das Schaltflächenelement und das visuelle Zeichnungsobjekt.

Diagramm der Hierarchie einer visuellen Struktur

Diagramm einer visuellen Strukturhierarchie

Tipp

Die IsHitTestVisible-Eigenschaft ruft einen Wert ab oder legt einen Wert fest, der deklariert, ob ein von UIElement abgeleitetes Objekt als Treffertestergebnis von einem Bereich seines gerenderten Inhalts zurückgegeben werden kann. Dadurch haben Sie die Möglichkeit, selektiv Änderungen an der visuellen Struktur vorzunehmen, um zu bestimmen, welche visuellen Objekte an einem Treffertest beteiligt sind.

Verwenden eines Treffertest-Ergebnisrückrufs

Sie können alle visuellen Objekte in einer visuellen Struktur auflisten, deren Geometrie einen angegebenen Koordinatenwert enthält. Dadurch können Sie alle visuellen Objekte identifizieren, auch diejenigen, die teilweise oder vollständig von anderen visuellen Objekten verdeckt sind. Um visuelle Objekte in einer visuellen Struktur aufzulisten, verwenden Sie die HitTest-Methode mit einer Treffertest-Rückruffunktion. Die Treffertest-Rückruffunktion wird vom System aufgerufen, wenn der von Ihnen angegebene Koordinatenwert in einem visuellen Objekt enthalten ist.

Während der Auflistung der Treffertestergebnisse sollten Sie keine Vorgänge ausführen, die die visuelle Struktur ändern. Das Hinzufügen oder Entfernen eines Objekts aus der visuellen Struktur, während diese durchlaufen wird, kann zu unvorhersehbarem Verhalten führen. Sie können die visuelle Struktur sicher ändern, nachdem die HitTest-Methode einen Wert zurückgegeben hat. Es kann sinnvoll sein, eine Datenstruktur anzugeben, beispielsweise eine ArrayList, um während der Auflistung der Treffertestergebnisse dort Werte zu speichern.

// Respond to the right mouse button down event by setting up a hit test results callback.
private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    // Retrieve the coordinate of the mouse position.
    Point pt = e.GetPosition((UIElement)sender);

    // Clear the contents of the list used for hit test results.
    hitResultsList.Clear();

    // Set up a callback to receive the hit test result enumeration.
    VisualTreeHelper.HitTest(myCanvas, null,
        new HitTestResultCallback(MyHitTestResult),
        new PointHitTestParameters(pt));

    // Perform actions on the hit test results list.
    if (hitResultsList.Count > 0)
    {
        Console.WriteLine("Number of Visuals Hit: " + hitResultsList.Count);
    }
}

Die Treffertest-Rückrufmethode definiert die Aktionen, die ausgeführt werden, wenn ein Treffertest für ein bestimmtes visuelles Objekt in der visuellen Struktur identifiziert wird. Nachdem diese Aktionen ausgeführt wurden, wird ein HitTestResultBehavior-Wert zurückgegeben, der bestimmt, ob die Auflistung weiterer vorhandener visueller Objekte fortgesetzt werden soll oder nicht.

// Return the result of the hit test to the callback.
public HitTestResultBehavior MyHitTestResult(HitTestResult result)
{
    // Add the hit test result to the list that will be processed after the enumeration.
    hitResultsList.Add(result.VisualHit);

    // Set the behavior to return visuals at all z-order levels.
    return HitTestResultBehavior.Continue;
}

Tipp

Die Auflistung der visuellen Objekttreffer erfolgt in Z-Reihenfolge. Das visuelle Objekt auf der obersten Z-Reihenfolgen-Ebene ist das erste aufgelistete Objekt. Alle anderen visuellen Objekte werden absteigend gemäß der Z-Reihenfolge aufgelistet. Diese Reihenfolge der Auflistung entspricht der Renderingreihenfolge der grafischen Elemente.

Sie können die Auflistung visueller Objekte mit der Treffertest-Rückruffunktion jederzeit anhalten, indem Sie Stop zurückgeben.

// Set the behavior to stop enumerating visuals.
return HitTestResultBehavior.Stop;

Verwenden eines Treffertestfilter-Rückrufs

Sie können einen optionalen Treffertestfilter verwenden, um die Objekte zu begrenzen, die an die Treffertestergebnisse weitergeleitet werden. Dadurch können Sie Teile der visuellen Struktur ignorieren, die nicht in Ihren Treffertestergebnissen verarbeitet werden sollen. Um einen Treffertestfilter zu implementieren, müssen Sie eine Treffertestfilter-Rückruffunktion definieren und als Parameterwert weitergeben, wenn Sie die HitTest-Methode aufrufen.

// Respond to the mouse wheel event by setting up a hit test filter and results enumeration.
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
    // Retrieve the coordinate of the mouse position.
    Point pt = e.GetPosition((UIElement)sender);

    // Clear the contents of the list used for hit test results.
    hitResultsList.Clear();

    // Set up a callback to receive the hit test result enumeration.
    VisualTreeHelper.HitTest(myCanvas,
                      new HitTestFilterCallback(MyHitTestFilter),
                      new HitTestResultCallback(MyHitTestResult),
                      new PointHitTestParameters(pt));

    // Perform actions on the hit test results list.
    if (hitResultsList.Count > 0)
    {
        ProcessHitTestResultsList();
    }
}

Wenn Sie die optionale Treffertestfilter-Rückruffunktion nicht angeben möchten, übergeben Sie einen null-Wert als Parameter für die HitTest-Methode.

// Set up a callback to receive the hit test result enumeration,
// but no hit test filter enumeration.
VisualTreeHelper.HitTest(myCanvas,
                  null,  // No hit test filtering.
                  new HitTestResultCallback(MyHitTestResult),
                  new PointHitTestParameters(pt));

Verringern der Verzweigungen in einer visuellen Struktur

Verzweigen einer visuellen Struktur mit einem Treffertestfilter

Die Treffertestfilter-Rückruffunktion gestattet Ihnen, alle visuellen Objekte aufzulisten, deren gerenderte Inhalte die von Ihnen angegebenen Koordinaten enthalten. Sie können jedoch auch bestimmte Verzweigungen der visuellen Struktur ignorieren, die im Rahmen Ihrer Treffertestergebnis-Rückruffunktion nicht verarbeitet werden sollen. Der Rückgabewert der Treffertestfilter-Rückruffunktion bestimmt, welcher Typ von Aktion von der Auflistung der visuellen Objekte ausgeführt werden soll. Wenn beispielsweise der Wert ContinueSkipSelfAndChildren zurückgegeben wird, können Sie das aktuelle visuelle Objekt und seine untergeordneten Elemente aus der Auflistung der Treffertestergebnisse entfernen. Dies bedeutet, dass für die Treffertestergebnis-Rückruffunktion diese Objekte nicht in der Auflistung enthalten sind. Durch das Verringern der Verzweigungen in der visuellen Struktur von Objekten wird der Verarbeitungsaufwand während der Übergabe der Auflistung von Treffertestergebnissen verringert. Im folgenden Codebeispiel überspringt der Filter Bezeichnungen und ihre Nachfolgerelemente und führt für alle anderen Elemente Treffertests durch.

// Filter the hit test values for each object in the enumeration.
public HitTestFilterBehavior MyHitTestFilter(DependencyObject o)
{
    // Test for the object value you want to filter.
    if (o.GetType() == typeof(Label))
    {
        // Visual object and descendants are NOT part of hit test results enumeration.
        return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
    }
    else
    {
        // Visual object is part of hit test results enumeration.
        return HitTestFilterBehavior.Continue;
    }
}

Tipp

Der Treffertestfilter-Rückruf wird gelegentlich aufgerufen, wenn der Treffertestergebnis-Rückruf nicht aufgerufen wird.

Überschreiben des Standardtreffertests

Sie können die Unterstützung des Standardtreffertests für ein visuelles Objekt überschreiben, indem Sie die HitTestCore-Methode überschreiben. In diesem Fall wird beim Aufrufen der HitTest-Methode die überschriebene Implementierung von HitTestCore aufgerufen. Ihre überschriebene Methode wird aufgerufen, wenn sich ein Treffertest innerhalb des umgebenden Rechtecks für das visuelle Objekt befindet. Dies gilt auch dann, wenn die Koordinate außerhalb des gerenderten Inhalts des visuellen Objekts liegt.

// Override default hit test support in visual object.
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
    Point pt = hitTestParameters.HitPoint;

    // Perform custom actions during the hit test processing,
    // which may include verifying that the point actually
    // falls within the rendered content of the visual.

    // Return hit on bounding rectangle of visual object.
    return new PointHitTestResult(this, pt);
}

Es kann vorkommen, dass Sie einen Treffertest sowohl für das umschließende Rechteck als auch für den gerenderten Inhalt eines visuellen Objekts durchführen möchten. Indem Sie den PointHitTestParameters-Parameterwert in der überschriebenen HitTestCore-Methode als Parameter für die Basismethode HitTestCore verwenden, können Sie basierend auf einem Treffer für das umschließende Rechteck eines visuellen Objekts Aktionen ausführen und anschließend einen zweiten Treffertest für den gerenderten Inhalt des visuellen Objekts vornehmen.

// Override default hit test support in visual object.
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
    // Perform actions based on hit test of bounding rectangle.
    // ...

    // Return results of base class hit testing,
    // which only returns hit on the geometry of visual objects.
    return base.HitTestCore(hitTestParameters);
}

Siehe auch

Aufgaben

Beispiel für Treffertests mit "DrawingVisuals"

Beispiel für Treffertests mit Win32-Interoperabilität

Gewusst wie: Treffertest für eine Geometrie in einem visuellen Objekt

Gewusst wie: Treffertest mithilfe eines Win32-Hostcontainers

Referenz

HitTest

HitTestResult

HitTestResultCallback

HitTestFilterCallback

IsHitTestVisible