using System; using System.Linq; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using HandyControl.Tools.Interop; namespace HandyControl.Tools; public static class VisualHelper { internal static VisualStateGroup TryGetVisualStateGroup(DependencyObject d, string groupName) { var root = GetImplementationRoot(d); if (root == null) return null; return VisualStateManager .GetVisualStateGroups(root)? .OfType() .FirstOrDefault(group => string.CompareOrdinal(groupName, group.Name) == 0); } internal static FrameworkElement GetImplementationRoot(DependencyObject d) => 1 == VisualTreeHelper.GetChildrenCount(d) ? VisualTreeHelper.GetChild(d, 0) as FrameworkElement : null; public static T GetChild(DependencyObject d) where T : DependencyObject { if (d == null) return default; if (d is T t) return t; for (var i = 0; i < VisualTreeHelper.GetChildrenCount(d); i++) { var child = VisualTreeHelper.GetChild(d, i); var result = GetChild(child); if (result != null) return result; } return default; } public static T GetParent(DependencyObject d) where T : DependencyObject => d switch { null => default, T t => t, Window _ => null, _ => GetParent(VisualTreeHelper.GetParent(d)) }; public static IntPtr GetHandle(this Visual visual) => (PresentationSource.FromVisual(visual) as HwndSource)?.Handle ?? IntPtr.Zero; internal static void HitTestVisibleElements(Visual visual, HitTestResultCallback resultCallback, HitTestParameters parameters) => VisualTreeHelper.HitTest(visual, ExcludeNonVisualElements, resultCallback, parameters); private static HitTestFilterBehavior ExcludeNonVisualElements(DependencyObject potentialHitTestTarget) { if (!(potentialHitTestTarget is Visual)) return HitTestFilterBehavior.ContinueSkipSelfAndChildren; if (!(potentialHitTestTarget is UIElement uIElement) || uIElement.IsVisible && uIElement.IsEnabled) return HitTestFilterBehavior.Continue; return HitTestFilterBehavior.ContinueSkipSelfAndChildren; } internal static bool ModifyStyle(IntPtr hWnd, int styleToRemove, int styleToAdd) { var windowLong = InteropMethods.GetWindowLong(hWnd, InteropValues.GWL.STYLE); var num = (windowLong & ~styleToRemove) | styleToAdd; if (num == windowLong) return false; InteropMethods.SetWindowLong(hWnd, InteropValues.GWL.STYLE, num); return true; } }