Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Winforms.sln
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "Microsoft.VisualBasic.Forms
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Forms.Common.TestUtilities", "src\Common\tests\TestUtilities\System.Windows.Forms.Common.TestUtilities.csproj", "{05FD23CE-60AE-44A8-8DD6-1688F04BE385}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiScrollBarTests", "src\System.Windows.Forms\tests\IntegrationTests\MauiTests\MauiScrollBarTests\MauiScrollBarTests.csproj", "{872E41E1-FF66-4B12-A273-1F26A548666F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -907,6 +909,22 @@ Global
{05FD23CE-60AE-44A8-8DD6-1688F04BE385}.Release|x64.Build.0 = Release|Any CPU
{05FD23CE-60AE-44A8-8DD6-1688F04BE385}.Release|x86.ActiveCfg = Release|Any CPU
{05FD23CE-60AE-44A8-8DD6-1688F04BE385}.Release|x86.Build.0 = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|arm64.ActiveCfg = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|arm64.Build.0 = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|x64.ActiveCfg = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|x64.Build.0 = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|x86.ActiveCfg = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Debug|x86.Build.0 = Debug|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|Any CPU.Build.0 = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|arm64.ActiveCfg = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|arm64.Build.0 = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|x64.ActiveCfg = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|x64.Build.0 = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|x86.ActiveCfg = Release|Any CPU
{872E41E1-FF66-4B12-A273-1F26A548666F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -966,6 +984,7 @@ Global
{0B4C8C7D-6157-46D4-AC1E-DF27F96C7AF6} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
{FC75CB54-D8D0-4B41-9A4D-9F862F34A02D} = {583F1292-AE8D-4511-B8D8-A81FE4642DDC}
{05FD23CE-60AE-44A8-8DD6-1688F04BE385} = {DF68A171-D27B-4E6A-8A7E-63A651622355}
{872E41E1-FF66-4B12-A273-1F26A548666F} = {8F20A905-BD37-4D80-B8DF-FA45276FC23F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7B1B0433-F612-4E5A-BE7E-FCF5B9F6E136}
Expand Down
1 change: 1 addition & 0 deletions src/System.Windows.Forms/src/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
[assembly: InternalsVisibleTo("MauiMonthCalendarTests, PublicKey=00000000000000000400000000000000")]
[assembly: InternalsVisibleTo("MauiPropertyGridViewTests, PublicKey=00000000000000000400000000000000")]
[assembly: InternalsVisibleTo("MauiTabControlTests, PublicKey=00000000000000000400000000000000")]
[assembly: InternalsVisibleTo("MauiScrollBarTests, PublicKey=00000000000000000400000000000000")]

// This is needed in order to Moq internal interfaces for testing
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
4 changes: 3 additions & 1 deletion src/System.Windows.Forms/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
~override System.Windows.Forms.TrackBar.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject
~override System.Windows.Forms.TrackBar.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject
*REMOVED*override System.Windows.Forms.HScrollBar.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject!
*REMOVED*override System.Windows.Forms.VScrollBar.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject!

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,5 @@ protected override CreateParams CreateParams

protected override Size DefaultSize
=> new Size(80, SystemInformation.HorizontalScrollBarHeight);

protected override AccessibleObject CreateAccessibilityInstance()
=> new HScrollBarAccessibleObject(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Drawing;
using static Interop;

namespace System.Windows.Forms
Expand All @@ -10,25 +11,143 @@ public partial class ScrollBar
{
internal class ScrollBarAccessibleObject : ControlAccessibleObject
{
private ScrollBar _owningScrollBar;
private readonly ScrollBar _owningScrollBar;
private ScrollBarFirstLineButtonAccessibleObject? _firstLineButtonAccessibleObject;
private ScrollBarFirstPageButtonAccessibleObject? _firstPageButtonAccessibleObject;
private ScrollBarLastLineButtonAccessibleObject? _lastLineButtonAccessibleObject;
private ScrollBarLastPageButtonAccessibleObject? _lastPageButtonAccessibleObject;
private ScrollBarThumbAccessibleObject? _thumbAccessibleObject;

internal ScrollBarAccessibleObject(ScrollBar owner) : base(owner)
internal ScrollBarAccessibleObject(ScrollBar owningScrollBar) : base(owningScrollBar)
{
_owningScrollBar = owner;
_owningScrollBar = owningScrollBar;
}

internal override bool IsIAccessibleExSupported() => true;
internal ScrollBarFirstLineButtonAccessibleObject FirstLineButtonAccessibleObject
=> _firstLineButtonAccessibleObject ??= new(_owningScrollBar);

internal override bool IsPatternSupported(UiaCore.UIA patternId)
internal ScrollBarFirstPageButtonAccessibleObject FirstPageButtonAccessibleObject
=> _firstPageButtonAccessibleObject ??= new(_owningScrollBar);

internal override UiaCore.IRawElementProviderFragmentRoot FragmentRoot => this;

internal ScrollBarLastLineButtonAccessibleObject LastLineButtonAccessibleObject
=> _lastLineButtonAccessibleObject ??= new(_owningScrollBar);

internal ScrollBarLastPageButtonAccessibleObject LastPageButtonAccessibleObject
=> _lastPageButtonAccessibleObject ??= new(_owningScrollBar);

internal override int[]? RuntimeId
{
if (patternId == UiaCore.UIA.ValuePatternId)
get
{
return true;
if (!_owningScrollBar.IsHandleCreated)
{
return base.RuntimeId;
}

var runtimeId = new int[2];
runtimeId[0] = RuntimeIDFirstItem;
runtimeId[1] = Interop.PARAM.ToInt(_owningScrollBar.InternalHandle);

return runtimeId;
}
}

return base.IsPatternSupported(patternId);
internal ScrollBarThumbAccessibleObject ThumbAccessibleObject
=> _thumbAccessibleObject ??= new(_owningScrollBar);

// 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 => _owningScrollBar.Maximum - _owningScrollBar.LargeChange + 1;

private bool ArePageButtonsDisplayed
=> FirstPageButtonAccessibleObject.IsDisplayed && LastPageButtonAccessibleObject.IsDisplayed;

private bool ArePageButtonsHidden
=> !FirstPageButtonAccessibleObject.IsDisplayed && !LastPageButtonAccessibleObject.IsDisplayed;

public override AccessibleObject? GetChild(int index)
{
if (!_owningScrollBar.IsHandleCreated)
{
return null;
}

return index switch
{
0 => FirstLineButtonAccessibleObject,
1 => FirstPageButtonAccessibleObject.IsDisplayed ? FirstPageButtonAccessibleObject : ThumbAccessibleObject,
2 => FirstPageButtonAccessibleObject.IsDisplayed
? ThumbAccessibleObject
: ArePageButtonsHidden ? LastLineButtonAccessibleObject : LastPageButtonAccessibleObject,
3 => ArePageButtonsDisplayed
? LastPageButtonAccessibleObject
: ArePageButtonsHidden ? null : LastLineButtonAccessibleObject,
4 => ArePageButtonsDisplayed ? LastLineButtonAccessibleObject : null,
_ => null
};
}

public override int GetChildCount()
=> _owningScrollBar.IsHandleCreated
? ArePageButtonsDisplayed
? 5
: ArePageButtonsHidden ? 3 : 4
: -1;

public override AccessibleObject? HitTest(int x, int y)
{
if (!_owningScrollBar.IsHandleCreated)
{
return null;
}

Point point = new(x, y);
if (ThumbAccessibleObject.Bounds.Contains(point))
{
return ThumbAccessibleObject;
}

if (FirstLineButtonAccessibleObject.Bounds.Contains(point))
{
return FirstLineButtonAccessibleObject;
}

if (FirstPageButtonAccessibleObject.Bounds.Contains(point))
{
return FirstPageButtonAccessibleObject;
}

if (LastPageButtonAccessibleObject.Bounds.Contains(point))
{
return LastPageButtonAccessibleObject;
}

if (LastLineButtonAccessibleObject.Bounds.Contains(point))
{
return LastLineButtonAccessibleObject;
}

return null;
}

internal override UiaCore.IRawElementProviderFragment? ElementProviderFromPoint(double x, double y)
{
AccessibleObject? element = HitTest((int)x, (int)y);

return element ?? base.ElementProviderFromPoint(x, y);
}

internal override UiaCore.IRawElementProviderFragment? FragmentNavigate(UiaCore.NavigateDirection direction)
=> direction switch
{
UiaCore.NavigateDirection.FirstChild => FirstLineButtonAccessibleObject,
UiaCore.NavigateDirection.LastChild => LastLineButtonAccessibleObject,
_ => base.FragmentNavigate(direction)
};

internal override object? GetPropertyValue(UiaCore.UIA propertyID)
=> propertyID switch
{
Expand All @@ -40,10 +159,25 @@ internal override bool IsPatternSupported(UiaCore.UIA patternId)
UiaCore.UIA.ControlTypePropertyId => _owningScrollBar.AccessibleRole == AccessibleRole.Default
? UiaCore.UIA.ScrollBarControlTypeId
: base.GetPropertyValue(propertyID),
UiaCore.UIA.IsKeyboardFocusablePropertyId => true,
UiaCore.UIA.RuntimeIdPropertyId => RuntimeId,
UiaCore.UIA.IsEnabledPropertyId => _owningScrollBar.Enabled,
UiaCore.UIA.IsOffscreenPropertyId => (State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen,
UiaCore.UIA.HasKeyboardFocusPropertyId => _owningScrollBar.Focused,
UiaCore.UIA.IsValuePatternAvailablePropertyId => IsPatternSupported(UiaCore.UIA.ValuePatternId),
_ => base.GetPropertyValue(propertyID)
};

internal override bool IsIAccessibleExSupported() => true;

internal override bool IsPatternSupported(UiaCore.UIA patternId)
{
if (patternId == UiaCore.UIA.ValuePatternId)
{
return true;
}

return base.IsPatternSupported(patternId);
}
}
}
}
Loading