| File: System\Windows\Forms\Scrolling\ScrollBar.ScrollBarAccessibleObject.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms\System.Windows.Forms.csproj (System.Windows.Forms) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Windows.Win32.System.Variant; using Windows.Win32.UI.Accessibility; namespace System.Windows.Forms; public partial class ScrollBar { internal class ScrollBarAccessibleObject : ControlAccessibleObject { private ScrollBarFirstLineButtonAccessibleObject? _firstLineButtonAccessibleObject; private ScrollBarFirstPageButtonAccessibleObject? _firstPageButtonAccessibleObject; private ScrollBarLastLineButtonAccessibleObject? _lastLineButtonAccessibleObject; private ScrollBarLastPageButtonAccessibleObject? _lastPageButtonAccessibleObject; private ScrollBarThumbAccessibleObject? _thumbAccessibleObject; internal ScrollBarAccessibleObject(ScrollBar owningScrollBar) : base(owningScrollBar) { } internal ScrollBarFirstLineButtonAccessibleObject? FirstLineButtonAccessibleObject => _firstLineButtonAccessibleObject ??= this.TryGetOwnerAs(out ScrollBar? owner) ? new(owner) : null; internal ScrollBarFirstPageButtonAccessibleObject? FirstPageButtonAccessibleObject => _firstPageButtonAccessibleObject ??= this.TryGetOwnerAs(out ScrollBar? owner) ? new(owner) : null; internal override IRawElementProviderFragmentRoot.Interface? FragmentRoot => this; internal ScrollBarLastLineButtonAccessibleObject? LastLineButtonAccessibleObject => _lastLineButtonAccessibleObject ??= this.TryGetOwnerAs(out ScrollBar? owner) ? new(owner) : null; internal ScrollBarLastPageButtonAccessibleObject? LastPageButtonAccessibleObject => _lastPageButtonAccessibleObject ??= this.TryGetOwnerAs(out ScrollBar? owner) ? new(owner) : null; internal ScrollBarThumbAccessibleObject? ThumbAccessibleObject => _thumbAccessibleObject ??= this.TryGetOwnerAs(out ScrollBar? owner) ? new(owner) : null; // The maximum value can only be reached programmatically. The value of a scroll bar cannot reach its maximum // value through user interaction at run time. The maximum value that can be reached through user interaction // is equal to 1 plus the Maximum property value minus the LargeChange property value. internal int UIMaximum => this.TryGetOwnerAs(out ScrollBar? owner) ? owner.Maximum - owner.LargeChange + 1 : 0; private bool ArePageButtonsDisplayed => (FirstPageButtonAccessibleObject?.IsDisplayed ?? false) && (LastPageButtonAccessibleObject?.IsDisplayed ?? false); private bool ArePageButtonsHidden => !(FirstPageButtonAccessibleObject?.IsDisplayed ?? true) && !(LastPageButtonAccessibleObject?.IsDisplayed ?? true); public override AccessibleObject? GetChild(int index) { if (!this.IsOwnerHandleCreated(out ScrollBar? _)) { return null; } return index switch { 0 => FirstLineButtonAccessibleObject, 1 => (FirstPageButtonAccessibleObject?.IsDisplayed ?? false) ? FirstPageButtonAccessibleObject : ThumbAccessibleObject, 2 => (FirstPageButtonAccessibleObject?.IsDisplayed ?? false) ? ThumbAccessibleObject : ArePageButtonsHidden ? LastLineButtonAccessibleObject : LastPageButtonAccessibleObject, 3 => ArePageButtonsDisplayed ? LastPageButtonAccessibleObject : ArePageButtonsHidden ? null : LastLineButtonAccessibleObject, 4 => ArePageButtonsDisplayed ? LastLineButtonAccessibleObject : null, _ => null }; } private protected override bool IsInternal => true; public override int GetChildCount() => this.IsOwnerHandleCreated(out ScrollBar? _) ? ArePageButtonsDisplayed ? 5 : ArePageButtonsHidden ? 3 : 4 : -1; public override AccessibleObject? HitTest(int x, int y) { if (!this.IsOwnerHandleCreated(out ScrollBar? _)) { return null; } Point point = new(x, y); if (ThumbAccessibleObject?.Bounds.Contains(point) == true) { return ThumbAccessibleObject; } if (FirstLineButtonAccessibleObject?.Bounds.Contains(point) == true) { return FirstLineButtonAccessibleObject; } if (FirstPageButtonAccessibleObject?.Bounds.Contains(point) == true) { return FirstPageButtonAccessibleObject; } if (LastPageButtonAccessibleObject?.Bounds.Contains(point) == true) { return LastPageButtonAccessibleObject; } if (LastLineButtonAccessibleObject?.Bounds.Contains(point) == true) { return LastLineButtonAccessibleObject; } return null; } internal override IRawElementProviderFragment.Interface? ElementProviderFromPoint(double x, double y) { AccessibleObject? element = HitTest((int)x, (int)y); return element ?? base.ElementProviderFromPoint(x, y); } internal override IRawElementProviderFragment.Interface? FragmentNavigate(NavigateDirection direction) => direction switch { NavigateDirection.NavigateDirection_FirstChild => FirstLineButtonAccessibleObject, NavigateDirection.NavigateDirection_LastChild => LastLineButtonAccessibleObject, _ => base.FragmentNavigate(direction) }; internal override VARIANT GetPropertyValue(UIA_PROPERTY_ID propertyID) => propertyID switch { // If we don't set a default role for the accessible object // it will be retrieved from Windows. // And we don't have a 100% guarantee it will be correct, hence set it ourselves. UIA_PROPERTY_ID.UIA_ControlTypePropertyId when this.GetOwnerAccessibleRole() == AccessibleRole.Default => (VARIANT)(int)UIA_CONTROLTYPE_ID.UIA_ScrollBarControlTypeId, UIA_PROPERTY_ID.UIA_HasKeyboardFocusPropertyId => (VARIANT)(this.TryGetOwnerAs(out ScrollBar? owner) && owner.Focused), UIA_PROPERTY_ID.UIA_RangeValueValuePropertyId => (VARIANT)RangeValue, UIA_PROPERTY_ID.UIA_RangeValueIsReadOnlyPropertyId => (VARIANT)IsReadOnly, UIA_PROPERTY_ID.UIA_RangeValueLargeChangePropertyId => (VARIANT)LargeChange, UIA_PROPERTY_ID.UIA_RangeValueSmallChangePropertyId => (VARIANT)SmallChange, UIA_PROPERTY_ID.UIA_RangeValueMaximumPropertyId => (VARIANT)Maximum, UIA_PROPERTY_ID.UIA_RangeValueMinimumPropertyId => (VARIANT)Minimum, UIA_PROPERTY_ID.UIA_IsRangeValuePatternAvailablePropertyId => (VARIANT)IsPatternSupported(UIA_PATTERN_ID.UIA_RangeValuePatternId), _ => base.GetPropertyValue(propertyID) }; internal override bool IsIAccessibleExSupported() => true; internal override double RangeValue => this.TryGetOwnerAs(out ScrollBar? owner) ? owner.Value : base.RangeValue; internal override double LargeChange => this.TryGetOwnerAs(out ScrollBar? owner) ? owner.LargeChange : base.LargeChange; internal override double SmallChange => this.TryGetOwnerAs(out ScrollBar? owner) ? owner.SmallChange : base.SmallChange; internal override double Maximum => this.TryGetOwnerAs(out ScrollBar? owner) ? owner.Maximum : base.Maximum; internal override double Minimum => this.TryGetOwnerAs(out ScrollBar? owner) ? owner.Minimum : base.Minimum; internal override bool IsReadOnly => false; internal override void SetValue(double newValue) { if (!this.IsOwnerHandleCreated(out ScrollBar? owner)) { return; } owner.Value = (int)newValue; } internal override bool IsPatternSupported(UIA_PATTERN_ID patternId) => patternId switch { UIA_PATTERN_ID.UIA_ValuePatternId => true, UIA_PATTERN_ID.UIA_RangeValuePatternId => true, _ => base.IsPatternSupported(patternId) }; } }