diff --git a/src/Wpf.Ui/Extensions/UiElementExtensions.cs b/src/Wpf.Ui/Extensions/UiElementExtensions.cs index bf6d4639d..95b3f0f47 100644 --- a/src/Wpf.Ui/Extensions/UiElementExtensions.cs +++ b/src/Wpf.Ui/Extensions/UiElementExtensions.cs @@ -10,7 +10,7 @@ internal static class UiElementExtensions /// /// Do not call it outside of NCHITTEST, NCLBUTTONUP, NCLBUTTONDOWN messages! /// - /// if mouse is over the element. otherwise. + /// if mouse is over the element. otherwise. public static bool IsMouseOverElement(this UIElement element, IntPtr lParam) { // This method will be invoked very often and must be as simple as possible. @@ -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() - .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 { @@ -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; + } }