Adding in HitTester App

This commit is contained in:
Clint Rutkas 2020-02-19 13:09:18 -08:00
parent 883bbf102a
commit babfc9ade3
10 changed files with 325 additions and 0 deletions

View file

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29613.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZone_HitTest", "FancyZone_HitTest\FancyZone_HitTest.csproj", "{4589E362-908E-4277-B2CE-F2257469356D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4589E362-908E-4277-B2CE-F2257469356D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4589E362-908E-4277-B2CE-F2257469356D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4589E362-908E-4277-B2CE-F2257469356D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4589E362-908E-4277-B2CE-F2257469356D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {10EA2631-C13F-4C50-9389-5BE4FCC66F2A}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,9 @@
<Application x:Class="FancyZone_HitTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FancyZone_HitTest"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace FancyZone_HitTest
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View file

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,36 @@
<Window x:Class="FancyZone_HitTest.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:FancyZone_HitTest"
mc:Ignorable="d"
Title="MainWindow" Width="1024" Height="768">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Grid MouseMove="Grid_MouseMove" Name="hitTestGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="#ff0000" Grid.Column="0" Name="a" />
<Rectangle Fill="#00ff00" Grid.Column="1" Name="b" />
<Rectangle Fill="#0000ff" Grid.Column="2" Name="c" />
<Rectangle Fill="#aabbff" Grid.ColumnSpan="3" Name="d" Width="550" Height="500" />
<!--Height="600"-->
<Rectangle Fill="#aabbff" Grid.ColumnSpan="3" Name="f" Height="400" Width="400" />
<Rectangle Fill="Orange" Grid.ColumnSpan="3" Name="e"/>
</Grid>
<StackPanel Grid.Column="1">
<TextBlock>Calculations</TextBlock>
<TextBlock x:Name="itemsHit" />
</StackPanel>
</Grid>
</Window>

View file

@ -0,0 +1,108 @@
using System;
using System.Collections;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace FancyZone_HitTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
static ArrayList _hitResultsList = new ArrayList();
static ArrayList _visualCalculationList = new ArrayList();
private void Grid_MouseMove(object sender, MouseEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point gridMouseLocation = e.GetPosition((UIElement)sender);
// Clear the contents of the list used for hit test results.
_hitResultsList.Clear();
_visualCalculationList.Clear();
// Set up a callback to receive the hit test result enumeration.
VisualTreeHelper.HitTest(hitTestGrid, null,
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(gridMouseLocation));
// Perform actions on the hit test results list.
if (_hitResultsList.Count > 0)
{
foreach (Rectangle item in hitTestGrid.Children.OfType<Rectangle>())
{
item.Opacity = 0.25;
item.StrokeThickness = 0;
}
itemsHit.Text = string.Format("Number of Visuals Hit: {0}{1}", _hitResultsList.Count, Environment.NewLine);
itemsHit.Text += string.Format("Grid mouse: {0}{1}", gridMouseLocation, Environment.NewLine);
itemsHit.Text += Environment.NewLine;
foreach (Shape item in _hitResultsList)
{
_visualCalculationList.Add(new VisualData(item, e, hitTestGrid));
}
var reorderedVisualData = _visualCalculationList.Cast<VisualData>().OrderBy(x => x, new VisualDataComparer<VisualData>());
foreach (VisualData item in reorderedVisualData)
{
itemsHit.Text += string.Format(
"Name: {7}{0}" +
"C Mouse: {4}{0}" +
"Rel Mouse: {3}{0}" +
"Edge Mouse: {8}{0}" +
"Abs TL: {1}{0}" +
"Center: {2}{0}" +
"Area: {5}{0}" +
"Edge %: {9}{0}" +
"a/d: {6}{0}",
Environment.NewLine,
item.TopLeft, // 1
item.CenterMass, // 2
item.RelativeMouseLocation, // 3
item.MouseDistanceFromCenter, // 4
item.Area, // 5
item.Area / item.MouseDistanceFromCenter, //6
item.Name, // 7
item.DistanceFromEdge, //8
item.DistanceFromEdgePercentage // 9
);
itemsHit.Text += Environment.NewLine;
}
if (reorderedVisualData.Count() > 0)
{
var rect = (hitTestGrid.FindName(reorderedVisualData.First().Name) as Rectangle);
rect.Opacity = .75;
rect.Stroke = Brushes.Black;
rect.StrokeThickness = 5;
}
}
else
{
itemsHit.Text = "";
}
}
public static 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;
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Media;
namespace FancyZone_HitTest
{
public static class Utilities
{
public static Point GetPosition(Visual element, Visual root)
{
var positionTransform = element.TransformToAncestor(root);
var areaPosition = positionTransform.Transform(new Point(0, 0));
return areaPosition;
}
}
}

View file

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace FancyZone_HitTest
{
public class VisualData
{
public Point RelativeMouseLocation;
public Point CenterMass;
public Point TopLeft;
public double MouseDistanceFromCenter;
public int Area;
public string Name;
public double DistanceFromEdge;
public double DistanceFromEdgePercentage;
public VisualData(Shape item, MouseEventArgs e, Visual root)
{
Name = item.Name;
int width = (int)Math.Floor(item.ActualWidth);
int height = (int)Math.Floor(item.ActualHeight);
TopLeft = Utilities.GetPosition(item, root);
CenterMass = new Point(width / 2, height / 2);
Area = width * height;
RelativeMouseLocation = e.GetPosition(item);
MouseDistanceFromCenter = Point.Subtract(RelativeMouseLocation, CenterMass).Length;
var mouseX = Math.Floor(RelativeMouseLocation.X);
var mouseY = Math.Floor(RelativeMouseLocation.Y);
var horDist = (RelativeMouseLocation.X < CenterMass.X) ? RelativeMouseLocation.X : width - mouseX;
var vertDist = (RelativeMouseLocation.Y < CenterMass.Y) ? RelativeMouseLocation.Y : height - mouseY;
var isHorCalc = (horDist < vertDist);
DistanceFromEdge = Math.Floor(isHorCalc ? horDist : vertDist);
if (isHorCalc)
{
DistanceFromEdgePercentage = (width - DistanceFromEdge) / width;
}
else
{
DistanceFromEdgePercentage = (height - DistanceFromEdge) / height;
}
}
}

View file

@ -0,0 +1,39 @@
using System.Collections.Generic;
namespace FancyZone_HitTest
{
public class VisualDataComparer<T> : IComparer<VisualData>
{
int IComparer<VisualData>.Compare(VisualData x, VisualData y)
{
// has quirks but workable
if (x.DistanceFromEdge == y.DistanceFromEdge)
{
return y.Area.CompareTo(x.Area);
}
else
{
return x.DistanceFromEdge.CompareTo(y.DistanceFromEdge);
}
// entire screen won't work
//if (x.MouseDistanceFromCenter == y.MouseDistanceFromCenter)
//{
// return y.Area.CompareTo(x.Area);
//}
//else
//{
// return x.MouseDistanceFromCenter.CompareTo(y.MouseDistanceFromCenter);
//}
//if (x.DistanceFromEdgePercentage == y.DistanceFromEdgePercentage)
//{
// return y.Area.CompareTo(x.Area);
//}
//else
//{
// return x.DistanceFromEdgePercentage.CompareTo(y.DistanceFromEdgePercentage);
//}
}
}
}