HitTest is buggy / not accurate when the UserControl's RenderTransform set to a large scale(ScaleX = ScaleY = 500)
See original GitHub issueDescription
.NET 6 or higher / WPF
I have set UserControl’s RenderTransform to a ScaleTransform(ScaleX = ScaleY = 500), and set the UserControl’s Template to be a Line shape. However, when running the application, I noticed that the mouse events of UserControl are triggered when the mouse click or move in the blank area near the line. When I set the scale to a smaller value,like ScaleX = ScaleY = 1, I don’t encounter this issue.
I find an similar problem here(https://social.msdn.microsoft.com/Forums/vstudio/en-US/8708e340-f734-4cf4-b91d-28b49fee2b72/hittest-is-buggy-not-accurate-for-transformed-scaled-etc-visuals?forum=wpf), but it seems that it has not been fixed yet.
Click in the blank area near the line:
Reproduction Steps
My demo code in github: https://github.com/yao-xiaofei/ShapeTest
Here is my code:
<Grid>
<UserControl PreviewMouseLeftButtonDown="UserControl_PreviewMouseLeftButtonDown">
<UserControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="500" ScaleY="500" />
</TransformGroup>
</UserControl.RenderTransform>
<UserControl.Template>
<ControlTemplate>
<Line
Stroke="Lime"
StrokeThickness="0.01"
UseLayoutRounding="True"
X1="0.4"
X2="0.8"
Y1="0.3"
Y2="0.3" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Cross" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</UserControl.Template>
</UserControl>
</Grid>
Expected behavior
My expectation is that when I set a larger scale value(ScaleX = ScaleY = 500 or larger), the UserControl should only respond to mouse events when clicking on the area of the line, and avoid triggering mouse events in the blank area.
Actual behavior
The mouse events of UserControl are triggered when the mouse click or move in the blank area near the line.
Click in the blank area near the line:
Regression?
No response
Known Workarounds
No response
Impact
No response
Configuration
No response
Other information
No response
Issue Analytics
- State:
- Created 3 months ago
- Reactions:1
- Comments:12 (3 by maintainers)
This is precision for geometry and should roughly have a linear correlation with the number of subdivisions required, i.e. double the precision requires double the number of geometry segments in the calculations. Changes in this value should have a linear effect to performance and perhaps even on memory if the resulting geometry is actually stored instead of just being hit tested. (This constant is used in more methods than just hit testing methods but I didn’t research how often those are called without supplying a specific precision).
Ok, was able to repro and found the cause, its the builtin default precision of the WPF geometry system, hardcoded to be 0.25 by default.
Since your lines are much finer (0.01 thickness) the default geometry precision is not sufficient. This has nothing to do with the scaling you are doing, this depends on the absolute numbers since the hit testing is done in the original scale not in the scale they are rendered at. You can construct a
LineGeometry
and do a hit test against it viaStrokeContains
and it will be very inaccurate with the thickness and coordinates you are using.The geometry API has overloads that allow you to specify a precision, if you use that and set it appropriately then the hit test will work. Unfortunately this means you’ll have to override hit testing for everything you are zoomin in at such high scales. It seems like an oversight that WPF doesn’t derive or propagate the required precision from the LayoutTransform, but it is what it is, I don’t think this will be changed at this point.
An alternative to overriding hit testing (depending on what you are planning to do) may be to pre-transform your geometry and objects so they are in the dimensions you are viewing them at.
Hope that helps.