Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Toto téma obsahuje přehled funkcí testování, které poskytuje vizuální vrstva. Podpora testování hitů umožňuje určit, zda geometrie nebo bodová hodnota spadá do vykresleného obsahu objektu Visual, který umožňuje implementovat chování uživatelského rozhraní, jako je obdélník výběru pro výběr více objektů.
Scénáře testování hitů
Třída UIElement poskytuje metodu InputHitTest , která umožňuje použít test proti prvku pomocí dané souřadnicové hodnoty. V mnoha případech poskytuje metoda InputHitTest požadovanou funkčnost pro implementaci testování zásahů do prvků. Existuje však několik scénářů, kdy může být potřeba implementovat detekci kolize ve vizuální vrstvě.
Testování zásahů na objektech, které nejsouUIElement: Toto platí, pokud testujete zásahy do objektůUIElement, které nejsou objekty, jako například DrawingVisual nebo grafické objekty.
Testování pomocí geometrie: To platí, pokud potřebujete použít test pomocí objektu geometrie, nikoli souřadnicové hodnoty bodu.
Testování s více objekty: To platí, pokud potřebujete testovat na více objektech, například překrývající se objekty. Můžete získat výsledky pro všechny vizuály protínající geometrii nebo bod, ne jenom první vizuál.
Ignorování UIElement zásad testování: To platí, když potřebujete ignorovat zásady testování hitů UIElement , které berou v úvahu takové faktory, jako je to, jestli je prvek zakázaný nebo neviditelný.
Poznámka:
Kompletní vzorový kód ilustrující hit testování ve vizuální vrstvě najdete v Hit Test Using DrawingVisuals Sample a Hit Test with Win32 Interoperation Sample.
Podpora testování detekce zásahů
Účelem HitTest metod ve VisualTreeHelper třídě je určit, zda je hodnota souřadnic geometrie nebo bodu v rámci vykresleného obsahu daného objektu, například ovládací prvek nebo grafický prvek. Pomocí testování stiskem můžete například určit, jestli kliknutí myší v ohraničujícím obdélníku objektu spadá do geometrie kruhu. Můžete se také rozhodnout, že přepíšete výchozí implementaci testování hitů a provedete vlastní výpočty testů hitů.
Následující obrázek znázorňuje vztah mezi neúhelníkovou oblastí objektu a jeho ohraničující obdélník.
Diagram platné oblasti testu kolize
Testování prokliků a pořadí Z-os
Vizuální vrstva WPF (Windows Presentation Foundation) podporuje testování zásahů proti všem objektům pod bodem nebo geometrií, nejen nejvrchnějším objektem. Výsledky jsou vráceny v z-pořadí. Nicméně vizuální objekt, který předáte jako parametr metodě HitTest, určuje, která část vizuálního stromu bude podrobena testu zásahu. Můžete provádět testování proti celému vizuálnímu stromu nebo libovolné jeho části.
Na následujícím obrázku je objekt kruhu nad čtvercovými i trojúhelníkovými objekty. Pokud vás zajímá pouze testování vizuálního objektu, jehož hodnota v pořadí zobrazení je nejvyšší, můžete nastavit, aby výčet vizuálních testů vrátil hodnotu Stop z HitTestResultCallback a tím zastavil procházení testu po první položce.
Diagram z-řazení vizuálního stromu
Chcete-li vyjmenovat všechny vizuální objekty pod konkrétním bodem nebo geometrií, vraťte Continue z HitTestResultCallback. To znamená, že můžete použít test vizuálních objektů, které jsou pod jinými objekty, i když jsou zcela nejasné. Další informace najdete v ukázkovém kódu v části "Použití zpětného volání výsledků testu přístupů".
Poznámka:
Test lze provést také u vizuálního objektu, který je transparentní.
Použití výchozího testování hitů
Pomocí metody můžete určit, zda je bod v geometrii vizuálního objektu, pomocí HitTest metody určit vizuální objekt a hodnotu souřadnic bodu, která se má testovat. Parametr vizuálního objektu identifikuje výchozí bod ve vizuálním stromu pro hledání pomocí hit testu. Pokud je ve vizuálním stromu nalezen vizuální objekt, jehož geometrie obsahuje souřadnici, je nastaven jako vlastnost objektu VisualHit.
HitTestResult se pak vrátí z metody HitTest. Pokud bod není obsažen v podsíňovém vizuálu, který testujete, HitTest vrátí hodnotu null
.
Poznámka:
Výchozí testování zásahu vždy vrátí objekt nejvýše umístěný v pořadí na ose z. K identifikaci všech vizuálních objektů, i těch, které mohou být částečně nebo zcela zakryté, použijte zpětné volání výsledku testu zásahu.
Hodnota souřadnice, kterou předáte jako parametr bodu pro metodu HitTest, musí být relativní ke souřadnicovému prostoru vizuálního objektu, proti kterému testujete. Pokud máte například vnořené vizuální objekty definované na (100, 100) v souřadnicovém prostoru nadřazeného objektu, je výsledek testování podřízeného vizuálu na (0, 0) ekvivalentní k dosažení testování (100, 100) v souřadnicovém prostoru nadřazeného objektu.
Následující kód ukazuje, jak nastavit obslužné rutiny událostí myši pro UIElement objekt, který se používá k zaznamenání událostí používaných k testování hitů.
// 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
Vliv vizuálního stromu na testování hitů
Výchozí bod ve stromu vizuálů určuje, které objekty se vrátí během testu vyhodnocení a vyčítání objektů. Pokud máte více objektů, které chcete testovat, musí být vizuální objekt použitý jako výchozí bod ve vizuálním stromu společným nadřazeným prvkem všech objektů, které vás zajímají. Pokud byste například chtěli otestovat prvek tlačítka i vizuál kreslení v následujícím diagramu, museli byste nastavit výchozí bod ve vizuálním stromu na společný nadřazený prvek obojího. V tomto případě je prvek plátna společným nadřazeným prvkem prvku tlačítka i vizuálu výkresu.
Diagram hierarchie vizuální stromové struktury
Poznámka:
Vlastnost IsHitTestVisible získává nebo nastavuje hodnotu, která deklaruje, zda může být UIElement-odvozený objekt vrácen jako výsledek z testu zasáhnutí z určité části jeho vykresleného obsahu. To vám umožňuje změnit vizuální strom selektivně a určit, které vizuální objekty jsou součástí testu zasažení.
Použití zpětného volání výsledku testu úderu
Můžete vytvořit výčet všech vizuálních objektů ve stromu vizuálu, jehož geometrie obsahuje zadanou hodnotu souřadnic. To vám umožní identifikovat všechny vizuální objekty, i ty, které mohou být částečně nebo zcela zakryté jinými vizuálními objekty. Pro vytvoření výčtu vizuálních objektů ve stromu vizuálních prvků použijte metodu HitTest s funkcí zpětného volání hit testu. Funkce zpětného volání testu zásahu je volána systémem, když hodnota souřadnic, kterou zadáte, je obsažena ve vizuálním objektu.
Během výčtu výsledků testu byste neměli provádět žádnou operaci, která upravuje strom vizuálu. Přidání nebo odebrání objektu z vizuálního stromu během procházení může způsobit nepředvídatelné chování. Po vrácení z metody HitTest můžete bezpečně upravit vizuální strom. Můžete chtít zadat datovou strukturu, například ArrayList, pro uložení hodnot během výčtu výsledků testu.
// 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
Metoda zpětného volání testu zásahu definuje akce, které provedete, když je test zásahu identifikován u konkrétního vizuálního objektu ve vizuálním stromu. Po provedení akcí vrátíte HitTestResultBehavior hodnotu, která určuje, zda pokračovat v výčtu jiných vizuálních objektů, nebo ne.
// 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
Poznámka:
Pořadí výčtu zásahových vizuálních objektů je určeno z-pořadím. Vizuální objekt na nejvyšší úrovni vykreslovacího pořadí je prvním objektem, který je vyčíslen. Všechny ostatní vizuální objekty, které jsou vyjmenované, jsou na nižší hladině z-řazení. Toto pořadí výčtu odpovídá pořadí vykreslování vizuálů.
Výčty vizuálních objektů můžete kdykoli zastavit v funkci zpětného volání hit test vrácením Stop.
// Set the behavior to stop enumerating visuals.
return HitTestResultBehavior.Stop;
' Set the behavior to stop enumerating visuals.
Return HitTestResultBehavior.Stop
Použití zpětného volání zkušebního filtru zásahu
Pomocí volitelného filtru testu zasáhnutí můžete omezit objekty, které jsou v rámci výsledků testu zohledněny. To vám umožní ignorovat části vizuálního stromu, které vás nezajímají při zpracování výsledků testu. Pokud chcete implementovat filtr testu, definujete funkci zpětného volání filtru testu a při volání metody ji předáte jako hodnotu parametru HitTest .
// 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
Pokud nechcete zadat volitelnou funkci zpětného volání filtru pro test zasažení, předejte jako jeho parametr pro metodu null
hodnotu HitTest.
// 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.
Prořezávání vizuálního stromu
Funkce zpětného volání filtru hitů testu umožňuje zobrazit výčet všech vizuálů, jejichž vykreslený obsah obsahuje zadané souřadnice. Můžete ale chtít ignorovat určité větve vizuálního stromu, které vás nezajímají pro zpracování ve vaší funkci zpětného volání výsledků testu. Návratová hodnota funkce zpětného volání filtru testu zasáhnutí určuje, jaký typ akce má být provedený při vyčíslení objektů vizuálu. Pokud například vrátíte hodnotu, ContinueSkipSelfAndChildrenmůžete z výčtu výsledků testu odebrat aktuální objekt vizuálu a jeho podřízené položky. To znamená, že zpětná volací funkce výsledků testu zásahu neuvidí tyto objekty ve svém výčtu. Vyřazení vizuálního stromu objektů snižuje množství zpracování během úspěšného testu – výčet výsledků testu. V následujícím příkladu kódu filtr přeskočí popisky a jejich potomky a dosáhne testů všeho ostatního.
// 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
Poznámka:
Zpětné volání filtru testu úspěšnosti se někdy volá v případech, kdy není voláno zpětné volání výsledků testu úspěšnosti.
Přepsání výchozího testování hitů
Výchozí podporu testování zásahu vizuálního objektu můžete změnit přepsáním metody HitTestCore. To znamená, že když vyvoláte metodu HitTest, je volána vaše přepsaná implementace HitTestCore. Vaše přepsaná metoda je volána, když hit test spadá do ohraničujícího obdélníku vizuálního objektu, i když souřadnice spadají mimo vykresleného obsahu vizuálního objektu.
// 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
Někdy můžete chtít provést hit test jak na ohraničující rámeček, tak na vykreslený obsah vizuálního objektu. Pomocí hodnoty parametru PointHitTestParameters
v přepsané metodě HitTestCore jako parametru základní metody HitTestCore, můžete provádět akce na základě zásahu ohraničujícího obdélníku vizuálního objektu, a potom provést druhý test zásahu na vykreslený obsah vizuálního objektu.
// 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
Viz také
.NET Desktop feedback