| File: System\Windows\Forms\Controls\TabControl\TabControl.TabControlAccessibleObject.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 System.Drawing; using Windows.Win32.System.Variant; using Windows.Win32.UI.Accessibility; namespace System.Windows.Forms; public partial class TabControl { internal sealed class TabControlAccessibleObject : ControlAccessibleObject { public TabControlAccessibleObject(TabControl owningTabControl) : base(owningTabControl) { } public override Rectangle Bounds { get { if (!this.IsOwnerHandleCreated(out TabControl? _)) { return Rectangle.Empty; } // The CHILDID_SELF constant returns to the id of the TabPage, which allows to use the native // "accLocation" method to get the "Bounds" property return SystemIAccessible.TryGetLocation(CHILDID_SELF); } } public override AccessibleRole Role => this.GetOwnerAccessibleRole(AccessibleRole.PageTabList); public override AccessibleStates State // The CHILDID_SELF constant returns to the id of the trackbar, which allows to use the native // "get_accState" method to get the "State" property => SystemIAccessible.TryGetState(CHILDID_SELF); internal override IRawElementProviderFragmentRoot.Interface FragmentRoot => this; internal override bool IsSelectionRequired => true; public override AccessibleObject? GetChild(int index) { if (!this.IsOwnerHandleCreated(out TabControl? owner) || owner.TabPages.Count == 0 || index < 0 || index > owner.TabPages.Count) { return null; } return index == 0 ? owner.SelectedTab?.AccessibilityObject : owner.TabPages[index - 1].TabAccessibilityObject; } private protected override bool IsInternal => true; public override int GetChildCount() { if (!this.IsOwnerHandleCreated(out TabControl? owner)) { // We return -1 instead of 0 when the Handle has not been created, // so that the user can distinguish between the situation // when something went wrong (in this case, the Handle was not created) // and the situation when the Handle was created, but the TabControl, // for example, does not contain TabPages. return -1; } if (owner.TabPages.Count == 0) { return 0; } // We add 1 to the number of TabPages, since the TabControl, in addition to the elements // for the TabPages,contains an element for the Panel of the selected TabPage. return owner.TabPages.Count + 1; } public override AccessibleObject? HitTest(int x, int y) { if (!this.IsOwnerHandleCreated(out TabControl? owner)) { return null; } Point point = new(x, y); if (owner.SelectedTab is not null && owner.SelectedTab.AccessibilityObject.Bounds.Contains(point)) { return owner.SelectedTab.AccessibilityObject; } foreach (TabPage tabPage in owner.TabPages) { if (tabPage.TabAccessibilityObject.Bounds.Contains(point)) { return tabPage.TabAccessibilityObject; } } return this; } internal override IRawElementProviderFragment.Interface? ElementProviderFromPoint(double x, double y) => HitTest((int)x, (int)y) ?? base.ElementProviderFromPoint(x, y); internal override IRawElementProviderFragment.Interface? FragmentNavigate(NavigateDirection direction) { if (!this.IsOwnerHandleCreated(out TabControl? owner)) { return null; } return direction switch { NavigateDirection.NavigateDirection_FirstChild => owner.SelectedTab?.AccessibilityObject, NavigateDirection.NavigateDirection_LastChild => owner.TabPages.Count > 0 ? owner.TabPages[^1].TabAccessibilityObject : null, _ => base.FragmentNavigate(direction) }; } internal override VARIANT GetPropertyValue(UIA_PROPERTY_ID propertyID) => propertyID switch { UIA_PROPERTY_ID.UIA_HasKeyboardFocusPropertyId => (VARIANT)(this.TryGetOwnerAs(out TabControl? owner) && owner.Focused), UIA_PROPERTY_ID.UIA_IsKeyboardFocusablePropertyId // This is necessary for compatibility with MSAA proxy: // IsKeyboardFocusable = true regardless the control is enabled/disabled. => VARIANT.True, _ => base.GetPropertyValue(propertyID) }; internal override IRawElementProviderSimple.Interface[]? GetSelection() => !this.IsOwnerHandleCreated(out TabControl? owner) || owner.SelectedTab is null ? [] : [owner.SelectedTab.TabAccessibilityObject]; internal override bool IsPatternSupported(UIA_PATTERN_ID patternId) => patternId switch { // The "Enabled" property of the TabControl does not affect the behavior of that property, // so it is always true UIA_PATTERN_ID.UIA_SelectionPatternId => true, _ => base.IsPatternSupported(patternId) }; } }