|
//---------------------------------------------------------------------------
//
// <copyright file="Automation.cs" company="Microsoft">
// Copyright (C) Microsoft Corporation. All rights reserved.
// </copyright>
//
//
// Description: Facade class that groups together the main functionality that clients need to get started.
//
// History:
// 06/02/2003 : BrendanM Ported to WCP
// 07/23/2003 : MKarr removed start and includeStart from FindRawElement and FindLogicalElement
//
//---------------------------------------------------------------------------
// PRESHARP: In order to avoid generating warnings about unkown message numbers and unknown pragmas.
#pragma warning disable 1634, 1691
using System.Windows.Automation;
using System.Windows.Automation.Provider;
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Reflection;
using System.Diagnostics;
using MS.Internal.Automation;
using MS.Win32;
namespace System.Windows.Automation
{
/// <summary>
/// Class containing client Automation methods that are not specific to a particular element
/// </summary>
#if (INTERNAL_COMPILE)
internal static class Automation
#else
public static class Automation
#endif
{
//------------------------------------------------------
//
// Public Constants / Readonly Fields
//
//------------------------------------------------------
#region Public Constants and Readonly Fields
/// <summary>Condition that describes the Raw view of the UIAutomation tree</summary>
public static readonly Condition RawViewCondition = Condition.TrueCondition;
/// <summary>Condition that describes the Control view of the UIAutomation tree</summary>
public static readonly Condition ControlViewCondition = new NotCondition(
new PropertyCondition( AutomationElement.IsControlElementProperty, false) );
//
/// <summary>Condition that describes the Content view of the UIAutomation tree</summary>
public static readonly Condition ContentViewCondition = new NotCondition( new OrCondition(
new PropertyCondition( AutomationElement.IsControlElementProperty, false),
new PropertyCondition( AutomationElement.IsContentElementProperty, false)));
#endregion Public Constants and Readonly Fields
//------------------------------------------------------
//
// Public Methods
//
//------------------------------------------------------
#region Public Methods
#region Element Comparisons
/// <summary>
/// Compares two elements, returning true if both refer to the same piece of UI.
/// </summary>
/// <param name="el1">element to compare</param>
/// <param name="el2">element to compare</param>
/// <returns>true if el1 and el2 refer to the same underlying UI</returns>
/// <remarks>Both el1 and el1 must be non-null</remarks>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static bool Compare(AutomationElement el1, AutomationElement el2)
{
return Misc.Compare(el1, el2);
}
/// <summary>
/// Compares two integer arrays, returning true if they have the same contents
/// </summary>
/// <param name="runtimeId1">integer array to compare</param>
/// <param name="runtimeId2">integer array to compare</param>
/// <returns>true if runtimeId1 and runtimeId2 refer to the same underlying UI</returns>
/// <remarks>Both runtimeId1 and runtimeId2 must be non-null. Can be
/// used to compare RuntimeIds from elements.</remarks>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static bool Compare(int[] runtimeId1, int[] runtimeId2)
{
return Misc.Compare(runtimeId1, runtimeId2);
}
#endregion Element Comparisons
#region Misc: Find, Property Names
/// <summary>
/// Get string describing specified property idenfier
/// </summary>
/// <param name="property">property to get string for</param>
/// <returns>Sting containing human-readable name of specified property</returns>
public static string PropertyName( AutomationProperty property )
{
Misc.ValidateArgumentNonNull(property, "property");
// Suppress PRESHARP Parameter to this public method must be validated; element is checked above.
#pragma warning suppress 56506
string full = property.ProgrammaticName.Split('.')[1]; // remove portion before the ".", leaving just "NameProperty" or similar
return full.Substring(0, full.Length - 8); // Slice away "Property" suffix
}
/// <summary>
/// Get string describing specified pattern idenfier
/// </summary>
/// <param name="pattern">pattern to get string for</param>
/// <returns>Sting containing human-readable name of specified pattern</returns>
public static string PatternName( AutomationPattern pattern )
{
Misc.ValidateArgumentNonNull(pattern, "pattern");
// Suppress PRESHARP Parameter to this public method must be validated; element is checked above.
#pragma warning suppress 56506
string full = pattern.ProgrammaticName;
return full.Substring(0, full.Length - 26); // Slice away "InvokePatternIdentifiers.Pattern" to get just "Invoke"
}
#endregion Misc: Find, Property Names
#region Events
/// <summary>
/// Called by a client to add a listener for pattern or custom events.
/// </summary>
/// <param name="eventId">A control pattern or custom event identifier.</param>
/// <param name="element">Element on which to listen for control pattern or custom events.</param>
/// <param name="scope">Specifies whether to listen to property changes events on the specified element, and/or its ancestors and children.</param>
/// <param name="eventHandler">Delegate to call when the specified event occurs.</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void AddAutomationEventHandler(
AutomationEvent eventId,
AutomationElement element,
TreeScope scope,
AutomationEventHandler eventHandler
)
{
Misc.ValidateArgumentNonNull(element, "element" );
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler" );
Misc.ValidateArgument( eventId != AutomationElement.AutomationFocusChangedEvent, SRID.EventIdMustNotBeAutomationFocusChanged );
Misc.ValidateArgument( eventId != AutomationElement.StructureChangedEvent,SRID.EventIdMustNotBeStructureChanged );
Misc.ValidateArgument( eventId != AutomationElement.AutomationPropertyChangedEvent, SRID.EventIdMustNotBeAutomationPropertyChanged );
if (eventId == WindowPattern.WindowClosedEvent)
{
// Once a window closes and the hwnd is destroyed we won't be able to determine where it was in the
// Automation tree; therefore only support WindowClosed events for all windows (eg. src==root and scope
// is descendants) or a specific WindowPattern element (src==root of a Window and scope is the element).
// Also handle odd combinations (eg. src==specific element and scope is subtree|ancestors).
bool paramsValidated = false;
if ( Misc.Compare( element, AutomationElement.RootElement ) )
{
// For root element need to have Descendants scope set (Note: Subtree includes Descendants)
if ( ( scope & TreeScope.Descendants ) == TreeScope.Descendants )
{
paramsValidated = true;
}
}
else
{
// otherwise non-root elements must have the entire tree (Anscestors, Element and Descendants)...
if ( ( scope & ( TreeScope.Ancestors | TreeScope.Element | TreeScope.Descendants ) ) == ( TreeScope.Ancestors | TreeScope.Element | TreeScope.Descendants ) )
{
paramsValidated = true;
}
else if ( ( scope & TreeScope.Element ) == TreeScope.Element )
{
// ...OR Element where the element implements WindowPattern
// PRESHARP will flag this as warning 56506/6506:Parameter 'element' to this public method must be validated: A null-dereference can occur here.
// False positive, element is checked, see above
#pragma warning suppress 6506
object val = element.GetCurrentPropertyValue(AutomationElement.NativeWindowHandleProperty);
if ( val != null && val is int && (int)val != 0 )
{
if ( HwndProxyElementProvider.IsWindowPatternWindow( NativeMethods.HWND.Cast( new IntPtr( (int)val ) ) ) )
{
paramsValidated = true;
}
}
}
}
if ( !paramsValidated )
{
throw new ArgumentException( SR.Get( SRID.ParamsNotApplicableToWindowClosedEvent ) );
}
}
// Add a client-side Handler for for this event request
EventListener l = new EventListener(eventId, scope, null, CacheRequest.CurrentUiaCacheRequest);
ClientEventManager.AddListener(element, eventHandler, l);
}
/// <summary>
/// Called by a client to remove a listener for pattern or custom events.
/// </summary>
/// <param name="eventId">a UIAccess or custom event identifier.</param>
/// <param name="element">Element to remove listener for</param>
/// <param name="eventHandler">The handler object that was passed to AddEventListener</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void RemoveAutomationEventHandler(
AutomationEvent eventId,
AutomationElement element,
AutomationEventHandler eventHandler
)
{
Misc.ValidateArgumentNonNull(element, "element" );
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler" );
Misc.ValidateArgument( eventId != AutomationElement.AutomationFocusChangedEvent, SRID.EventIdMustNotBeAutomationFocusChanged );
Misc.ValidateArgument( eventId != AutomationElement.StructureChangedEvent, SRID.EventIdMustNotBeStructureChanged );
Misc.ValidateArgument( eventId != AutomationElement.AutomationPropertyChangedEvent, SRID.EventIdMustNotBeAutomationPropertyChanged );
//CASRemoval:AutomationPermission.Demand( AutomationPermissionFlag.Read );
// Remove the client-side listener for for this event
ClientEventManager.RemoveListener( eventId, element, eventHandler );
}
/// <summary>
/// Called by a client to add a listener for property changed events.
/// </summary>
/// <param name="element">Element on which to listen for property changed events.</param>
/// <param name="scope">Specifies whether to listen to property changes events on the specified element, and/or its ancestors and children.</param>
/// <param name="eventHandler">Callback object to call when a specified property change occurs.</param>
/// <param name="properties">Params array of properties to listen for changes in.</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void AddAutomationPropertyChangedEventHandler(
AutomationElement element, // reference element for listening to the event
TreeScope scope, // scope to listen to
AutomationPropertyChangedEventHandler eventHandler, // callback object
params AutomationProperty [] properties // listen for changes to these properties
)
{
Misc.ValidateArgumentNonNull(element, "element" );
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler" );
Misc.ValidateArgumentNonNull(properties, "properties" );
if (properties.Length == 0)
{
throw new ArgumentException( SR.Get(SRID.AtLeastOnePropertyMustBeSpecified) );
}
// Check that no properties are interpreted properties
//
foreach (AutomationProperty property in properties)
{
Misc.ValidateArgumentNonNull(property, "properties" );
}
// Add a client-side listener for for this event request
EventListener l = new EventListener(AutomationElement.AutomationPropertyChangedEvent, scope, properties, CacheRequest.CurrentUiaCacheRequest);
ClientEventManager.AddListener(element, eventHandler, l);
}
/// <summary>
/// Called by a client to remove a listener for property changed events.
/// </summary>
/// <param name="element">Element to remove listener for</param>
/// <param name="eventHandler">The handler object that was passed to AutomationPropertyChangedEventHandler</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void RemoveAutomationPropertyChangedEventHandler(
AutomationElement element, // reference element being listened to
AutomationPropertyChangedEventHandler eventHandler // callback object (used as cookie here)
)
{
Misc.ValidateArgumentNonNull(element, "element" );
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler" );
//CASRemoval:AutomationPermission.Demand( AutomationPermissionFlag.Read );
// Remove the client-side listener for for this event
ClientEventManager.RemoveListener(AutomationElement.AutomationPropertyChangedEvent, element, eventHandler);
}
/// <summary>
/// Called by a client to add a listener for structure change events.
/// </summary>
/// <param name="element">Element on which to listen for structure change events.</param>
/// <param name="scope">Specifies whether to listen to property changes events on the specified element, and/or its ancestors and children.</param>
/// <param name="eventHandler">Delegate to call when a structure change event occurs.</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void AddStructureChangedEventHandler(AutomationElement element, TreeScope scope, StructureChangedEventHandler eventHandler)
{
Misc.ValidateArgumentNonNull(element, "element");
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler");
// Add a client-side listener for for this event request
EventListener l = new EventListener(AutomationElement.StructureChangedEvent, scope, null, CacheRequest.CurrentUiaCacheRequest);
ClientEventManager.AddListener(element, eventHandler, l);
}
/// <summary>
/// Called by a client to remove a listener for structure change events.
/// </summary>
/// <param name="element">Element to remove listener for</param>
/// <param name="eventHandler">The handler object that was passed to AddStructureChangedListener</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void RemoveStructureChangedEventHandler(AutomationElement element, StructureChangedEventHandler eventHandler)
{
Misc.ValidateArgumentNonNull(element, "element");
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler");
//CASRemoval:AutomationPermission.Demand(AutomationPermissionFlag.Read);
// Remove the client-side listener for for this event
ClientEventManager.RemoveListener(AutomationElement.StructureChangedEvent, element, eventHandler);
}
/// <summary>
/// Called by a client to add a listener for focus changed events.
/// </summary>
/// <param name="eventHandler">Delegate to call when a focus change event occurs.</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void AddAutomationFocusChangedEventHandler(
AutomationFocusChangedEventHandler eventHandler
)
{
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler" );
// Add a client-side listener for for this event request
EventListener l = new EventListener(AutomationElement.AutomationFocusChangedEvent,
TreeScope.Subtree | TreeScope.Ancestors,
null,
CacheRequest.CurrentUiaCacheRequest);
ClientEventManager.AddFocusListener(eventHandler, l);
}
/// <summary>
/// Called by a client to remove a listener for focus changed events.
/// </summary>
/// <param name="eventHandler">The handler object that was passed to AddAutomationFocusChangedListener</param>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void RemoveAutomationFocusChangedEventHandler(
AutomationFocusChangedEventHandler eventHandler
)
{
Misc.ValidateArgumentNonNull(eventHandler, "eventHandler" );
//CASRemoval:AutomationPermission.Demand( AutomationPermissionFlag.Read );
// Remove the client-side listener for for this event
ClientEventManager.RemoveFocusListener(eventHandler);
}
/// <summary>
/// Called by a client to remove all listeners that the client has added.
/// </summary>
///
/// <outside_see conditional="false">
/// This API does not work inside the secure execution environment.
/// <exception cref="System.Security.Permissions.SecurityPermission"/>
/// </outside_see>
public static void RemoveAllEventHandlers()
{
//CASRemoval:AutomationPermission.Demand( AutomationPermissionFlag.Read );
// Remove the client-side listener for for this event
ClientEventManager.RemoveAllListeners();
}
#endregion Events
#endregion Public Methods
}
}
|