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); }
// 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); }