예제 #1
0
        private static List <MeasurementResult> FindCandidatesInGroup(DirectionFunction function, Rect focusedBounds, AutomationElement group, System.Windows.Automation.Condition condition)
        {
            var results  = new List <MeasurementResult>();
            var children = group.FindAll(TreeScope.Children, condition)?.Cast <AutomationElement>();

            if (children == null)
            {
                return(results);
            }

            AutomationElement candidate           = null;
            double            nearestItemDistance = double.PositiveInfinity;

            foreach (var element in children)
            {
                var info         = element.Current;
                var targetBounds = info.BoundingRectangle;
                var controlType  = info.ControlType;

                if (controlType == ControlType.TreeItem)
                {
                    results.AddRange(FindCandidatesInGroup(function, focusedBounds, element, condition));
                }

                if (_ignoreElements.Contains(controlType) || targetBounds == focusedBounds || !function.IsInDirection(targetBounds, focusedBounds) || info.IsOffscreen)
                {
                    continue;
                }

                var distance = function.DistanceCaluculator(targetBounds, focusedBounds, _weightingValue);
                if (!IsFocusable(info, controlType) || targetBounds == _zero)
                {
                    distance = double.PositiveInfinity;
                }

                if (distance < nearestItemDistance && _enumerateTargets.Contains(controlType))
                {
                    nearestItemDistance = distance;
                    candidate           = element;
                }
                else
                {
                    results.AddRange(FindCandidatesInGroup(function, focusedBounds, element, condition));
                }
            }

            if (candidate == null)
            {
                return(results);
            }
            results.Add(new MeasurementResult(candidate, nearestItemDistance));
            return(results);
        }
예제 #2
0
        private static void InternalMoveTo(Direction direction, Unit unit)
        {
            Initialize();
            Task.Run(() => SpatialNavigation.UIAssistantAPI.ThemeAPI.SwitchTheme("General"));
            if (unit == Unit.Group)
            {
                _enumerateTargets = _groupTargets;
            }
            else
            {
                _enumerateTargets = _itemTargets;
            }

            var activeWindow = SpatialNavigation.UIAssistantAPI.WindowAPI.ActiveWindow;
            var rootElement  = activeWindow.Element;
            var current      = AutomationElement.FocusedElement;

            if (current == null || current == rootElement)
            {
                MoveToFirst(rootElement);
                return;
            }

            _weightingValue = activeWindow.Bounds.BottomRight.GetDistance(new Point(0, 0));

            var currentInfo = current.Current;
            var parent      = current.GetParent();

            if (parent != rootElement && unit == Unit.Group)
            {
                current     = parent;
                currentInfo = parent.Current;
            }

            var focusedBounds = currentInfo.BoundingRectangle;

            _excludes.Add(focusedBounds);
            var type     = currentInfo.ControlType;
            var function = new DirectionFunction(direction);

            if (parent != rootElement && unit != Unit.Group)
            {
                if (!TryMoveToSibling(parent, function, focusedBounds))
                {
                    TryMove(rootElement, function, focusedBounds, unit);
                    return;
                }
            }
            else
            {
                TryMove(rootElement, function, focusedBounds, unit);
            }
        }
예제 #3
0
        private static bool TryMoveToSibling(AutomationElement current, DirectionFunction function, Rect focusedBounds)
        {
            if (current == null)
            {
                return(false);
            }

            var condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true), new PropertyCondition(AutomationElement.IsOffscreenProperty, false));

            _excludes.Add(current.Current.BoundingRectangle);
            var results     = FindCandidatesInGroup(function, focusedBounds, current, condition);
            var destination = results.OrderBy(x => x.Distance).FirstOrDefault()?.Element;

            if (destination != null)
            {
                Move(destination, focusedBounds);
                return(true);
            }
            return(false);
        }
예제 #4
0
        private static bool TryMove(AutomationElement current, DirectionFunction function, Rect focusedBounds, Unit unit)
        {
            if (current == null)
            {
                return(false);
            }

            var results     = FindCandidates(function, focusedBounds, current, unit);
            var destination = results.OrderBy(x => x.Distance).ElementAtOrDefault(0)?.Element;

            if (destination != null)
            {
                if (destination.Current.ControlType == ControlType.TabItem)
                {
                    var tab      = destination.GetParent();
                    var tabItems = tab.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem))?.Cast <AutomationElement>();
                    destination = tabItems?.FirstOrDefault(x => x.IsSelected()) ?? destination;
                }
                Move(destination, focusedBounds);
                return(true);
            }
            return(false);
        }
예제 #5
0
        // Too complex...
        private static List <MeasurementResult> FindCandidates(DirectionFunction function, Rect focusedBounds, AutomationElement root, Unit unit)
        {
            List <MeasurementResult> results = new List <MeasurementResult>();
            var children = root.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition)?.Cast <AutomationElement>();

            if (children == null)
            {
                return(results);
            }

            AutomationElement        candidate        = null;
            List <MeasurementResult> candidates       = new List <MeasurementResult>();
            List <AutomationElement> focusedAncestors = new List <AutomationElement>();
            double nearestFocusableDistance           = double.PositiveInfinity;

            foreach (var element in children)
            {
                var info        = element.Current;
                var bounds      = info.BoundingRectangle;
                var controlType = info.ControlType;

                // for WPF(Tab and TabItem)
                if (controlType == ControlType.Tab)
                {
                    focusedAncestors.Add(element);
                }
                else if (controlType == ControlType.TabItem)
                {
                    candidates.Add(new MeasurementResult(element, _weightingValue * 3));
                }

                if (_excludes.Any(x => x == bounds))
                {
                    continue;
                }
                if (bounds.Contains(focusedBounds) || bounds == _zero)
                {
                    focusedAncestors.Add(element);
                    continue;
                }
                if (!function.IsInDirection(bounds, focusedBounds) || bounds == focusedBounds)
                {
                    continue;
                }
                var distance = function.DistanceCaluculator(bounds, focusedBounds, _weightingValue);

                if (unit != Unit.Group || !controlType.IsContainer() || controlType == ControlType.Group)
                {
                    candidates.Add(new MeasurementResult(element, distance));
                }
                if (distance < nearestFocusableDistance)
                {
                    if (_enumerateTargets.Contains(controlType) && IsFocusable(info, controlType))
                    {
                        nearestFocusableDistance = distance;
                        candidate = element;
                    }
                }
            }

            focusedAncestors.ForEach(x => results.AddRange(FindCandidates(function, focusedBounds, x, unit)));
            candidates = candidates.OrderBy(x => x.Distance).ToList();
            foreach (var c in candidates)
            {
                var condition = new PropertyCondition(AutomationElement.IsEnabledProperty, true);
                var result    = FindCandidatesInGroup(function, focusedBounds, c.Element, condition);
                if (result.Count > 0)
                {
                    results.AddRange(result);
                    break;
                }
            }
            if (candidate != null)
            {
                results.Add(new MeasurementResult(candidate, nearestFocusableDistance));
            }
            return(results);
        }