Skip to content

Construction of AccessibleObject forces creation of Handle #3062

@RussKie

Description

@RussKie
  • .NET Core Version:
    .NET 5 P4

Problem description:

Multiple code paths involving a construction or an interaction with an AccessibleObject on a control that hasn't had its Handle created cause the creation of the Handle.
This may lead to undesired side-effects like described in #2797.

Expected behavior:

None of AccessibleObject events must be raised if an owner control doesn't have a valid `Handle.

public bool RaiseAutomationNotification(AutomationNotificationKind notificationKind, AutomationNotificationProcessing notificationProcessing, string notificationText)
{
if (!notificationEventAvailable)
{
return false;
}
try
{
// The activityId can be any string. It cannot be null. It is not used currently.
HRESULT result = UiaCore.UiaRaiseNotificationEvent(
this,
notificationKind,
notificationProcessing,
notificationText,
string.Empty);
return result == HRESULT.S_OK;
}
catch (EntryPointNotFoundException)
{
// The UIA Notification event is not available, so don't attempt to raise it again.
notificationEventAvailable = false;
return false;
}
}
/// <summary>
/// Raises the LiveRegionChanged UIA event.
/// This method must be overridden in derived classes that support the UIA live region feature.
/// </summary>
/// <returns>True if operation succeeds, False otherwise.</returns>
public virtual bool RaiseLiveRegionChanged()
{
throw new NotSupportedException(SR.AccessibleObjectLiveRegionNotSupported);
}
internal bool RaiseAutomationEvent(UiaCore.UIA eventId)
{
if (UiaCore.UiaClientsAreListening().IsTrue())
{
HRESULT result = UiaCore.UiaRaiseAutomationEvent(this, eventId);
return result == HRESULT.S_OK;
}
return false;
}
internal bool RaiseAutomationPropertyChangedEvent(UiaCore.UIA propertyId, object oldValue, object newValue)
{
if (UiaCore.UiaClientsAreListening().IsTrue())
{
HRESULT result = UiaCore.UiaRaiseAutomationPropertyChangedEvent(this, propertyId, oldValue, newValue);
return result == HRESULT.S_OK;
}
return false;
}
internal bool RaiseStructureChangedEvent(UiaCore.StructureChangeType structureChangeType, int[] runtimeId)
{
if (UiaCore.UiaClientsAreListening().IsTrue())
{
HRESULT result = UiaCore.UiaRaiseStructureChangedEvent(this, structureChangeType, runtimeId, runtimeId == null ? 0 : runtimeId.Length);
return result == HRESULT.S_OK;
}
return false;
}

Minimal repro:

Run the following test:

[WinFormsFact]
public void ToolStripItem_Select_InvokeWithParent_Success()
{
using var parent = new ToolStrip();
using var item = new SubToolStripItem
{
Parent = parent
};
item.Select();
Assert.True(item.Selected);
Assert.False(parent.IsHandleCreated);
// Select again.
item.Select();
Assert.True(item.Selected);
Assert.False(parent.IsHandleCreated);
}

Line:14014 will cause ToolStripItem.Handle to be created.

 	System.Windows.Forms.dll!System.Windows.Forms.Control.CreateHandle() Line 4912	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.Control.Handle.get() Line 2464	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.Control.ControlAccessibleObject.ControlAccessibleObject(System.Windows.Forms.Control ownerControl = {System.Windows.Forms.ToolStrip}) Line 32	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStrip.ToolStripAccessibleObject.ToolStripAccessibleObject(System.Windows.Forms.ToolStrip owner = {System.Windows.Forms.ToolStrip}) Line 5016	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStrip.CreateAccessibilityInstance() Line 4985	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.Control.AccessibilityObject.get() Line 498	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.ToolStripItemAccessibleObject.FragmentRoot.get() Line 364	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.AccessibleObject.Interop.UiaCore.IRawElementProviderFragment.FragmentRoot.get() Line 819	C#	Symbols loaded.
 	[Native to Managed Transition]		Annotated Frame
 	[Managed to Native Transition]		Annotated Frame
 	System.Windows.Forms.dll!System.Windows.Forms.AccessibleObject.RaiseAutomationEvent(Interop.UiaCore.UIA eventId = AutomationFocusChangedEventId) Line 2267	C#	Symbols loaded.
>	System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.ToolStripItemAccessibleObject.RaiseFocusChanged() Line 481	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.Select() Line 3094	C#	Symbols loaded.
 	System.Windows.Forms.Tests.dll!System.Windows.Forms.Tests.ToolStripItemTests.ToolStripItem_Select_InvokeWithParent_Success() Line 14017	C#	Symbols loaded.

Metadata

Metadata

Labels

🪲 bugProduct bug (most likely)💥 regression-previewRegression from a preview releasetenet-accessibilityMAS violation, UIA issue; problems with accessibility standards

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions