Megosztás a következőn keresztül:


Érintési tesztelés a vizuális rétegben

Ez a témakör áttekintést nyújt a vizuális réteg által biztosított találattesztelési funkciókról. A találattesztelés támogatása lehetővé teszi annak megállapítását, hogy egy geometria vagy pont értéke egy Visualrenderelt tartalmába tartozik-e, lehetővé téve a felhasználói felület viselkedésének implementálását, például egy kijelölési téglalapot több objektum kijelöléséhez.

Ütközésvizsgálati forgatókönyvek

A UIElement osztály biztosítja a InputHitTest metódust, amely lehetővé teszi, hogy egy adott koordináta-érték használatával teszteljen egy elemet. A InputHitTest metódus sok esetben biztosítja az elemek találattesztelésének implementálásához szükséges funkciókat. Azonban több forgatókönyv is létezik, amelyekben előfordulhat, hogy a vizualizációs rétegen kell implementálnia a találattesztelést.

  • NemUIElement objektumokon végzett tesztelés: Ez akkor érvényes, ha nemUIElement objektumokat, például DrawingVisual vagy grafikus objektumokat tesztel.

  • Találat tesztelése geometria használatával: Ez akkor érvényes, ha egy pont koordináta-értéke helyett egy geometriai objektum használatával kell elvégeznie a találat tesztelést.

  • Több objektumon végzett ütközésvizsgálat: Ez akkor alkalmazandó, ha több objektumon, például átfedésben lévő objektumokon kell ütközésvizsgálatot végeznie. Az összes geometriát vagy pontot metsző vizualizáció eredményeit lekérheti, nem csak az elsőt.

  • Amikor figyelmen kívül kell hagyni a UIElement találatteszti direktívát: Ez akkor alkalmazandó, ha nem veszi figyelembe a UIElement találatteszti direktívát, amely például azt vizsgálja meg, hogy egy elem le van-e tiltva vagy láthatatlan.

Megjegyzés:

A vizuális rétegen végzett találattesztelést szemléltető teljes kódmintát a Hit Test using DrawingVisuals Sample és Hit Test with Win32 Interoperation Samplecímű témakörben talál.

Ütközésvizsgálati támogatás

A HitTest osztály VisualTreeHelper metódusainak célja annak meghatározása, hogy egy geometria- vagy pontkoordináta-érték egy adott objektum renderelt tartalmán belül van-e, például vezérlő vagy grafikus elem. A találattesztelés használatával például megállapíthatja, hogy egy egérkattintás az objektum határoló téglalapján belül, egy kör geometriáján belül esik-e. Dönthet úgy is, hogy felülbírálja a találattesztelés alapértelmezett implementációját a saját egyéni találatteszt-számítások elvégzéséhez.

Az alábbi ábra egy nem téglalap alakú objektum régiója és határoló téglalapja közötti kapcsolatot mutatja be.

Érvényes találati tesztrégió diagramja
Érvényes érintési tesztterület diagramja

Tesztelés és Z-sorrend elérése

A Windows Presentation Foundation (WPF) vizualizációs réteg támogatja a pont vagy geometria alatti összes objektumon végzett találattesztelést, nem csak a legfelső objektumon. Az eredmények z-sorrendben jelennek meg. A HitTest metódus paramétereként átadott vizualizációobjektum azonban meghatározza a vizualizációfa azon részét, amelyet tesztelni fog. A teljes vizualizációfát vagy annak bármely részét tesztelheti.

Az alábbi ábrán a kör objektum a négyzet és a háromszög objektum tetején található. Ha csak annak a vizuális objektumnak szeretné tesztelni a találatát, amelynek z-rend értéke a legmagasabb, beállíthatja a vizuális találatteszt listázását úgy, hogy az első elem után a Stop a HitTestResultCallback-nél leálljon a bejárás.

Vizuális fa z-sorrendjének diagramja
Vizualizációfa z-sorrendjének diagramja

Ha az összes vizuális objektumot egy adott pont vagy geometria alatt szeretné számba venni, adja vissza a Continue-t a HitTestResultCallback-ből. Ez azt jelenti, hogy a más objektumok alatt lévő vizuális objektumok tesztelését akkor is elvégezheti, ha azok teljesen el vannak fedve. További információért tekintse meg a "Találatteszt eredményeinek visszahívása" című szakasz mintakódját.

Megjegyzés:

Az átlátszó vizualizációs objektumok is tesztelhetők.

Alapértelmezett találattesztelés használata

Egy pontnak egy vizuális objektum geometriáján belüli elhelyezkedését a HitTest metódussal azonosíthatja, amelyet egy vizuális objektum és egy pontkoordináta-érték tesztelésére használ. A vizuális objektum paramétere azonosítja a találati teszt keresésének kezdőpontját a vizuális fában. Ha olyan vizualizációs objektum található a vizualizációfán, amelynek geometriája tartalmazza a koordinátát, akkor az egy VisualHit objektum HitTestResult tulajdonságára van állítva. A HitTestResult ezután visszaadódik a HitTest metódusból. Ha a pont nem található abban a vizuális al-fában, amelyen találatvizsgálatot végzünk, akkor a HitTest a nullértéket adja vissza.

Megjegyzés:

Az alapértelmezett találattesztelés mindig a z sorrendben lévő legfelső objektumot adja vissza. Az összes vizuális objektum azonosításához , még azokat is, amelyek részben vagy teljesen elhomályosulhatnak, használjon találati teszteredmény-visszahívást.

A HitTest metódus pontparamétereként átadott koordináta értékének a vizuális objektum koordinátarendszeréhez kell viszonyulnia, amelyen ütközéstesztet végez. Ha például a szülő koordinátaterületén a (100, 100) helyen beágyazott vizuális objektumok vannak meghatározva, akkor egy gyermekvizuális tesztelése a (0, 0) helyen egyenértékű azzal, mintha a szülő koordinátaterületén a (100, 100) pozíciót tesztelnénk.

Az alábbi kód bemutatja, hogyan állíthat be egéresemény-kezelőket egy UIElement objektumhoz, amely a találatteszteléshez használt események rögzítésére szolgál.

// 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.
    }
}
' Respond to the left mouse button down event by initiating the hit test.
Private Overloads Sub OnMouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    ' Retrieve the coordinate of the mouse position.
    Dim pt As Point = e.GetPosition(CType(sender, UIElement))

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

    If result IsNot Nothing Then
        ' Perform action on hit visual object.
    End If
End Sub

A vizualizációfa hatása a találatok tesztelésére

A vizualizációfa kiindulási pontja határozza meg, hogy mely objektumokat adja vissza a rendszer az objektumok találattesztjének számbavétele során. Ha több objektumot szeretne tesztelni, a vizuális fa kiindulópontjaként használt vizuális objektumnak az összes objektum közös ősének kell lennie. Ha például a gombelemet és a rajzvizualizációt is tesztelni szeretné az alábbi ábrán, akkor a vizualizációfában a kiindulási pontot mindkettő közös elődjének kell beállítania. Ebben az esetben a vászonelem a gombelem és a rajzvizualizáció közös őse.

vizuális fa hierarchia diagramja
A vizuális fa hierarchiájának diagramja

Megjegyzés:

A IsHitTestVisible tulajdonság egy olyan értéket kap vagy állít be, amely deklarálja, hogy egy UIElement-származtatott objektum visszaadható-e találati teszt eredményként a renderelt tartalom bizonyos részeiből. Ez lehetővé teszi, hogy szelektíven módosítsa a vizualizációfát annak megállapításához, hogy mely vizuális objektumok vesznek részt a találati tesztekben.

Találatteszt eredményének visszahívása

Számba vehet minden vizualizációs objektumot egy vizualizációfán, amelynek geometriája megadott koordinátaértéket tartalmaz. Ez lehetővé teszi az összes vizuális objektum azonosítását, még azokat is, amelyeket részben vagy teljesen elfedhetnek más vizuális objektumok. A vizuális fa objektumainak felsorolásához használja a HitTest metódust egy ütközésvizsgálati visszahívási függvénnyel. A találatteszt visszahívási függvényt a rendszer hívja meg, ha a megadott koordináta-érték egy vizualizációobjektumban található.

A találati teszt eredményeinek számbavétele során ne végezzen olyan műveletet, amely módosítja a vizuális fát. Egy objektum hozzáadása vagy eltávolítása a vizualizációfáról bejárás közben kiszámíthatatlan viselkedést eredményezhet. A vizualizációfát a HitTest metódus visszatérése után nyugodtan módosíthatja. Előfordulhat, hogy olyan adatstruktúrát szeretne megadni, például egy ArrayList, amely értékek tárolására szolgál a találati teszt eredményeinek számbavétele során.

// 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);
    }
}
' Respond to the right mouse button down event by setting up a hit test results callback.
Private Overloads Sub OnMouseRightButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
    ' Retrieve the coordinate of the mouse position.
    Dim pt As Point = e.GetPosition(CType(sender, UIElement))

    ' 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, Nothing, New HitTestResultCallback(AddressOf MyHitTestResult), New PointHitTestParameters(pt))

    ' Perform actions on the hit test results list.
    If hitResultsList.Count > 0 Then
        Console.WriteLine("Number of Visuals Hit: " & hitResultsList.Count)
    End If
End Sub

A találati teszt visszahívási metódusa határozza meg azokat a műveleteket, amelyeket akkor hajt végre, amikor egy találati tesztet egy adott vizualizációs objektumon azonosít a vizualizációfán. A műveletek végrehajtása után egy HitTestResultBehavior értéket ad vissza, amely meghatározza, hogy folytatja-e a többi vizualizációs objektum számbavételét.

// 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;
}
' Return the result of the hit test to the callback.
Public Function MyHitTestResult(ByVal result As HitTestResult) As HitTestResultBehavior
    ' 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
End Function

Megjegyzés:

A találati vizuális objektumok felsorolási sorrendje a z-sorrend szerint történik. A legtöbb z-order szinten lévő vizualizációs objektum az első számbavételi objektum. Az enumerált egyéb vizualizációs objektumok z-sorrendben csökkenő szinten vannak. Ez az enumerálási sorrend a vizualizációk renderelési sorrendjének felel meg.

A vizualizációs objektumok számbavételét bármikor leállíthatja a hit test callback függvényben a Stopvisszaadásával.

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

Hit Test Filter Callback használata

Opcionális találatteszt-szűrővel korlátozhatja a találati teszt eredményeinek átadott objektumokat. Ez lehetővé teszi, hogy figyelmen kívül hagyja a vizuális fa azon részeit, amelyeket nem kíván feldolgozni a találati teszt eredményei során. A találatteszt-szűrő implementálásához meg kell határoznia egy találati tesztszűrő visszahívási függvényét, és paraméterértékként kell átadnia, amikor meghívja a HitTest metódust.

// 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();
    }
}
' Respond to the mouse wheel event by setting up a hit test filter and results enumeration.
Private Overloads Sub OnMouseWheel(ByVal sender As Object, ByVal e As MouseWheelEventArgs)
    ' Retrieve the coordinate of the mouse position.
    Dim pt As Point = e.GetPosition(CType(sender, UIElement))

    ' 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(AddressOf MyHitTestFilter), New HitTestResultCallback(AddressOf MyHitTestResult), New PointHitTestParameters(pt))

    ' Perform actions on the hit test results list.
    If hitResultsList.Count > 0 Then
        ProcessHitTestResultsList()
    End If
End Sub

Ha nem szeretné megadni az opcionális találati tesztszűrő visszahívási függvényét, adjon meg egy null értéket a HitTest metódus paramétereként.

// 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));
' Set up a callback to receive the hit test result enumeration,
' but no hit test filter enumeration.
VisualTreeHelper.HitTest(myCanvas, Nothing, New HitTestResultCallback(AddressOf MyHitTestResult), New PointHitTestParameters(pt)) ' No hit test filtering.

Vizualizációfa metszése találattesztszűrővel
Vizualizációfa metszése

A találati tesztszűrő visszahívási függvénye lehetővé teszi az összes vizuális elem felsorolását, amelynek renderelt tartalma tartalmazza a megadott koordinátákat. Előfordulhat azonban, hogy figyelmen kívül szeretné hagyni a vizualizációfa egyes ágait, amelyeket nem szeretne feldolgozni a találati teszteredmények visszahívási függvényében. A találati tesztszűrő visszahívási függvényének visszatérési értéke határozza meg, hogy milyen típusú műveletet kell elvégeznie a vizualizációobjektumok számbavételének. Ha például a ContinueSkipSelfAndChildrenértéket adja vissza, eltávolíthatja az aktuális vizuális objektumot és annak gyermekeit a találati teszt eredmények listájából. Ez azt jelenti, hogy a találati teszt eredményeinek visszahívási függvénye nem látja ezeket az objektumokat a felsorolásában. Az objektumok vizuális fájának egyszerűsítése csökkenti a feldolgozás mennyiségét a találati teszt eredményeinek feldolgozása során. A következő kód példában a szűrő kihagyja a címkéket és azok leszármazottait, és minden mást tesztel.

// 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;
    }
}
' Filter the hit test values for each object in the enumeration.
Public Function MyHitTestFilter(ByVal o As DependencyObject) As HitTestFilterBehavior
    ' Test for the object value you want to filter.
    If o.GetType() Is GetType(Label) Then
        ' 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
    End If
End Function

Megjegyzés:

Előfordulhat, hogy a találatvizsgálati szűrő visszahívását meghívják olyan esetekben, amikor a találatvizsgálati eredmények visszahívása nem történik meg.

Alapértelmezett ütközésvizsgálat felülírása

Felülbírálhatja egy vizualizáció objektum alapértelmezett találattesztelési támogatását a HitTestCore metódus felülbírálásával. Ez azt jelenti, hogy amikor meghívja a HitTest metódust, a rendszer meghívja a HitTestCore felülírt implementációját. A felülbírált metódus akkor kerül meghívásra, ha egy találatvizsgálat a vizuális objektum határoló téglalapjára esik, még akkor is, ha a koordináta a vizuális objektum renderelt tartalmán kívül esik.

// 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);
}
' Override default hit test support in visual object.
Protected Overrides Overloads Function HitTestCore(ByVal hitTestParameters As PointHitTestParameters) As HitTestResult
    Dim pt As Point = 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(Me, pt)
End Function

Előfordulhat, hogy egy vizuális objektum határoló téglalapjára és renderelt tartalmára is ütközésvizsgálatot szeretne végezni. Ha a felülbírált PointHitTestParameters metódus HitTestCore paraméterértékét az alapmetódus HitTestCoreparamétereként használja, akkor végrehajthat műveleteket egy vizuális objektum határoló téglalapjának találata alapján, majd elvégezhet egy második találati tesztet a vizuális objektum renderelt tartalmán.

// 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);
}
' Override default hit test support in visual object.
Protected Overrides Overloads Function HitTestCore(ByVal hitTestParameters As PointHitTestParameters) As HitTestResult
    ' 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 MyBase.HitTestCore(hitTestParameters)
End Function

Lásd még