Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questo argomento viene fornita una panoramica delle funzionalità di hit testing fornite dal livello visivo. Il supporto di hit testing consente di determinare se un valore di geometria o punto rientra nel contenuto renderizzato di un Visual, permettendo di implementare comportamenti dell'UI come un rettangolo di selezione per selezionare più oggetti.
Scenari di verifica delle collisioni
La UIElement classe fornisce il InputHitTest metodo , che consente di eseguire il hit test su un elemento usando un determinato valore di coordinata. In molti casi, il InputHitTest metodo fornisce la funzionalità desiderata per l'implementazione di hit testing di elementi. Esistono tuttavia diversi scenari in cui potrebbe essere necessario implementare hit testing a livello visivo.
Hit testing su oggetti nonUIElement : questo vale se si esegue il hit testing di oggetti nonUIElement , ad esempio DrawingVisual o oggetti grafici.
Hit testing usando una geometria: questo vale se è necessario eseguire un hit test usando un oggetto di geometria anziché il valore di coordinata di un punto.
Hit testing su più oggetti: questo vale quando è necessario eseguire il hit test su più oggetti, ad esempio oggetti sovrapposti. È possibile ottenere risultati per tutti gli elementi visivi che si intersecano con una geometria o un punto, non solo per il primo.
Questo si applica quando è necessario ignorare i criteri di hit testing UIElement, che considerano fattori come se un elemento è disabilitato o invisibile UIElement.
Annotazioni
Per un esempio di codice completo che illustra il test di impatto a livello visivo, vedere Esempio di Hit Test usando DrawingVisuals e Esempio di Hit Test con interoperabilità Win32.
Supporto per il rilevamento delle interazioni
Lo scopo dei metodi HitTest della classe VisualTreeHelper è determinare se un valore di coordinata di geometria o punto sia contenuto nel contenuto reso di un determinato oggetto, come un controllo o un elemento grafico. Ad esempio, è possibile usare hit testing per determinare se un clic del mouse all'interno del rettangolo di delimitazione di un oggetto rientra nella geometria di un cerchio. È anche possibile scegliere di eseguire l'override dell'implementazione predefinita di hit testing per eseguire calcoli personalizzati di hit test.
La figura seguente mostra la relazione tra l'area di un oggetto non rettangolare e il relativo rettangolo di delimitazione.
Diagramma dell'area di hit test valida
Hit Testing e ordine Z
Il livello visivo Windows Presentation Foundation (WPF) supporta il hit testing su tutti gli oggetti in un punto o in una geometria, non solo l'oggetto più in alto. I risultati vengono restituiti in ordine z. Tuttavia, l'oggetto visivo passato come parametro al metodo HitTest determina quale parte della struttura ad albero visuale sarà sottoposta a hit test. È possibile eseguire un hit test sull'intera struttura ad albero visuale o su qualsiasi parte di essa.
Nell'illustrazione seguente, l'oggetto circle si trova sopra gli oggetti quadrati e triangoli. Se si è interessati solo a eseguire il test di colpo sull'oggetto visivo il cui valore nella z-order è il più alto, è possibile impostare l'enumerazione del test di hit visivo per restituire Stop da HitTestResultCallback, arrestando l'attraversamento del test di hit dopo il primo elemento.
Diagramma dell'ordine z di una struttura ad albero visuale
Se si desidera enumerare tutti gli oggetti visivi in un punto o una geometria specifica, restituire Continue da HitTestResultCallback. Ciò significa che è possibile eseguire il hit test per gli oggetti visivi che si trovano sotto altri oggetti, anche se sono completamente nascosti. Per ulteriori informazioni, vedere il codice di esempio nella sezione "Utilizzare un callback dei risultati di hit test".
Annotazioni
Un oggetto visivo trasparente può anche essere sottoposto a un test di interazione.
Uso del testing di impatto predefinito
È possibile identificare se un punto si trova all'interno della geometria di un oggetto visivo utilizzando il HitTest metodo per specificare un oggetto visivo e un valore di coordinata punto su cui eseguire il test. Il parametro dell'oggetto visivo identifica il punto iniziale nella struttura ad albero visuale per la ricerca di hit test. Se un oggetto visivo viene trovato nella struttura ad albero visuale la cui geometria contiene la coordinata, viene impostata sulla VisualHit proprietà di un HitTestResult oggetto . Viene HitTestResult quindi restituito dal HitTest metodo . Se il punto non è contenuto nell'albero visuale secondario su cui viene eseguito il hit testing, HitTest restituisce null.
Annotazioni
Il hit testing predefinito restituisce sempre l'oggetto più in alto nell'ordine z. Per identificare tutti gli oggetti visivi, anche quelli che possono essere parzialmente o completamente nascosti, usare un callback dei risultati dell'hit test.
Il valore della coordinata passato come parametro punto per il HitTest metodo deve essere relativo allo spazio delle coordinate dell'oggetto visivo su cui si esegue il hit testing. ** Ad esempio, se sono stati definiti oggetti visivi annidati a (100, 100) nello spazio delle coordinate dell'elemento padre, il test di impatto di un oggetto visivo figlio a (0, 0) equivale a un test di impatto a (100, 100).
Nel codice seguente viene illustrato come configurare i gestori eventi del mouse per un UIElement oggetto usato per acquisire gli eventi usati per l'hit testing.
// 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
Come la struttura ad albero visuale influenza l'hit testing
Il punto iniziale nella struttura ad albero visuale determina quali oggetti vengono restituiti durante l'enumerazione hit test degli oggetti. Se si desidera eseguire il hit test di più oggetti, l'oggetto visivo usato come punto iniziale nella struttura ad albero visuale deve essere il predecessore comune di tutti gli oggetti di interesse. Ad esempio, se si è interessati a eseguire hit testing sia sul pulsante che sul disegno visivo nel diagramma seguente, è necessario impostare il punto iniziale nell'albero visivo sull'antenato comune di entrambi. In questo caso, l'elemento canvas è l'antenato comune sia dell'elemento pulsante che del componente visivo del disegno.
Diagramma di una gerarchia ad albero visuale
Annotazioni
La proprietà IsHitTestVisible ottiene o imposta un valore che dichiara se un oggetto derivato da UIElement può essere restituito come risultato di un test di impatto da una parte del suo contenuto sottoposto a rendering. In questo modo è possibile modificare in modo selettivo la struttura ad albero visuale per determinare quali oggetti visivi sono coinvolti in un hit test.
Uso di un callback dei risultati di hit test
È possibile enumerare tutti gli oggetti visivi in una struttura ad albero visuale la cui geometria contiene un valore di coordinata specificato. In questo modo è possibile identificare tutti gli oggetti visivi, anche quelli parzialmente o completamente nascosti da altri oggetti visivi. Per enumerare gli oggetti visivi in un albero visuale, utilizzare il metodo HitTest con una funzione di callback per il rilevamento di collisioni. La funzione di callback di hit test viene chiamata dal sistema quando il valore di coordinata specificato è contenuto in un oggetto visivo.
Durante l'enumerazione dei risultati dell'hit test, non è consigliabile eseguire alcuna operazione che modifica la struttura ad albero visuale. L'aggiunta o la rimozione di un oggetto dalla struttura ad albero visuale durante l'attraversamento può comportare un comportamento imprevedibile. È possibile modificare in modo sicuro la struttura ad albero visuale dopo la restituzione del HitTest metodo. Potresti voler fornire una struttura di dati, come un ArrayList, per archiviare i valori durante l'enumerazione dei risultati dell'hit test.
// 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
Il metodo di callback hit test definisce le azioni eseguite quando un hit test viene identificato in un oggetto visivo specifico nella struttura ad albero visuale. Dopo aver eseguito le azioni, viene restituito un HitTestResultBehavior valore che determina se continuare o meno l'enumerazione di qualsiasi altro oggetto visivo.
// 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
Annotazioni
L'ordine di enumerazione degli oggetti visivi di hit è in base all'ordine z. L'oggetto visivo al livello più alto dell'ordine z è il primo oggetto enumerato. Qualsiasi altro oggetto visivo enumerato è a livello di ordine z decrescente. Questo ordine di enumerazione corrisponde all'ordine di rendering degli oggetti visivi.
È possibile arrestare l'enumerazione degli oggetti visivi in qualsiasi momento nella funzione di callback di hit test restituendo Stop.
// Set the behavior to stop enumerating visuals.
return HitTestResultBehavior.Stop;
' Set the behavior to stop enumerating visuals.
Return HitTestResultBehavior.Stop
Utilizzo di un callback per il filtro di hit test
È possibile usare un filtro di hit test facoltativo per limitare gli oggetti passati ai risultati dell'hit test. In questo modo è possibile ignorare le parti della struttura ad albero visuale a cui non si è interessati nell'elaborazione dei risultati dell'hit test. Per implementare un filtro hit test, definire una funzione di callback per il filtro hit test e passarla come valore di parametro quando si chiama il metodo 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
Se non si desidera fornire la funzione di callback facoltativa per il filtro del test di impatto, passare il valore null come parametro nel metodo 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.
Eliminazione di una struttura ad albero visuale
La funzione di callback del filtro di hit test consente di enumerare tutti gli oggetti visivi il cui contenuto sottoposto a rendering contiene le coordinate specificate. Tuttavia, è possibile ignorare determinati rami della struttura ad albero visuale che non ti interessano per l'elaborazione nella funzione di callback dei risultati dell'hit test. Il valore restituito della funzione di callback del filtro hit test determina il tipo di azione che deve essere eseguita dall'enumerazione degli oggetti visivi. Ad esempio, se si restituisce il valore ContinueSkipSelfAndChildren, è possibile rimuovere l'oggetto visivo corrente e i relativi elementi figlio dall'enumerazione dei risultati dell'hit test. Ciò significa che la funzione di callback dei risultati dell'hit test non visualizzerà questi oggetti nell'enumerazione. L'eliminazione della struttura ad albero visuale degli oggetti riduce la quantità di elaborazione durante il passaggio di enumerazione dei risultati dell'hit test. Nell'esempio di codice seguente, il filtro ignora le etichette e i relativi discendenti e esegue un test di impatto su tutto il resto.
// 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
Annotazioni
Il callback del filtro hit test viene talvolta chiamato nei casi in cui il callback dei risultati dell'hit test non viene chiamato.
Sovrascrittura dell'hit testing predefinito
È possibile eseguire l'override del supporto di hit testing predefinito di un oggetto visivo eseguendo l'override del HitTestCore metodo . Ciò significa che quando si richiama il HitTest metodo , viene chiamata l'implementazione sottoposta a override di HitTestCore . Il metodo ridefinito viene chiamato quando un hit test rientra nel rettangolo di contorno dell'oggetto visivo, anche se la coordinata cade fuori dal contenuto visualizzato dell'oggetto visivo.
// 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
In alcuni casi può essere necessario eseguire il hit test sia sul rettangolo di delimitazione che sul contenuto sottoposto a rendering di un oggetto visivo. Usando il valore del parametro PointHitTestParameters nel metodo HitTestCore sottoposto a override come parametro del metodo HitTestCore di base, è possibile eseguire azioni in base a un colpo del rettangolo di delimitazione di un oggetto visivo e quindi eseguire un secondo hit test contro il contenuto renderizzato dell'oggetto visivo.
// 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
Vedere anche
.NET Desktop feedback