Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 26 additions & 20 deletions src/Wpf.Ui/Extensions/UiElementExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal static class UiElementExtensions
/// <summary>
/// Do not call it outside of NCHITTEST, NCLBUTTONUP, NCLBUTTONDOWN messages!
/// </summary>
/// <returns><see langword="true"/> if mouse is over the element. <see langword="false"/> otherwise.</returns>
/// <returns><see langword="true" /> if mouse is over the element. <see langword="false" /> otherwise.</returns>
public static bool IsMouseOverElement(this UIElement element, IntPtr lParam)
{
// This method will be invoked very often and must be as simple as possible.
Expand All @@ -21,25 +21,18 @@ public static bool IsMouseOverElement(this UIElement element, IntPtr lParam)

try
{
var mousePosScreen = new Point(Get_X_LParam(lParam), Get_Y_LParam(lParam));

return new Rect(default, element.RenderSize).Contains(element.PointFromScreen(mousePosScreen))
&& element.IsHitTestVisible
&& (
!(element is System.Windows.Controls.Panel panel)
|| // If element is Panel, check if children at mousePosRelative is with IsHitTestVisible false.
(
panel
.Children.OfType<UIElement>()
.FirstOrDefault(child =>
new Rect(default, child.RenderSize).Contains(
child.PointFromScreen(mousePosScreen)
)
)
?.IsHitTestVisible
?? false
)
);
// Ensure the visual is connected to a presentation source (needed for PointFromScreen).
if (PresentationSource.FromVisual(element) == null)
{
return false;
}

var mousePosition = new Point(Get_X_LParam(lParam), Get_Y_LParam(lParam));

// If element is Panel, check if children at mousePosition is with IsHitTestVisible false.
return new Rect(default, element.RenderSize).Contains(element.PointFromScreen(mousePosition)) &&
element.IsHitTestVisible &&
(element is not System.Windows.Controls.Panel panel || IsChildHitTestVisibleAtPointFromScreen(panel, mousePosition));
}
catch
{
Expand All @@ -56,4 +49,17 @@ private static int Get_Y_LParam(IntPtr lParam)
{
return (short)(lParam.ToInt32() >> 16);
}

private static bool IsChildHitTestVisibleAtPointFromScreen(System.Windows.Controls.Panel panel, Point mousePosition)
{
foreach (UIElement child in panel.Children)
{
if (new Rect(default, child.RenderSize).Contains(child.PointFromScreen(mousePosition)))
{
return child.IsHitTestVisible;
}
}

return false;
}
}
Loading