зеркало из https://github.com/dotnet/winforms.git
Fixng 3214 - UIA providers support for Button control (#3215)
This commit is contained in:
Родитель
5797d8e7b0
Коммит
fdb4350682
|
@ -9327,7 +9327,7 @@ virtual System.Windows.Forms.UpDownBase.ValidateEditText() -> void
|
|||
~System.Windows.Forms.BindingSource.Sort.get -> string
|
||||
~System.Windows.Forms.BindingSource.Sort.set -> void
|
||||
~System.Windows.Forms.BindingsCollection.this[int index].get -> System.Windows.Forms.Binding
|
||||
~System.Windows.Forms.ButtonBase.ButtonBaseAccessibleObject.ButtonBaseAccessibleObject(System.Windows.Forms.Control owner) -> void
|
||||
System.Windows.Forms.ButtonBase.ButtonBaseAccessibleObject.ButtonBaseAccessibleObject(System.Windows.Forms.Control! owner) -> void
|
||||
~System.Windows.Forms.ButtonBase.FlatAppearance.get -> System.Windows.Forms.FlatButtonAppearance
|
||||
~System.Windows.Forms.ButtonBase.Image.get -> System.Drawing.Image
|
||||
~System.Windows.Forms.ButtonBase.Image.set -> void
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
~override System.Windows.Forms.Splitter.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject
|
||||
~override System.Windows.Forms.Button.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject
|
||||
System.Windows.Forms.ListViewGroup.TitleImageIndex.get -> int
|
||||
System.Windows.Forms.ListViewGroup.TitleImageIndex.set -> void
|
||||
System.Windows.Forms.ListViewGroup.TitleImageKey.get -> string!
|
||||
|
|
|
@ -6713,4 +6713,7 @@ Stack trace where the illegal operation occurred was:
|
|||
<data name="ListViewGroupImageListDescr" xml:space="preserve">
|
||||
<value>The ImageList control used by the ListView for ListViewGroup images in all views.</value>
|
||||
</data>
|
||||
<data name="ConstructorArgumentInvalidValueType" xml:space="preserve">
|
||||
<value>Argument '{0}' cannot be converted to type '{1}'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Nezpracovaný typ {0}.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Aktivní ovládací prvek.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Unbehandelter Typ {0}.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Das zurzeit aktivierte Steuerelement.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Tipo no controlado {0}.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Control activo actual.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Type {0} non géré.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Le contrôle actuellement actif.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Tipo {0} non gestito.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Controllo correntemente attivo.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">ハンドルされていない型 {0} です。</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">現在アクティブなコントロールです。</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">처리되지 않은 {0} 형식입니다.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">현재 활성 컨트롤입니다.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Nieobsługiwany typ {0}.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Aktualnie aktywny formant.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Tipo {0} não tratado.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">O controle ativo atualmente.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">Необработанный тип {0}.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Активный в текущий момент элемент управления.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">İşlenmemiş {0} türü.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">Şu anda etkin denetim.</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">未处理的类型 {0}。</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">当前处于活动状态的控件。</target>
|
||||
|
|
|
@ -1177,6 +1177,11 @@
|
|||
<target state="translated">未處理的類型 {0}。</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ConstructorArgumentInvalidValueType">
|
||||
<source>Argument '{0}' cannot be converted to type '{1}'.</source>
|
||||
<target state="new">Argument '{0}' cannot be converted to type '{1}'.</target>
|
||||
<note />
|
||||
</trans-unit>
|
||||
<trans-unit id="ContainerControlActiveControlDescr">
|
||||
<source>The currently active control.</source>
|
||||
<target state="translated">目前作用中的控制項。</target>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using static Interop.UiaCore;
|
||||
|
||||
namespace System.Windows.Forms
|
||||
{
|
||||
public partial class Button
|
||||
{
|
||||
internal class ButtonAccessibleObject : ButtonBaseAccessibleObject
|
||||
{
|
||||
public ButtonAccessibleObject(Button owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
internal override object? GetPropertyValue(UIA propertyID)
|
||||
=> propertyID switch
|
||||
{
|
||||
UIA.NamePropertyId
|
||||
=> Name,
|
||||
UIA.AutomationIdPropertyId
|
||||
=> Owner.Name,
|
||||
UIA.ControlTypePropertyId
|
||||
=> UIA.ButtonControlTypeId,
|
||||
UIA.IsKeyboardFocusablePropertyId
|
||||
=>
|
||||
// This is necessary for compatibility with MSAA proxy:
|
||||
// IsKeyboardFocusable = true regardless the control is enabled/disabled.
|
||||
true,
|
||||
UIA.HasKeyboardFocusPropertyId
|
||||
=> Owner.Focused,
|
||||
_ => base.GetPropertyValue(propertyID)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ namespace System.Windows.Forms
|
|||
/// </summary>
|
||||
[SRDescription(nameof(SR.DescriptionButton))]
|
||||
[Designer("System.Windows.Forms.Design.ButtonBaseDesigner, " + AssemblyRef.SystemDesign)]
|
||||
public class Button : ButtonBase, IButtonControl
|
||||
public partial class Button : ButtonBase, IButtonControl
|
||||
{
|
||||
/// <summary>
|
||||
/// The dialog result that will be sent to the parent dialog form when
|
||||
|
@ -87,6 +87,9 @@ namespace System.Windows.Forms
|
|||
}
|
||||
}
|
||||
|
||||
protected override AccessibleObject CreateAccessibilityInstance()
|
||||
=> new ButtonAccessibleObject(this);
|
||||
|
||||
internal override ButtonBaseAdapter CreateFlatAdapter()
|
||||
{
|
||||
return new ButtonFlatAdapter(this);
|
||||
|
@ -182,6 +185,8 @@ namespace System.Windows.Forms
|
|||
}
|
||||
}
|
||||
|
||||
internal override bool SupportsUiaProviders => true;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref='Control.OnMouseEnter'/> event.
|
||||
/// </summary>
|
||||
|
@ -249,6 +254,10 @@ namespace System.Windows.Forms
|
|||
AccessibilityNotifyClients(AccessibleEvents.StateChange, -1);
|
||||
AccessibilityNotifyClients(AccessibleEvents.NameChange, -1);
|
||||
|
||||
// UIA events:
|
||||
AccessibilityObject.RaiseAutomationPropertyChangedEvent(UiaCore.UIA.NamePropertyId, Name, Name);
|
||||
AccessibilityObject.RaiseAutomationEvent(UiaCore.UIA.AutomationPropertyChangedEventId);
|
||||
|
||||
base.OnClick(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace System.Windows.Forms
|
||||
{
|
||||
public partial class ButtonBase
|
||||
{
|
||||
public class ButtonBaseAccessibleObject : ControlAccessibleObject
|
||||
{
|
||||
private readonly ButtonBase _owningButtonBase;
|
||||
|
||||
public ButtonBaseAccessibleObject(Control owner)
|
||||
: base((owner is ButtonBase owningButtonBase) ? owner : throw new ArgumentException(string.Format(SR.ConstructorArgumentInvalidValueType, nameof(Owner), typeof(ButtonBase))))
|
||||
{
|
||||
_owningButtonBase = owningButtonBase;
|
||||
}
|
||||
|
||||
public override AccessibleStates State
|
||||
=> _owningButtonBase.IsHandleCreated && _owningButtonBase.OwnerDraw && _owningButtonBase.MouseIsDown
|
||||
? base.State | AccessibleStates.Pressed
|
||||
: base.State;
|
||||
|
||||
public override void DoDefaultAction()
|
||||
{
|
||||
if (_owningButtonBase.IsHandleCreated)
|
||||
{
|
||||
_owningButtonBase.OnClick(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ namespace System.Windows.Forms
|
|||
/// Implements the basic functionality required by a button control.
|
||||
/// </summary>
|
||||
[Designer("System.Windows.Forms.Design.ButtonBaseDesigner, " + AssemblyRef.SystemDesign)]
|
||||
public abstract class ButtonBase : Control
|
||||
public abstract partial class ButtonBase : Control
|
||||
{
|
||||
private FlatStyle flatStyle = System.Windows.Forms.FlatStyle.Standard;
|
||||
private ContentAlignment imageAlign = ContentAlignment.MiddleCenter;
|
||||
|
@ -1349,33 +1349,5 @@ namespace System.Windows.Forms
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ButtonBaseAccessibleObject : ControlAccessibleObject
|
||||
{
|
||||
public ButtonBaseAccessibleObject(Control owner) : base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public override void DoDefaultAction()
|
||||
{
|
||||
((ButtonBase)Owner).OnClick(EventArgs.Empty);
|
||||
}
|
||||
|
||||
public override AccessibleStates State
|
||||
{
|
||||
get
|
||||
{
|
||||
AccessibleStates state = base.State;
|
||||
|
||||
ButtonBase owner = (ButtonBase)Owner;
|
||||
if (owner.OwnerDraw && owner.MouseIsDown)
|
||||
{
|
||||
state |= AccessibleStates.Pressed;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Xunit;
|
||||
using static Interop.UiaCore;
|
||||
|
||||
namespace System.Windows.Forms.Tests
|
||||
{
|
||||
public class Button_ButtonAccessibleObjectTests
|
||||
{
|
||||
[WinFormsFact]
|
||||
public void ButtonAccessibleObject_Ctor_NullControl_ThrowsArgumentException()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => new Button.ButtonAccessibleObject(null));
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void ButtonAccessibleObject_Ctor_InitializesOwner()
|
||||
{
|
||||
using var button = new Button();
|
||||
Assert.False(button.IsHandleCreated);
|
||||
var buttonAccessibleObject = new Button.ButtonAccessibleObject(button);
|
||||
|
||||
Assert.Same(button, buttonAccessibleObject.Owner);
|
||||
// TODO: ControlAccessibleObject should not force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(button.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void ButtonAccessibleObject_AccessibleRole_Default_ReturnsPushButton()
|
||||
{
|
||||
using var button = new Button
|
||||
{
|
||||
AccessibleRole = AccessibleRole.Default
|
||||
};
|
||||
|
||||
Assert.False(button.IsHandleCreated);
|
||||
var buttonAccessibleObject = new Button.ButtonAccessibleObject(button);
|
||||
|
||||
Assert.Equal(AccessibleRole.PushButton, buttonAccessibleObject.Role);
|
||||
// TODO: ControlAccessibleObject should not force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(button.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void ButtonAccessibleObject_AccessibleRole_Custom_ReturnsExpected()
|
||||
{
|
||||
using var button = new Button
|
||||
{
|
||||
AccessibleRole = AccessibleRole.Link
|
||||
};
|
||||
|
||||
Assert.False(button.IsHandleCreated);
|
||||
var buttonAccessibleObject = new Button.ButtonAccessibleObject(button);
|
||||
|
||||
Assert.Equal(AccessibleRole.Link, buttonAccessibleObject.Role);
|
||||
// TODO: ControlAccessibleObject should not force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(button.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[InlineData((int)UIA.NamePropertyId, "TestName")]
|
||||
[InlineData((int)UIA.ControlTypePropertyId, UIA.ButtonControlTypeId)]
|
||||
[InlineData((int)UIA.IsKeyboardFocusablePropertyId, true)]
|
||||
[InlineData((int)UIA.AutomationIdPropertyId, "Button1")]
|
||||
public void ButtonAccessibleObject_GetPropertyValue_Invoke_ReturnsExpected(int propertyID, object expected)
|
||||
{
|
||||
using var button = new Button
|
||||
{
|
||||
Name = "Button1",
|
||||
AccessibleName = "TestName"
|
||||
};
|
||||
|
||||
Assert.False(button.IsHandleCreated);
|
||||
var buttonAccessibleObject = new Button.ButtonAccessibleObject(button);
|
||||
object value = buttonAccessibleObject.GetPropertyValue((UIA)propertyID);
|
||||
|
||||
Assert.Equal(expected, value);
|
||||
// TODO: ControlAccessibleObject should not force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(button.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void ButtonAccessibleObject_IsPatternSupported_Invoke_ReturnsTrue_ForLegacyIAccessiblePatternId()
|
||||
{
|
||||
using var button = new Button();
|
||||
|
||||
Assert.False(button.IsHandleCreated);
|
||||
var buttonAccessibleObject = new Button.ButtonAccessibleObject(button);
|
||||
|
||||
Assert.True(buttonAccessibleObject.IsPatternSupported(UIA.LegacyIAccessiblePatternId));
|
||||
// TODO: ControlAccessibleObject should not force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(button.IsHandleCreated);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using WinForms.Common.Tests;
|
||||
using Xunit;
|
||||
|
||||
namespace System.Windows.Forms.Tests
|
||||
{
|
||||
public class ButtonBase_ButtonBaseAccessibleObjectTests
|
||||
{
|
||||
[WinFormsFact]
|
||||
public void ButtonBaseAccessibleObject_Ctor_NullControl_ThrowsArgumentException()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => new ButtonBase.ButtonBaseAccessibleObject(null));
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void ButtonBaseAccessibleObject_Ctor_InvalidTypeControl_ThrowsArgumentException()
|
||||
{
|
||||
using var textBox = new TextBox();
|
||||
Assert.Throws<ArgumentException>(() => new ButtonBase.ButtonBaseAccessibleObject(textBox));
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[InlineData(FlatStyle.Flat, true, true, AccessibleStates.Focusable | AccessibleStates.Pressed)]
|
||||
[InlineData(FlatStyle.Flat, false, true, AccessibleStates.Focusable | AccessibleStates.Pressed)]
|
||||
[InlineData(FlatStyle.Flat, true, false, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.Flat, false, false, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.Popup, true, true, AccessibleStates.Focusable | AccessibleStates.Pressed)]
|
||||
[InlineData(FlatStyle.Popup, false, true, AccessibleStates.Focusable | AccessibleStates.Pressed)]
|
||||
[InlineData(FlatStyle.Popup, true, false, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.Popup, false, false, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.Standard, true, true, AccessibleStates.Focusable | AccessibleStates.Pressed)]
|
||||
[InlineData(FlatStyle.Standard, false, true, AccessibleStates.Focusable | AccessibleStates.Pressed)]
|
||||
[InlineData(FlatStyle.Standard, true, false, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.Standard, false, false, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.System, true, true, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.System, false, true, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.System, true, false, AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.System, false, false, AccessibleStates.Focusable)]
|
||||
public void ButtonBaseAccessibleObject_State_is_correct(FlatStyle flatStyle, bool createControl, bool mouseIsDown, AccessibleStates expectedAccessibleState)
|
||||
{
|
||||
using var button = new SubButtonBase()
|
||||
{
|
||||
FlatStyle = flatStyle
|
||||
};
|
||||
|
||||
if (createControl)
|
||||
{
|
||||
button.CreateControl();
|
||||
}
|
||||
|
||||
Assert.Equal(createControl, button.IsHandleCreated);
|
||||
|
||||
if (mouseIsDown)
|
||||
{
|
||||
button.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
|
||||
}
|
||||
|
||||
var buttonBaseAccessibleObject = new ButtonBase.ButtonBaseAccessibleObject(button);
|
||||
|
||||
Assert.Equal(expectedAccessibleState, buttonBaseAccessibleObject.State);
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(button.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[InlineData(true, true, AccessibleRole.Client)]
|
||||
[InlineData(true, false, AccessibleRole.HelpBalloon)]
|
||||
[InlineData(false, true, AccessibleRole.Client)]
|
||||
[InlineData(false, false, AccessibleRole.HelpBalloon)]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeWithRole_ReturnsExpected(bool createControl, bool defaultRole, AccessibleRole expectedAccessibleRole)
|
||||
{
|
||||
using var control = new SubButtonBase();
|
||||
|
||||
if (!defaultRole)
|
||||
{
|
||||
control.AccessibleRole = AccessibleRole.HelpBalloon;
|
||||
}
|
||||
|
||||
if (createControl)
|
||||
{
|
||||
control.CreateControl();
|
||||
}
|
||||
|
||||
Assert.Equal(createControl, control.IsHandleCreated);
|
||||
|
||||
ButtonBase.ButtonBaseAccessibleObject instance = Assert.IsType<ButtonBase.ButtonBaseAccessibleObject>(control.CreateAccessibilityInstance());
|
||||
|
||||
Assert.NotNull(instance);
|
||||
Assert.Same(control, instance.Owner);
|
||||
Assert.Equal(expectedAccessibleRole, instance.Role);
|
||||
Assert.NotSame(control.CreateAccessibilityInstance(), instance);
|
||||
Assert.NotSame(control.AccessibilityObject, instance);
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(FlatStyle))]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeWithDefaultRole_ReturnsExpected_ForAllFlatStyles(FlatStyle flatStyle)
|
||||
{
|
||||
using var control = new SubButtonBase()
|
||||
{
|
||||
FlatStyle = flatStyle
|
||||
};
|
||||
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
ButtonBase.ButtonBaseAccessibleObject instance = Assert.IsType<ButtonBase.ButtonBaseAccessibleObject>(control.CreateAccessibilityInstance());
|
||||
Assert.Equal(AccessibleRole.Client, instance.Role);
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeDoDefaultAction_CallsOnClick(bool createControl)
|
||||
{
|
||||
using var control = new SubButtonBase();
|
||||
|
||||
if (createControl)
|
||||
{
|
||||
control.CreateControl();
|
||||
}
|
||||
|
||||
Assert.Equal(createControl, control.IsHandleCreated);
|
||||
|
||||
int callCount = 0;
|
||||
control.Click += (sender, e) =>
|
||||
{
|
||||
Assert.Same(control, sender);
|
||||
Assert.Same(EventArgs.Empty, e);
|
||||
callCount++;
|
||||
};
|
||||
|
||||
var buttonBaseAccessibleObject = new ButtonBase.ButtonBaseAccessibleObject(control);
|
||||
buttonBaseAccessibleObject.DoDefaultAction();
|
||||
|
||||
Assert.Equal(1, callCount);
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeIButtonControlDoDefaultAction_CallsOnClick(bool createControl)
|
||||
{
|
||||
using var control = new SubButtonBase();
|
||||
|
||||
if (createControl)
|
||||
{
|
||||
control.CreateControl();
|
||||
}
|
||||
|
||||
Assert.Equal(createControl, control.IsHandleCreated);
|
||||
|
||||
int callCount = 0;
|
||||
control.Click += (sender, e) =>
|
||||
{
|
||||
Assert.Same(control, sender);
|
||||
Assert.Same(EventArgs.Empty, e);
|
||||
callCount++;
|
||||
};
|
||||
int performClickCallCount = 0;
|
||||
control.PerformClickAction = () => performClickCallCount++;
|
||||
var buttonBaseAccessibleObject = new ButtonBase.ButtonBaseAccessibleObject(control);
|
||||
|
||||
buttonBaseAccessibleObject.DoDefaultAction();
|
||||
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.Equal(0, performClickCallCount);
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
}
|
||||
|
||||
private class SubButtonBase : ButtonBase
|
||||
{
|
||||
public Action PerformClickAction { get; set; }
|
||||
|
||||
public new AccessibleObject CreateAccessibilityInstance() => base.CreateAccessibilityInstance();
|
||||
|
||||
public new void OnMouseDown(MouseEventArgs e) => base.OnMouseDown(e);
|
||||
|
||||
public void PerformClick() => PerformClickAction();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4490,105 +4490,6 @@ namespace System.Windows.Forms.Tests
|
|||
Assert.Equal(2, callCount);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(FlatStyle))]
|
||||
public void ButtonBase_CreateAccessibilityInstance_Invoke_ReturnsExpected(FlatStyle flatStyle)
|
||||
{
|
||||
using var control = new SubButtonBase
|
||||
{
|
||||
FlatStyle = flatStyle
|
||||
};
|
||||
ButtonBase.ButtonBaseAccessibleObject instance = Assert.IsType<ButtonBase.ButtonBaseAccessibleObject>(control.CreateAccessibilityInstance());
|
||||
Assert.NotNull(instance);
|
||||
Assert.Same(control, instance.Owner);
|
||||
Assert.Equal(AccessibleStates.Focusable, instance.State);
|
||||
Assert.Equal(AccessibleRole.Client, instance.Role);
|
||||
Assert.NotSame(control.CreateAccessibilityInstance(), instance);
|
||||
Assert.NotSame(control.AccessibilityObject, instance);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[InlineData(FlatStyle.Flat, AccessibleStates.Pressed | AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.Popup, AccessibleStates.Pressed | AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.Standard, AccessibleStates.Pressed | AccessibleStates.Focusable)]
|
||||
[InlineData(FlatStyle.System, AccessibleStates.Focusable)]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeMouseDown_ReturnsExpected(FlatStyle flatStyle, AccessibleStates expectedState)
|
||||
{
|
||||
using var control = new SubButtonBase
|
||||
{
|
||||
FlatStyle = flatStyle
|
||||
};
|
||||
control.OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
|
||||
ButtonBase.ButtonBaseAccessibleObject instance = Assert.IsType<ButtonBase.ButtonBaseAccessibleObject>(control.CreateAccessibilityInstance());
|
||||
Assert.NotNull(instance);
|
||||
Assert.Same(control, instance.Owner);
|
||||
Assert.Equal(expectedState, instance.State);
|
||||
Assert.Equal(AccessibleRole.Client, instance.Role);
|
||||
Assert.NotSame(control.CreateAccessibilityInstance(), instance);
|
||||
Assert.NotSame(control.AccessibilityObject, instance);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(FlatStyle))]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeWithCustomRole_ReturnsExpected(FlatStyle flatStyle)
|
||||
{
|
||||
using var control = new SubButtonBase
|
||||
{
|
||||
FlatStyle = flatStyle,
|
||||
AccessibleRole = AccessibleRole.HelpBalloon
|
||||
};
|
||||
ButtonBase.ButtonBaseAccessibleObject instance = Assert.IsType<ButtonBase.ButtonBaseAccessibleObject>(control.CreateAccessibilityInstance());
|
||||
Assert.NotNull(instance);
|
||||
Assert.Same(control, instance.Owner);
|
||||
Assert.Equal(AccessibleStates.Focusable, instance.State);
|
||||
Assert.Equal(AccessibleRole.HelpBalloon, instance.Role);
|
||||
Assert.NotSame(control.CreateAccessibilityInstance(), instance);
|
||||
Assert.NotSame(control.AccessibilityObject, instance);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(FlatStyle))]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeDoDefaultAction_CallsOnClick(FlatStyle flatStyle)
|
||||
{
|
||||
using var control = new SubButtonBase
|
||||
{
|
||||
FlatStyle = flatStyle
|
||||
};
|
||||
int callCount = 0;
|
||||
control.Click += (sender, e) =>
|
||||
{
|
||||
Assert.Same(control, sender);
|
||||
Assert.Same(EventArgs.Empty, e);
|
||||
callCount++;
|
||||
};
|
||||
ButtonBase.ButtonBaseAccessibleObject instance = Assert.IsType<ButtonBase.ButtonBaseAccessibleObject>(control.CreateAccessibilityInstance());
|
||||
instance.DoDefaultAction();
|
||||
Assert.Equal(1, callCount);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
[CommonMemberData(nameof(CommonTestHelper.GetEnumTypeTheoryData), typeof(FlatStyle))]
|
||||
public void ButtonBase_CreateAccessibilityInstance_InvokeIButtonControlDoDefaultAction_CallsOnClick(FlatStyle flatStyle)
|
||||
{
|
||||
using var control = new ButtonControl
|
||||
{
|
||||
FlatStyle = flatStyle
|
||||
};
|
||||
int callCount = 0;
|
||||
control.Click += (sender, e) =>
|
||||
{
|
||||
Assert.Same(control, sender);
|
||||
Assert.Same(EventArgs.Empty, e);
|
||||
callCount++;
|
||||
};
|
||||
int performClickCallCount = 0;
|
||||
control.PerformClickAction = () => performClickCallCount++;
|
||||
ButtonBase.ButtonBaseAccessibleObject instance = Assert.IsType<ButtonBase.ButtonBaseAccessibleObject>(control.CreateAccessibilityInstance());
|
||||
instance.DoDefaultAction();
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.Equal(0, performClickCallCount);
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void ButtonBase_Dispose_Invoke_Success()
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@ using Moq;
|
|||
using WinForms.Common.Tests;
|
||||
using Xunit;
|
||||
using static Interop;
|
||||
using static Interop.UiaCore;
|
||||
using static Interop.User32;
|
||||
|
||||
namespace System.Windows.Forms.Tests
|
||||
|
@ -1813,13 +1814,17 @@ namespace System.Windows.Forms.Tests
|
|||
control.Click += handler;
|
||||
control.OnClick(eventArgs);
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
|
||||
// Remove handler.
|
||||
control.Click -= handler;
|
||||
control.OnClick(eventArgs);
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
|
@ -1849,7 +1854,9 @@ namespace System.Windows.Forms.Tests
|
|||
control.OnClick(eventArgs);
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.Equal(DialogResult.Yes, form.DialogResult);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
Assert.False(parent.IsHandleCreated);
|
||||
Assert.False(form.IsHandleCreated);
|
||||
|
||||
|
@ -1858,7 +1865,9 @@ namespace System.Windows.Forms.Tests
|
|||
control.OnClick(eventArgs);
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.Equal(DialogResult.Yes, form.DialogResult);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
Assert.False(parent.IsHandleCreated);
|
||||
Assert.False(form.IsHandleCreated);
|
||||
}
|
||||
|
@ -2994,13 +3003,17 @@ namespace System.Windows.Forms.Tests
|
|||
control.Click += handler;
|
||||
control.PerformClick();
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
|
||||
// Remove handler.
|
||||
control.Click -= handler;
|
||||
control.PerformClick();
|
||||
Assert.Equal(1, callCount);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(control.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
|
@ -3165,7 +3178,9 @@ namespace System.Windows.Forms.Tests
|
|||
};
|
||||
Assert.Equal(expectedClickCallCount != 0, control.ProcessMnemonic(charCode));
|
||||
Assert.Equal(expectedClickCallCount, clickCallCount);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.Equal(expectedClickCallCount != 0, control.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsTheory]
|
||||
|
@ -3205,6 +3220,24 @@ namespace System.Windows.Forms.Tests
|
|||
Assert.Equal("System.Windows.Forms.Button, Text: ", control.ToString());
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void Button_RaiseAutomationEvent_Invoke_Success()
|
||||
{
|
||||
using var button = new TestButton();
|
||||
Assert.False(button.IsHandleCreated);
|
||||
|
||||
var accessibleObject = (SubButtonAccessibleObject)button.AccessibilityObject;
|
||||
Assert.Equal(0, accessibleObject.RaiseAutomationEventCallsCount);
|
||||
Assert.Equal(0, accessibleObject.RaiseAutomationPropertyChangedEventCallsCount);
|
||||
|
||||
button.PerformClick();
|
||||
|
||||
Assert.Equal(1, accessibleObject.RaiseAutomationEventCallsCount);
|
||||
Assert.Equal(1, accessibleObject.RaiseAutomationPropertyChangedEventCallsCount);
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.True(button.IsHandleCreated);
|
||||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void Button_ToString_InvokeShortText_ReturnsExpected()
|
||||
{
|
||||
|
@ -3463,7 +3496,9 @@ namespace System.Windows.Forms.Tests
|
|||
control.WndProc(ref m);
|
||||
Assert.Equal(expectedResult, m.Result);
|
||||
Assert.Equal(expectedCallCount, callCount);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
|
||||
// TODO: ControlAccessibleObject shouldn't force handle creation, tracked in https://github.com/dotnet/winforms/issues/3062
|
||||
Assert.Equal(expectedCallCount > 0, control.IsHandleCreated);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3603,5 +3638,38 @@ namespace System.Windows.Forms.Tests
|
|||
|
||||
public new void WndProc(ref Message m) => base.WndProc(ref m);
|
||||
}
|
||||
|
||||
private class TestButton : Button
|
||||
{
|
||||
protected override AccessibleObject CreateAccessibilityInstance()
|
||||
{
|
||||
return new SubButtonAccessibleObject(this);
|
||||
}
|
||||
}
|
||||
|
||||
private class SubButtonAccessibleObject : Button.ButtonAccessibleObject
|
||||
{
|
||||
public SubButtonAccessibleObject(Button owner) : base(owner)
|
||||
{
|
||||
RaiseAutomationEventCallsCount = 0;
|
||||
RaiseAutomationPropertyChangedEventCallsCount = 0;
|
||||
}
|
||||
|
||||
public int RaiseAutomationEventCallsCount { get; private set; }
|
||||
|
||||
public int RaiseAutomationPropertyChangedEventCallsCount { get; private set; }
|
||||
|
||||
internal override bool RaiseAutomationEvent(UIA eventId)
|
||||
{
|
||||
RaiseAutomationEventCallsCount++;
|
||||
return base.RaiseAutomationEvent(eventId);
|
||||
}
|
||||
|
||||
internal override bool RaiseAutomationPropertyChangedEvent(UIA propertyId, object oldValue, object newValue)
|
||||
{
|
||||
RaiseAutomationPropertyChangedEventCallsCount++;
|
||||
return base.RaiseAutomationPropertyChangedEvent(propertyId, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче