WPF之碰撞检测–HitTesting
效果如下:
界面代码如下:
<Window x:Class="Hit_Testing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Hit_Testing"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Canvas Name="canvas1" MouseLeftButtonDown="Canvas_MouseLeftButtonDown">
<Rectangle MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave" Canvas.Left="20" Canvas.Top="20" Width="100" Height="60" Stroke="Black" Fill="LightBlue" Opacity="0.7"/>
<Rectangle MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave" Canvas.Left="70" Canvas.Top="50" Width="100" Height="60" Stroke="Black" Fill="LightBlue" Opacity="0.7"/>
<Rectangle MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave" Canvas.Left="150" Canvas.Top="80" Width="100" Height="60" Stroke="Black" Fill="LightBlue" Opacity="0.7"/>
<Rectangle MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave" Canvas.Left="20" Canvas.Top="100" Width="100" Height="60" Stroke="Black" Fill="LightBlue" Opacity="0.7"/>
<Rectangle MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave" Canvas.Left="40" Canvas.Top="60" Width="100" Height="60" Stroke="Black" Fill="LightBlue" Opacity="0.7"/>
<Rectangle Canvas.Left="30" Canvas.Top="130" MouseLeave="Rectangle_MouseLeave" Width="100" Height="60" Stroke="Black" Fill="LightBlue" Opacity="0.7"/>
</Canvas>
</Window>
后台代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Hit_Testing
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private List<Rectangle> hitList = new List<Rectangle>();
private EllipseGeometry hitArea = new EllipseGeometry();
public MainWindow()
{
InitializeComponent();
Initialize();
}
private void Initialize()
{
foreach(Rectangle rect in this.canvas1.Children)
{
rect.Fill = Brushes.LightBlue;
}
}
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Initialize();
// Get Mouse Click Point
Point pt = e.GetPosition(this.canvas1);
// Define hit testing area
hitArea = new EllipseGeometry(pt, 1.0, 1.0);
hitList.Clear();
// Call HitTest Method
VisualTreeHelper.HitTest(canvas1, null, new HitTestResultCallback(HitTestCallback), new GeometryHitTestParameters(hitArea));
if(hitList.Count>0)
{
foreach(Rectangle rect in hitList)
{
// Change rectangle fill if it is hit;
rect.Fill = Brushes.LightCoral;
}
MessageBox.Show($"You hit+{hitList.Count.ToString()}+ rectangles.");
}
}
private HitTestResultBehavior HitTestCallback(HitTestResult result)
{
// Retrieve the results of the hit test
IntersectionDetail intersectionDetail = ((GeometryHitTestResult)result).IntersectionDetail;
switch(intersectionDetail)
{
case IntersectionDetail.FullyContains:
// Add HitTest result to the List
hitList.Add((Rectangle)result.VisualHit);
return HitTestResultBehavior.Continue;
case IntersectionDetail.Intersects:
// Set behavior to return the visuals at all z-orders levels;
return HitTestResultBehavior.Continue;
case IntersectionDetail.FullyInside:
// Set bahivor to return the visuals at all z-orders levels;
return HitTestResultBehavior.Continue;
default:
return HitTestResultBehavior.Stop;
}
}
private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
{
Rectangle rect = (Rectangle)sender;
if(rect!=null)
{
rect.Fill = Brushes.Green;
}
}
private void Rectangle_MouseLeave(object sender, MouseEventArgs e)
{
Rectangle rect = (Rectangle)sender;
if (rect != null && rect.Fill==Brushes.Green)
{
rect.Fill = Brushes.LightBlue;
}
}
}
}