Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / AccessibleObject.cs / 1305376 / AccessibleObject.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
/*
*/
namespace System.Windows.Forms {
using Accessibility;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Win32;
using System.ComponentModel;
using System.Reflection;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
///
///
/// Provides an implementation for an object that can be inspected by an
/// accessibility application.
///
[ComVisible(true)]
public class AccessibleObject : StandardOleMarshalObject,
IReflect,
IAccessible,
UnsafeNativeMethods.IEnumVariant,
UnsafeNativeMethods.IOleWindow {
// Member variables
///
///
/// Specifies the interface used by this .
///
private IAccessible systemIAccessible = null;
///
///
/// Specifies the
/// used by this .
///
private UnsafeNativeMethods.IEnumVariant systemIEnumVariant = null;
private UnsafeNativeMethods.IEnumVariant enumVariant = null;
// IOleWindow interface of the 'inner' system IAccessible object that we are wrapping
private UnsafeNativeMethods.IOleWindow systemIOleWindow = null;
private bool systemWrapper = false; // Indicates this object is being used ONLY to wrap a system IAccessible
private int accObjId = NativeMethods.OBJID_CLIENT; // Indicates what kind of 'inner' system accessible object we are using
///
public AccessibleObject() {
}
// This constructor is used ONLY for wrapping system IAccessible objects
//
private AccessibleObject(IAccessible iAcc) {
this.systemIAccessible = iAcc;
this.systemWrapper = true;
}
// Properties
///
///
/// Gets the bounds of the accessible object, in screen coordinates.
///
public virtual Rectangle Bounds {
get {
// Use the system provided bounds
if (systemIAccessible != null) {
int left = 0;
int top = 0;
int width = 0;
int height = 0;
try {
systemIAccessible.accLocation(out left, out top, out width, out height, NativeMethods.CHILDID_SELF);
return new Rectangle(left, top, width, height);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return Rectangle.Empty;
}
}
///
///
/// Gets a description of the default action for an object.
///
public virtual string DefaultAction {
get {
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accDefaultAction(NativeMethods.CHILDID_SELF);
}
catch (COMException e) {
// Not all objects provide a default action
//
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
}
///
///
/// Gets a description
/// of the object's visual appearance to the user.
///
public virtual string Description {
get {
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accDescription(NativeMethods.CHILDID_SELF);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
}
private UnsafeNativeMethods.IEnumVariant EnumVariant {
get {
if (enumVariant == null) {
enumVariant = new EnumVariantObject(this);
}
return enumVariant;
}
}
///
///
/// Gets a description of what the object does or how the object is used.
///
public virtual string Help {
get {
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accHelp(NativeMethods.CHILDID_SELF);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
}
///
///
/// Gets the object shortcut key or access key
/// for an accessible object.
///
public virtual string KeyboardShortcut {
get {
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accKeyboardShortcut(NativeMethods.CHILDID_SELF);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
}
///
///
/// Gets
/// or sets the object name.
///
public virtual string Name {
// Does nothing by default
get {
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accName(NativeMethods.CHILDID_SELF);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
set {
if (systemIAccessible != null) {
try {
systemIAccessible.set_accName(NativeMethods.CHILDID_SELF, value);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
}
}
///
///
/// When overridden in a derived class, gets or sets the parent of an accessible object.
///
public virtual AccessibleObject Parent {
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
get {
if (systemIAccessible != null) {
return WrapIAccessible(systemIAccessible.accParent);
}
else {
return null;
}
}
}
///
///
/// Gets the role of this accessible object.
///
public virtual AccessibleRole Role {
get {
if (systemIAccessible != null) {
return (AccessibleRole) systemIAccessible.get_accRole(NativeMethods.CHILDID_SELF);
}
else {
return AccessibleRole.None;
}
}
}
///
///
/// Gets
/// the state of this accessible object.
///
public virtual AccessibleStates State {
get {
if (systemIAccessible != null) {
return (AccessibleStates) systemIAccessible.get_accState(NativeMethods.CHILDID_SELF);
}
else {
return AccessibleStates.None;
}
}
}
///
///
/// Gets or sets the value of an accessible object.
///
public virtual string Value {
// Does nothing by default
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
get {
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accValue(NativeMethods.CHILDID_SELF);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return "";
}
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
set {
if (systemIAccessible != null) {
try {
systemIAccessible.set_accValue(NativeMethods.CHILDID_SELF, value);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
}
}
// Methods
///
///
/// When overridden in a derived class, gets the accessible child corresponding to the specified
/// index.
///
public virtual AccessibleObject GetChild(int index) {
return null;
}
///
///
/// When overridden in a derived class, gets the number of children
/// belonging to an accessible object.
///
public virtual int GetChildCount() {
return -1;
}
///
///
/// Mechanism for overriding default IEnumVariant behavior of the 'inner' system accessible object
/// (IEnumVariant is how a system accessible object exposes its ordered list of child objects).
///
/// USAGE: Overridden method in derived class should return array of integers representing new order
/// to be imposed on the child accessible object collection returned by the system (which
/// we assume will be a set of accessible objects that represent the child windows, in
/// z-order). Each array element contains the original z-order based rank of the child window
/// that is to appear at that position in the new ordering. Note: This array could also be
/// used to filter out unwanted child windows too, if necessary (not recommended).
///
internal virtual int[] GetSysChildOrder() {
return null;
}
///
///
/// Mechanism for overriding default IAccessible.accNavigate behavior of the 'inner' system accessible
/// object (accNavigate is how you move between parent, child and sibling accessible objects).
///
/// USAGE: 'navdir' indicates navigation operation to perform, relative to this accessible object.
/// If operation is unsupported, return false to allow fall-back to default system behavior. Otherwise
/// return destination object in the out parameter, or null to indicate 'off end of list'.
///
internal virtual bool GetSysChild(AccessibleNavigation navdir, out AccessibleObject accessibleObject) {
accessibleObject = null;
return false;
}
///
///
/// When overridden in a derived class,
/// gets the object that has the keyboard focus.
///
public virtual AccessibleObject GetFocused() {
// Default behavior for objects with AccessibleObject children
//
if (GetChildCount() >= 0) {
int count = GetChildCount();
for(int index=0; index < count; ++index) {
AccessibleObject child = GetChild(index);
Debug.Assert(child != null, "GetChild(" + index.ToString(CultureInfo.InvariantCulture) + ") returned null!");
if (child != null && ((child.State & AccessibleStates.Focused) != 0)) {
return child;
}
}
if ((this.State & AccessibleStates.Focused) != 0) {
return this;
}
return null;
}
if (systemIAccessible != null) {
try {
return WrapIAccessible(systemIAccessible.accFocus);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
/// Gets an identifier for a Help topic and the path to the Help file associated
/// with this accessible object.
///
public virtual int GetHelpTopic(out string fileName) {
if (systemIAccessible != null) {
try {
int retVal = systemIAccessible.get_accHelpTopic(out fileName, NativeMethods.CHILDID_SELF);
if (fileName != null && fileName.Length > 0) {
IntSecurity.DemandFileIO(FileIOPermissionAccess.PathDiscovery, fileName);
}
return retVal;
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
fileName = null;
return -1;
}
///
///
/// When overridden in
/// a derived class, gets the currently selected child.
///
public virtual AccessibleObject GetSelected() {
// Default behavior for objects with AccessibleObject children
//
if (GetChildCount() >= 0) {
int count = GetChildCount();
for(int index=0; index < count; ++index) {
AccessibleObject child = GetChild(index);
Debug.Assert(child != null, "GetChild(" + index.ToString(CultureInfo.InvariantCulture) + ") returned null!");
if (child != null && ((child.State & AccessibleStates.Selected) != 0)) {
return child;
}
}
if ((this.State & AccessibleStates.Selected) != 0) {
return this;
}
return null;
}
if (systemIAccessible != null) {
try {
return WrapIAccessible(systemIAccessible.accSelection);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
/// Return the child object at the given screen coordinates.
///
public virtual AccessibleObject HitTest(int x, int y) {
// Default behavior for objects with AccessibleObject children
//
if (GetChildCount() >= 0) {
int count = GetChildCount();
for(int index=0; index < count; ++index) {
AccessibleObject child = GetChild(index);
Debug.Assert(child != null, "GetChild(" + index.ToString(CultureInfo.InvariantCulture) + ") returned null!");
if (child != null && child.Bounds.Contains(x, y)) {
return child;
}
}
return this;
}
if (systemIAccessible != null) {
try {
return WrapIAccessible(systemIAccessible.accHitTest(x, y));
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
if (this.Bounds.Contains(x, y)) {
return this;
}
return null;
}
///
///
///
///
/// Perform the default action
///
///
void IAccessible.accDoDefaultAction(Object childID) {
IntSecurity.UnmanagedCode.Demand();
if (IsClientObject) {
ValidateChildID(ref childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccDoDefaultAction: this = " +
this.ToString() + ", childID = " + childID.ToString());
// If the default action is to be performed on self, do it.
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
DoDefaultAction();
return;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
child.DoDefaultAction();
return;
}
}
if (systemIAccessible != null) {
try {
systemIAccessible.accDoDefaultAction(childID);
}
catch (COMException e) {
// Not all objects provide a default action
//
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
}
///
///
///
///
/// Perform a hit test
///
///
Object IAccessible.accHitTest(
int xLeft,
int yTop) {
if (IsClientObject) {
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccHitTest: this = " +
this.ToString());
AccessibleObject obj = HitTest(xLeft, yTop);
if (obj != null) {
return AsVariant(obj);
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.accHitTest(xLeft, yTop);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
///
/// The location of the Accessible object
///
///
void IAccessible.accLocation(
out int pxLeft,
out int pyTop,
out int pcxWidth,
out int pcyHeight,
Object childID) {
pxLeft = 0;
pyTop = 0;
pcxWidth = 0;
pcyHeight = 0;
if (IsClientObject) {
ValidateChildID(ref childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: this = " +
this.ToString() + ", childID = " + childID.ToString());
// Use the Location function's return value if available
//
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
Rectangle bounds = this.Bounds;
pxLeft = bounds.X;
pyTop = bounds.Y;
pcxWidth = bounds.Width;
pcyHeight = bounds.Height;
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: Returning " +
bounds.ToString());
return;
}
// If we have an accessible object collection, get the appropriate child
//
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
Rectangle bounds = child.Bounds;
pxLeft = bounds.X;
pyTop = bounds.Y;
pcxWidth = bounds.Width;
pcyHeight = bounds.Height;
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: Returning " +
bounds.ToString());
return;
}
}
if (systemIAccessible != null) {
try {
systemIAccessible.accLocation(out pxLeft, out pyTop, out pcxWidth, out pcyHeight, childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: Setting " +
pxLeft.ToString(CultureInfo.InvariantCulture) + ", " +
pyTop.ToString(CultureInfo.InvariantCulture) + ", " +
pcxWidth.ToString(CultureInfo.InvariantCulture) + ", " +
pcyHeight.ToString(CultureInfo.InvariantCulture));
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
return;
}
}
///
///
///
///
/// Navigate to another accessible object.
///
///
Object IAccessible.accNavigate(
int navDir,
Object childID) {
IntSecurity.UnmanagedCode.Demand();
if (IsClientObject) {
ValidateChildID(ref childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccNavigate: this = " +
this.ToString() + ", navdir = " + navDir.ToString(CultureInfo.InvariantCulture) + ", childID = " + childID.ToString());
// Use the Navigate function's return value if available
//
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
AccessibleObject newObject = Navigate((AccessibleNavigation)navDir);
if (newObject != null) {
return AsVariant(newObject);
}
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return AsVariant(child.Navigate((AccessibleNavigation)navDir));
}
}
if (systemIAccessible != null) {
try {
Object retObject;
if (!SysNavigate(navDir, childID, out retObject))
retObject = systemIAccessible.accNavigate(navDir, childID);
return retObject;
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
///
/// Select an accessible object.
///
///
void IAccessible.accSelect(int flagsSelect, Object childID) {
IntSecurity.UnmanagedCode.Demand();
if (IsClientObject) {
ValidateChildID(ref childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccSelect: this = " +
this.ToString() + ", flagsSelect = " + flagsSelect.ToString(CultureInfo.InvariantCulture) + ", childID = " + childID.ToString());
// If the selection is self, do it.
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
Select((AccessibleSelection)flagsSelect); // Uses an Enum which matches SELFLAG
return;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
child.Select((AccessibleSelection)flagsSelect);
return;
}
}
if (systemIAccessible != null) {
try {
systemIAccessible.accSelect(flagsSelect, childID);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
return;
}
}
///
///
/// Performs the default action associated with this accessible object.
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public virtual void DoDefaultAction() {
// By default, just does the system default action if available
//
if (systemIAccessible != null) {
try {
systemIAccessible.accDoDefaultAction(0);
}
catch (COMException e) {
// Not all objects provide a default action
//
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
return;
}
}
///
///
///
///
/// Returns a child Accessible object
///
///
object IAccessible.get_accChild(object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccChild: this = " +
this.ToString() + ", childID = " + childID.ToString());
// Return self for CHILDID_SELF
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return AsIAccessible(this);
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
// Make sure we're not returning ourselves as our own child
//
Debug.Assert(child != this, "An accessible object is returning itself as its own child. This can cause Accessibility client applications to hang.");
if (child == this) {
return null;
}
return AsIAccessible(child);
}
}
// Otherwise, return the default system child for this control (if any)
if (systemIAccessible != null) {
return systemIAccessible.get_accChild(childID);
}
return null;
}
///
///
///
/// Return the number of children
///
int IAccessible.accChildCount {
get {
int childCount = -1;
if (IsClientObject) {
childCount = GetChildCount();
}
if (childCount == -1) {
if (systemIAccessible != null) {
childCount = systemIAccessible.accChildCount;
}
else {
childCount = 0;
}
}
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.accHildCount: this = " + this.ToString() + ", returning " + childCount.ToString(CultureInfo.InvariantCulture));
return childCount;
}
}
///
///
///
///
/// Return the default action
///
///
string IAccessible.get_accDefaultAction(Object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
// Return the default action property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return DefaultAction;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return child.DefaultAction;
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accDefaultAction(childID);
}
catch (COMException e) {
// Not all objects provide a default action
//
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
///
/// Return the object or child description
///
///
string IAccessible.get_accDescription(Object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
// Return the description property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return Description;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return child.Description;
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accDescription(childID);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
/// Returns the appropriate child from the Accessible Child Collection, if available
///
private AccessibleObject GetAccessibleChild(object childID) {
if (!childID.Equals(NativeMethods.CHILDID_SELF)) {
int index = (int)childID - 1; // The first child is childID == 1 (index == 0)
if (index >= 0 && index < GetChildCount()) {
return GetChild(index);
}
}
return null;
}
///
///
///
/// Return the object or child focus
///
object IAccessible.accFocus {
get {
if (IsClientObject) {
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccFocus: this = " +
this.ToString());
AccessibleObject obj = GetFocused();
if (obj != null) {
return AsVariant(obj);
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.accFocus;
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
}
///
///
///
///
/// Return help for this accessible object.
///
///
string IAccessible.get_accHelp(Object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return Help;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return child.Help;
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accHelp(childID);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
///
/// Return the object or child help topic
///
///
int IAccessible.get_accHelpTopic(out string pszHelpFile, Object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return GetHelpTopic(out pszHelpFile);
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return child.GetHelpTopic(out pszHelpFile);
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accHelpTopic(out pszHelpFile, childID);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
pszHelpFile = null;
return -1;
}
///
///
///
///
/// Return the object or child keyboard shortcut
///
///
string IAccessible.get_accKeyboardShortcut(Object childID) {
return get_accKeyboardShortcutInternal(childID);
}
internal virtual string get_accKeyboardShortcutInternal(Object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return KeyboardShortcut;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return child.KeyboardShortcut;
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accKeyboardShortcut(childID);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
///
/// Return the object or child name
///
///
string IAccessible.get_accName(object childID) {
return get_accNameInternal(childID);
}
///
///
internal virtual string get_accNameInternal(object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.get_accName: this = " + this.ToString() +
", childID = " + childID.ToString());
// Return the name property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return Name;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return child.Name;
}
}
// Otherwise, use the system provided name
if (systemIAccessible != null) {
string retval = systemIAccessible.get_accName(childID);
if (IsClientObject) {
if (retval == null || retval.Length == 0) {
retval = Name; // Name the child after its parent
}
}
return retval;
}
return null;
}
///
///
///
/// Return the parent object
///
object IAccessible.accParent {
get {
IntSecurity.UnmanagedCode.Demand();
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.accParent: this = " + this.ToString());
AccessibleObject parent = Parent;
if (parent != null) {
// Some debugging related tests
//
Debug.Assert(parent != this, "An accessible object is returning itself as its own parent. This can cause accessibility clients to hang.");
if (parent == this) {
parent = null; // This should prevent accessibility clients from hanging
}
}
return AsIAccessible(parent);
}
}
///
///
///
///
/// The role property describes an object's purpose in terms of its
/// relationship with sibling or child objects.
///
///
object IAccessible.get_accRole(object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
// Return the role property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return (int)Role;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return (int)child.Role;
}
}
if (systemIAccessible != null) {
return systemIAccessible.get_accRole(childID);
}
return null;
}
///
///
///
/// Return the object or child selection
///
object IAccessible.accSelection {
get {
if (IsClientObject) {
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccSelection: this = " +
this.ToString());
AccessibleObject obj = GetSelected();
if (obj != null) {
return AsVariant(obj);
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.accSelection;
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
}
///
///
///
///
/// Return the object or child state
///
///
object IAccessible.get_accState(object childID) {
if (IsClientObject) {
ValidateChildID(ref childID);
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccState: this = " +
this.ToString() + ", childID = " + childID.ToString());
// Return the state property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return (int)State;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return (int)child.State;
}
}
if (systemIAccessible != null) {
return systemIAccessible.get_accState(childID);
}
return null;
}
///
///
///
///
/// Return the object or child value
///
///
string IAccessible.get_accValue(object childID) {
IntSecurity.UnmanagedCode.Demand();
if (IsClientObject) {
ValidateChildID(ref childID);
// Return the value property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
return Value;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
return child.Value;
}
}
if (systemIAccessible != null) {
try {
return systemIAccessible.get_accValue(childID);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
///
/// Set the object or child name
///
///
void IAccessible.set_accName(
Object childID,
string newName) {
if (IsClientObject) {
ValidateChildID(ref childID);
// Set the name property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
// Attempt to set the name property
Name = newName;
return;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
child.Name = newName;
return;
}
}
if (systemIAccessible != null) {
systemIAccessible.set_accName(childID, newName);
return;
}
}
///
///
///
///
/// Set the object or child value
///
///
void IAccessible.set_accValue(
Object childID,
string newValue) {
IntSecurity.UnmanagedCode.Demand();
if (IsClientObject) {
ValidateChildID(ref childID);
// Set the value property if available
if (childID.Equals(NativeMethods.CHILDID_SELF)) {
// Attempt to set the value property
Value = newValue;
return;
}
// If we have an accessible object collection, get the appropriate child
AccessibleObject child = GetAccessibleChild(childID);
if (child != null) {
child.Value = newValue;
return;
}
}
if (systemIAccessible != null) {
try {
systemIAccessible.set_accValue(childID, newValue);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
return;
}
}
///
///
/// [[....] - Apr04]
///
/// Now that AccessibleObject is used to wrap all system-provided (OLEACC.DLL) accessible
/// objects, it needs to implement IOleWindow and pass this down to the inner object. This is
/// necessary because the OS function WindowFromAccessibleObject() walks up the parent chain
/// looking for the first object that implements IOleWindow, and uses that to get the hwnd.
///
/// But this creates a new problem for AccessibleObjects that do NOT have windows, ie. which
/// represent simple elements. To the OS, these simple elements will now appear to implement
/// IOleWindow, so it will try to get hwnds from them - which they simply cannot provide.
///
/// To work around this problem, the AccessibleObject for a simple element will delegate all
/// IOleWindow calls up the parent chain itself. This will stop at the first window-based
/// accessible object, which will be able to return an hwnd back to the OS. So we are
/// effectively 'preempting' what WindowFromAccessibleObject() would do.
///
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
int UnsafeNativeMethods.IOleWindow.GetWindow(out IntPtr hwnd) {
// See if we have an inner object that can provide the window handle
if (systemIOleWindow != null) {
return systemIOleWindow.GetWindow(out hwnd);
}
// Otherwise delegate to the parent object
AccessibleObject parent = this.Parent;
if (parent is UnsafeNativeMethods.IOleWindow) {
return (parent as UnsafeNativeMethods.IOleWindow).GetWindow(out hwnd);
}
// Or fail if there is no parent
hwnd = IntPtr.Zero;
return NativeMethods.E_FAIL;
}
///
///
/// See GetWindow() above for details.
///
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
void UnsafeNativeMethods.IOleWindow.ContextSensitiveHelp(int fEnterMode) {
// See if we have an inner object that can provide help
if (systemIOleWindow != null) {
systemIOleWindow.ContextSensitiveHelp(fEnterMode);
return;
}
// Otherwise delegate to the parent object
AccessibleObject parent = this.Parent;
if (parent is UnsafeNativeMethods.IOleWindow) {
(parent as UnsafeNativeMethods.IOleWindow).ContextSensitiveHelp(fEnterMode);
return;
}
// Or do nothing if there is no parent
}
///
///
///
/// Clone this accessible object.
///
///
void UnsafeNativeMethods.IEnumVariant.Clone(UnsafeNativeMethods.IEnumVariant[] v) {
EnumVariant.Clone(v);
}
///
///
///
/// Obtain the next n children of this accessible object.
///
///
int UnsafeNativeMethods.IEnumVariant.Next(int n, IntPtr rgvar, int[] ns) {
return EnumVariant.Next(n, rgvar, ns);
}
///
///
/// Resets the child accessible object enumerator.
///
void UnsafeNativeMethods.IEnumVariant.Reset() {
EnumVariant.Reset();
}
///
///
///
/// Skip the next n child accessible objects
///
///
void UnsafeNativeMethods.IEnumVariant.Skip(int n) {
EnumVariant.Skip(n);
}
///
///
/// When overridden in a derived class,
/// navigates to another object.
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public virtual AccessibleObject Navigate(AccessibleNavigation navdir) {
// Some default behavior for objects with AccessibleObject children
//
if (GetChildCount() >= 0) {
switch(navdir) {
case AccessibleNavigation.FirstChild:
return GetChild(0);
case AccessibleNavigation.LastChild:
return GetChild(GetChildCount() - 1);
case AccessibleNavigation.Previous:
case AccessibleNavigation.Up:
case AccessibleNavigation.Left:
if (Parent.GetChildCount() > 0) {
return null;
}
break;
case AccessibleNavigation.Next:
case AccessibleNavigation.Down:
case AccessibleNavigation.Right:
if (Parent.GetChildCount() > 0) {
return null;
}
break;
}
}
if (systemIAccessible != null) {
try {
object retObject = null;
if (!SysNavigate((int)navdir, NativeMethods.CHILDID_SELF, out retObject))
retObject = systemIAccessible.accNavigate((int)navdir, NativeMethods.CHILDID_SELF);
return WrapIAccessible(retObject);
}
catch (COMException e) {
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
}
return null;
}
///
///
///
/// Selects this accessible object.
///
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public virtual void Select(AccessibleSelection flags) {
// By default, do the system behavior
//
if (systemIAccessible != null) {
try {
systemIAccessible.accSelect((int)flags, 0);
}
catch (COMException e) {
// Not all objects provide the select function
//
if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
throw e;
}
}
return;
}
}
private object AsVariant(AccessibleObject obj) {
if (obj == this) {
return NativeMethods.CHILDID_SELF;
}
return AsIAccessible(obj);
}
private IAccessible AsIAccessible(AccessibleObject obj) {
if (obj != null && obj.systemWrapper) {
return obj.systemIAccessible;
}
return obj;
}
///
///
/// Indicates what kind of 'inner' system accessible object we are using as our fall-back
/// implementation of IAccessible (when the systemIAccessible member is not null). The inner
/// object is provided by OLEACC.DLL. Note that although the term 'id' is used, this value
/// really represents a category or type of accessible object. Ids are only unique among
/// accessible objects associated with the same window handle. Currently supported ids are...
///
/// OBJID_CLIENT - represents the window's client area (including any child windows)
/// OBJID_WINDOW - represents the window's non-client area (including caption, frame controls and scrollbars)
///
/// NOTE: When the id is OBJID_WINDOW, we short-circuit most of the virtual override behavior of
/// AccessibleObject, and turn the object into a simple wrapper around the inner system object. So
/// for a *user-defined* accessible object, that has NO inner object, its important that the id is
/// left as OBJID_CLIENT, otherwise the object will be short-circuited into a total NOP!
///
///
internal int AccessibleObjectId {
get {
return accObjId;
}
set {
accObjId = value;
}
}
///
///
/// Indicates whether this accessible object represents the client area of the window.
///
///
internal bool IsClientObject {
get {
return AccessibleObjectId == NativeMethods.OBJID_CLIENT;
}
}
///
///
/// Indicates whether this accessible object represents the non-client area of the window.
///
///
internal bool IsNonClientObject {
get {
return AccessibleObjectId == NativeMethods.OBJID_WINDOW;
}
}
///
///
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
internal IAccessible GetSystemIAccessibleInternal() {
return this.systemIAccessible;
}
///
///
/// [To be supplied.]
///
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected void UseStdAccessibleObjects(IntPtr handle) {
UseStdAccessibleObjects(handle, AccessibleObjectId);
}
///
///
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected void UseStdAccessibleObjects(IntPtr handle, int objid) {
// Get a standard accessible Object
Guid IID_IAccessible = new Guid(NativeMethods.uuid_IAccessible);
object acc = null;
int result = UnsafeNativeMethods.CreateStdAccessibleObject(
new HandleRef(this, handle),
objid,
ref IID_IAccessible,
ref acc);
// Get the IEnumVariant interface
Guid IID_IEnumVariant = new Guid(NativeMethods.uuid_IEnumVariant);
object en = null;
result = UnsafeNativeMethods.CreateStdAccessibleObject(
new HandleRef(this, handle),
objid,
ref IID_IEnumVariant,
ref en);
Debug.Assert(acc != null, "SystemIAccessible is null");
Debug.Assert(en != null, "SystemIEnumVariant is null");
if (acc != null || en != null) {
systemIAccessible = (IAccessible)acc;
systemIEnumVariant = (UnsafeNativeMethods.IEnumVariant)en;
systemIOleWindow = acc as UnsafeNativeMethods.IOleWindow;
}
}
///
/// Performs custom navigation between parent/child/sibling accessible objects. This is basically
/// just a wrapper for GetSysChild(), that does some of the dirty work, such as wrapping the
/// returned object in a VARIANT. Usage is similar to GetSysChild(). Called prior to calling
/// IAccessible.accNavigate on the 'inner' system accessible object.
///
///
private bool SysNavigate(int navDir, Object childID, out Object retObject) {
retObject = null;
// Only override system navigation relative to ourselves (since we can't interpret OLEACC child ids)
if (!childID.Equals(NativeMethods.CHILDID_SELF))
return false;
// Perform any supported navigation operation (fall back on system for unsupported navigation ops)
AccessibleObject newObject;
if (!GetSysChild((AccessibleNavigation) navDir, out newObject))
return false;
// If object found, wrap in a VARIANT. Otherwise return null for 'end of list' (OLEACC expects this)
retObject = (newObject == null) ? null : AsVariant(newObject);
// Tell caller not to fall back on system behavior now
return true;
}
///
///
/// Make sure that the childID is valid.
///
internal void ValidateChildID(ref object childID) {
// An empty childID is considered to be the same as CHILDID_SELF.
// Some accessibility programs pass null into our functions, so we
// need to convert them here.
if (childID == null) {
childID = NativeMethods.CHILDID_SELF;
}
else if (childID.Equals(NativeMethods.DISP_E_PARAMNOTFOUND)) {
childID = 0;
}
else if (!(childID is Int32)) {
// AccExplorer seems to occasionally pass in objects instead of an int ChildID.
//
childID = 0;
}
}
private AccessibleObject WrapIAccessible(object iacc) {
IAccessible accessible = iacc as IAccessible;
if (accessible == null) {
return null;
}
// Check to see if this object already wraps iacc
//
if (this.systemIAccessible == iacc) {
return this;
}
return new AccessibleObject(accessible);
}
///
///
///
/// Return the requested method if it is implemented by the Reflection object. The
/// match is based upon the name and DescriptorInfo which describes the signature
/// of the method.
///
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) {
return typeof(IAccessible).GetMethod(name, bindingAttr, binder, types, modifiers);
}
///
///
///
/// Return the requested method if it is implemented by the Reflection object. The
/// match is based upon the name of the method. If the object implementes multiple methods
/// with the same name an AmbiguousMatchException is thrown.
///
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) {
return typeof(IAccessible).GetMethod(name, bindingAttr);
}
///
///
MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) {
return typeof(IAccessible).GetMethods(bindingAttr);
}
///
///
///
/// Return the requestion field if it is implemented by the Reflection object. The
/// match is based upon a name. There cannot be more than a single field with
/// a name.
///
FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) {
return typeof(IAccessible).GetField(name, bindingAttr);
}
///
///
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) {
return typeof(IAccessible).GetFields(bindingAttr);
}
///
///
///
/// Return the property based upon name. If more than one property has the given
/// name an AmbiguousMatchException will be thrown. Returns null if no property
/// is found.
///
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) {
return typeof(IAccessible).GetProperty(name, bindingAttr);
}
///
///
///
/// Return the property based upon the name and Descriptor info describing the property
/// indexing. Return null if no property is found.
///
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
return typeof(IAccessible).GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}
///
///
///
/// Returns an array of PropertyInfos for all the properties defined on
/// the Reflection object.
///
PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) {
return typeof(IAccessible).GetProperties(bindingAttr);
}
///
///
///
/// Return an array of members which match the passed in name.
///
MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) {
return typeof(IAccessible).GetMember(name, bindingAttr);
}
///
///
///
/// Return an array of all of the members defined for this object.
///
MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) {
return typeof(IAccessible).GetMembers(bindingAttr);
}
///
///
///
/// Description of the Binding Process.
/// We must invoke a method that is accessable and for which the provided
/// parameters have the most specific match. A method may be called if
/// 1. The number of parameters in the method declaration equals the number of
/// arguments provided to the invocation
/// 2. The type of each argument can be converted by the binder to the
/// type of the type of the parameter.
///
/// The binder will find all of the matching methods. These method are found based
/// upon the type of binding requested (MethodInvoke, Get/Set Properties). The set
/// of methods is filtered by the name, number of arguments and a set of search modifiers
/// defined in the Binder.
///
/// After the method is selected, it will be invoked. Accessability is checked
/// at that point. The search may be control which set of methods are searched based
/// upon the accessibility attribute associated with the method.
///
/// The BindToMethod method is responsible for selecting the method to be invoked.
/// For the default binder, the most specific method will be selected.
///
/// This will invoke a specific member...
/// @exception If invokeAttr is CreateInstance then all other
/// Access types must be undefined. If not we throw an ArgumentException.
/// @exception If the invokeAttr is not CreateInstance then an
/// ArgumentException when name is null.
/// @exception ArgumentException when invokeAttr does not specify the type
/// @exception ArgumentException when invokeAttr specifies both get and set of
/// a property or field.
/// @exception ArgumentException when invokeAttr specifies property set and
/// invoke method.
///
object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) {
if (args.Length == 0) {
MemberInfo[] member = typeof(IAccessible).GetMember(name);
if (member != null && member.Length > 0 && member[0] is PropertyInfo) {
MethodInfo getMethod = ((PropertyInfo)member[0]).GetGetMethod();
if (getMethod != null && getMethod.GetParameters().Length > 0) {
args = new object[getMethod.GetParameters().Length];
for (int i = 0; i < args.Length; i++) {
args[i] = NativeMethods.CHILDID_SELF;
}
}
}
}
return typeof(IAccessible).InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
///
///
///
/// Return the underlying Type that represents the IReflect Object. For expando object,
/// this is the (Object) IReflectInstance.GetType(). For Type object it is this.
///
Type IReflect.UnderlyingSystemType {
get {
return typeof(IAccessible);
}
}
private class EnumVariantObject : UnsafeNativeMethods.IEnumVariant {
private int currentChild = 0;
private AccessibleObject owner;
public EnumVariantObject(AccessibleObject owner) {
Debug.Assert(owner != null, "Cannot create EnumVariantObject with a null owner");
this.owner = owner;
}
public EnumVariantObject(AccessibleObject owner, int currentChild) {
Debug.Assert(owner != null, "Cannot create EnumVariantObject with a null owner");
this.owner = owner;
this.currentChild = currentChild;
}
void UnsafeNativeMethods.IEnumVariant.Clone(UnsafeNativeMethods.IEnumVariant[] v) {
v[0] = new EnumVariantObject(owner, currentChild);
}
///
///
/// Resets the child accessible object enumerator.
///
void UnsafeNativeMethods.IEnumVariant.Reset() {
currentChild = 0;
// SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
// (allow access to children of an AccessibleObject in partial trust).
//
IntSecurity.UnmanagedCode.Assert();
try {
if (owner.systemIEnumVariant != null)
owner.systemIEnumVariant.Reset();
}
finally {
CodeAccessPermission.RevertAssert();
}
}
///
///
/// Skips the next n child accessible objects.
///
void UnsafeNativeMethods.IEnumVariant.Skip(int n) {
currentChild += n;
// SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
// (allow access to children of an AccessibleObject in partial trust).
//
IntSecurity.UnmanagedCode.Assert();
try {
if (owner.systemIEnumVariant != null)
owner.systemIEnumVariant.Skip(n);
}
finally {
CodeAccessPermission.RevertAssert();
}
}
///
///
/// Gets the next n child accessible objects.
///
int UnsafeNativeMethods.IEnumVariant.Next(int n, IntPtr rgvar, int[] ns) {
// NOTE: rgvar is a pointer to an array of variants
if (owner.IsClientObject) {
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "EnumVariantObject: owner = " + owner.ToString() + ", n = " + n);
Debug.Indent();
int childCount;
int[] newOrder;
if ((childCount = owner.GetChildCount()) >= 0)
NextFromChildCollection(n, rgvar, ns, childCount);
else if (owner.systemIEnumVariant == null)
NextEmpty(n, rgvar, ns);
else if ((newOrder = owner.GetSysChildOrder()) != null)
NextFromSystemReordered(n, rgvar, ns, newOrder);
else
NextFromSystem(n, rgvar, ns);
Debug.Unindent();
}
else {
NextFromSystem(n, rgvar, ns);
}
// Tell caller whether requested number of items was returned. Once list of items has
// been exhausted, we return S_FALSE so that caller knows to stop calling this method.
return (ns[0] == n) ? NativeMethods.S_OK : NativeMethods.S_FALSE;
}
///
/// When we have the IEnumVariant of an accessible proxy provided by the system (ie.
/// OLEACC.DLL), we can fall back on that to return the children. Generally, the system
/// proxy will enumerate the child windows, create a suitable kind of child accessible
/// proxy for each one, and return a set of IDispatch interfaces to these proxy objects.
///
private void NextFromSystem(int n, IntPtr rgvar, int[] ns) {
// SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
// (allow access to children of an AccessibleObject in partial trust).
//
IntSecurity.UnmanagedCode.Assert();
try {
owner.systemIEnumVariant.Next(n, rgvar, ns);
}
finally {
CodeAccessPermission.RevertAssert();
}
currentChild += ns[0];
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: Delegating to systemIEnumVariant");
}
///
/// Sometimes we want to rely on the system-provided behavior to create and return child
/// accessible objects, but we want to impose a new order on those objects (or even filter
/// some objects out).
///
/// This method takes an array of ints that dictates the new order. It queries the system
/// for each child individually, and inserts the result into the correct *new* position.
///
/// Note: This code has to make certain *assumptions* about OLEACC.DLL proxy object behavior.
/// However, this behavior is well documented. We *assume* the proxy will return a set of
/// child accessible objects that correspond 1:1 with the owning control's child windows,
/// and that the default order it returns these objects in is z-order (which also happens
/// to be the order that children appear in the Control.Controls[] collection).
///
private void NextFromSystemReordered(int n, IntPtr rgvar, int[] ns, int[] newOrder) {
int i;
for (i = 0; i < n && currentChild < newOrder.Length; ++i) {
if (!GotoItem(owner.systemIEnumVariant, newOrder[currentChild], GetAddressOfVariantAtIndex(rgvar, i)))
break;
++currentChild;
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: adding sys child " + currentChild + " of " + newOrder.Length);
}
ns[0] = i;
}
///
/// If we have our own custom accessible child collection, return a set of 1-based integer
/// child ids, that the caller will eventually pass back to us via IAccessible.get_accChild().
///
private void NextFromChildCollection(int n, IntPtr rgvar, int[] ns, int childCount) {
int i;
for (i = 0; i < n && currentChild < childCount; ++i) {
++currentChild;
Marshal.GetNativeVariantForObject(((object) currentChild), GetAddressOfVariantAtIndex(rgvar, i));
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: adding own child " + currentChild + " of " + childCount);
}
ns[0] = i;
}
///
/// Default behavior if there is no custom child collection or system-provided
/// proxy to fall back on. In this case, we return an empty child collection.
///
private void NextEmpty(int n, IntPtr rgvar, int[] ns) {
ns[0] = 0;
Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: no children to add");
}
///
/// Given an IEnumVariant interface, this method jumps to a specific
/// item in the collection and extracts the result for that one item.
///
private static bool GotoItem(UnsafeNativeMethods.IEnumVariant iev, int index, IntPtr variantPtr) {
int[] ns = new int[1];
// SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
// (allow access to children of an AccessibleObject in partial trust).
//
IntSecurity.UnmanagedCode.Assert();
try {
iev.Reset();
iev.Skip(index);
iev.Next(1, variantPtr, ns);
}
finally {
CodeAccessPermission.RevertAssert();
}
return (ns[0] == 1);
}
///
/// Given an array of pointers to variants, calculate address of a given array element.
///
private static IntPtr GetAddressOfVariantAtIndex(IntPtr variantArrayPtr, int index) {
int variantSize = 8 + (IntPtr.Size * 2);
return (IntPtr) ((ulong) variantArrayPtr + ((ulong) index) * ((ulong) variantSize));
}
}
} // end class AccessibleObject
///
/// Internal object passed out to OLEACC clients via WM_GETOBJECT.
/// NOTE: THIS CLASS IS INTERNAL FOR SECURITY REASONS AND SHOULD REMAIN SO!
///
internal sealed class InternalAccessibleObject : StandardOleMarshalObject,
UnsafeNativeMethods.IAccessibleInternal,
System.Reflection.IReflect,
UnsafeNativeMethods.IEnumVariant,
UnsafeNativeMethods.IOleWindow {
private IAccessible publicIAccessible; // AccessibleObject as IAccessible
private UnsafeNativeMethods.IEnumVariant publicIEnumVariant; // AccessibleObject as IEnumVariant
private UnsafeNativeMethods.IOleWindow publicIOleWindow; // AccessibleObject as IOleWindow
private IReflect publicIReflect; // AccessibleObject as IReflect
///
/// Create a new wrapper. Protect this with UnmanagedCode Permission
///
[
SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)
]
internal InternalAccessibleObject(AccessibleObject accessibleImplemention) {
// Get all the casts done here to catch any issues early
publicIAccessible = (IAccessible) accessibleImplemention;
publicIEnumVariant = (UnsafeNativeMethods.IEnumVariant) accessibleImplemention;
publicIOleWindow = (UnsafeNativeMethods.IOleWindow) accessibleImplemention;
publicIReflect = (IReflect) accessibleImplemention;
// Note: Deliberately not holding onto AccessibleObject to enforce all access through the interfaces
}
///
/// If the given object is an AccessibleObject return it as a InternalAccessibleObject
/// This ensures we wrap all AccessibleObjects before handing them out to OLEACC
///
private object AsNativeAccessible(object accObject) {
if (accObject is AccessibleObject) {
return new InternalAccessibleObject(accObject as AccessibleObject);
}
else {
return accObject;
}
}
//
// IAccessibleInternal implementation...
//
void UnsafeNativeMethods.IAccessibleInternal.accDoDefaultAction(object childID) {
IntSecurity.UnmanagedCode.Assert();
publicIAccessible.accDoDefaultAction(childID);
}
object UnsafeNativeMethods.IAccessibleInternal.accHitTest(int xLeft, int yTop) {
IntSecurity.UnmanagedCode.Assert();
return AsNativeAccessible(publicIAccessible.accHitTest(xLeft, yTop));
}
void UnsafeNativeMethods.IAccessibleInternal.accLocation(out int l, out int t, out int w, out int h, Object childID) {
IntSecurity.UnmanagedCode.Assert();
publicIAccessible.accLocation(out l, out t, out w, out h, childID);
}
object UnsafeNativeMethods.IAccessibleInternal.accNavigate(int navDir, object childID) {
IntSecurity.UnmanagedCode.Assert();
return AsNativeAccessible(publicIAccessible.accNavigate(navDir, childID));
}
void UnsafeNativeMethods.IAccessibleInternal.accSelect(int flagsSelect, Object childID) {
IntSecurity.UnmanagedCode.Assert();
publicIAccessible.accSelect(flagsSelect, childID);
}
object UnsafeNativeMethods.IAccessibleInternal.get_accChild(object childID) {
IntSecurity.UnmanagedCode.Assert();
return AsNativeAccessible(publicIAccessible.get_accChild(childID));
}
int UnsafeNativeMethods.IAccessibleInternal.get_accChildCount() {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.accChildCount;
}
string UnsafeNativeMethods.IAccessibleInternal.get_accDefaultAction(Object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accDefaultAction(childID);
}
string UnsafeNativeMethods.IAccessibleInternal.get_accDescription(Object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accDescription(childID);
}
object UnsafeNativeMethods.IAccessibleInternal.get_accFocus() {
IntSecurity.UnmanagedCode.Assert();
return AsNativeAccessible(publicIAccessible.accFocus);
}
string UnsafeNativeMethods.IAccessibleInternal.get_accHelp(Object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accHelp(childID);
}
int UnsafeNativeMethods.IAccessibleInternal.get_accHelpTopic(out string pszHelpFile, Object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accHelpTopic(out pszHelpFile, childID);
}
string UnsafeNativeMethods.IAccessibleInternal.get_accKeyboardShortcut(Object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accKeyboardShortcut(childID);
}
string UnsafeNativeMethods.IAccessibleInternal.get_accName(Object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accName(childID);
}
object UnsafeNativeMethods.IAccessibleInternal.get_accParent() {
IntSecurity.UnmanagedCode.Assert();
return AsNativeAccessible(publicIAccessible.accParent);
}
object UnsafeNativeMethods.IAccessibleInternal.get_accRole(object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accRole(childID);
}
object UnsafeNativeMethods.IAccessibleInternal.get_accSelection() {
IntSecurity.UnmanagedCode.Assert();
return AsNativeAccessible(publicIAccessible.accSelection);
}
object UnsafeNativeMethods.IAccessibleInternal.get_accState(object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accState(childID);
}
string UnsafeNativeMethods.IAccessibleInternal.get_accValue(object childID) {
IntSecurity.UnmanagedCode.Assert();
return publicIAccessible.get_accValue(childID);
}
void UnsafeNativeMethods.IAccessibleInternal.set_accName(Object childID, string newName) {
IntSecurity.UnmanagedCode.Assert();
publicIAccessible.set_accName(childID, newName);
}
void UnsafeNativeMethods.IAccessibleInternal.set_accValue(Object childID, string newValue) {
IntSecurity.UnmanagedCode.Assert();
publicIAccessible.set_accValue(childID, newValue);
}
//
// IEnumVariant implementation...
//
void UnsafeNativeMethods.IEnumVariant.Clone(UnsafeNativeMethods.IEnumVariant[] v) {
IntSecurity.UnmanagedCode.Assert();
publicIEnumVariant.Clone(v);
}
int UnsafeNativeMethods.IEnumVariant.Next(int n, IntPtr rgvar, int[] ns) {
IntSecurity.UnmanagedCode.Assert();
return publicIEnumVariant.Next(n, rgvar, ns);
}
void UnsafeNativeMethods.IEnumVariant.Reset() {
IntSecurity.UnmanagedCode.Assert();
publicIEnumVariant.Reset();
}
void UnsafeNativeMethods.IEnumVariant.Skip(int n) {
IntSecurity.UnmanagedCode.Assert();
publicIEnumVariant.Skip(n);
}
//
// IOleWindow implementation...
//
int UnsafeNativeMethods.IOleWindow.GetWindow(out IntPtr hwnd) {
IntSecurity.UnmanagedCode.Assert();
return publicIOleWindow.GetWindow(out hwnd);
}
void UnsafeNativeMethods.IOleWindow.ContextSensitiveHelp(int fEnterMode) {
IntSecurity.UnmanagedCode.Assert();
publicIOleWindow.ContextSensitiveHelp(fEnterMode);
}
//
// IReflect implementation...
//
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) {
return publicIReflect.GetMethod(name, bindingAttr, binder, types, modifiers);
}
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) {
return publicIReflect.GetMethod(name, bindingAttr);
}
MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) {
return publicIReflect.GetMethods(bindingAttr);
}
FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) {
return publicIReflect.GetField(name, bindingAttr);
}
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) {
return publicIReflect.GetFields(bindingAttr);
}
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) {
return publicIReflect.GetProperty(name, bindingAttr);
}
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
return publicIReflect.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}
PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) {
return publicIReflect.GetProperties(bindingAttr);
}
MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) {
return publicIReflect.GetMember(name, bindingAttr);
}
MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) {
return publicIReflect.GetMembers(bindingAttr);
}
object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) {
IntSecurity.UnmanagedCode.Demand();
return publicIReflect.InvokeMember(name, invokeAttr, binder, publicIAccessible, args, modifiers, culture, namedParameters);
}
Type IReflect.UnderlyingSystemType {
get {
IReflect r = publicIReflect;
return publicIReflect.UnderlyingSystemType;
}
}
} // end class InternalAccessibleObject
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AddInSegmentDirectoryNotFoundException.cs
- Rules.cs
- AssemblyInfo.cs
- HierarchicalDataSourceControl.cs
- AppDomain.cs
- PartialList.cs
- SmiRequestExecutor.cs
- ParameterBuilder.cs
- OdbcCommandBuilder.cs
- AuthenticationException.cs
- PropertyDescriptors.cs
- UIElementAutomationPeer.cs
- CodeDOMUtility.cs
- XmlImplementation.cs
- InvalidOperationException.cs
- DocumentReferenceCollection.cs
- PropertyEmitter.cs
- DependencyObject.cs
- IncrementalCompileAnalyzer.cs
- TokenizerHelper.cs
- DocComment.cs
- TrustLevel.cs
- ToolStripSeparatorRenderEventArgs.cs
- SystemPens.cs
- UserPersonalizationStateInfo.cs
- RowBinding.cs
- DataGridViewRowCollection.cs
- ReadOnlyCollectionBuilder.cs
- DocumentPage.cs
- ToolStripRendererSwitcher.cs
- FieldMetadata.cs
- LockedAssemblyCache.cs
- KeyPullup.cs
- odbcmetadatacolumnnames.cs
- IndexerHelper.cs
- OptimizedTemplateContentHelper.cs
- SapiRecoContext.cs
- CustomErrorCollection.cs
- TextEditorContextMenu.cs
- GridItem.cs
- BaseCollection.cs
- LineServicesRun.cs
- CapabilitiesRule.cs
- DataColumnChangeEvent.cs
- RawStylusSystemGestureInputReport.cs
- OracleParameter.cs
- DateTime.cs
- SourceElementsCollection.cs
- WinEventHandler.cs
- SessionStateModule.cs
- Number.cs
- TypeBuilderInstantiation.cs
- Ipv6Element.cs
- UserPersonalizationStateInfo.cs
- GraphicsContext.cs
- DocumentPageView.cs
- PKCS1MaskGenerationMethod.cs
- SortFieldComparer.cs
- PartialTrustHelpers.cs
- XmlDocumentFieldSchema.cs
- TextContainer.cs
- CriticalFileToken.cs
- SqlClientFactory.cs
- IdleTimeoutMonitor.cs
- StyleSelector.cs
- GenerateHelper.cs
- TargetControlTypeAttribute.cs
- CommandHelpers.cs
- Component.cs
- QueryOutputWriter.cs
- PassportPrincipal.cs
- TextEditorCopyPaste.cs
- HtmlToClrEventProxy.cs
- BamlReader.cs
- SequentialWorkflowRootDesigner.cs
- ProviderSettings.cs
- CorrelationManager.cs
- SamlConstants.cs
- EventHandlersStore.cs
- AssociationSet.cs
- PropertyEmitter.cs
- Validator.cs
- PropertyChangingEventArgs.cs
- StreamAsIStream.cs
- sapiproxy.cs
- LinearQuaternionKeyFrame.cs
- XmlSchemaExporter.cs
- ErrorWrapper.cs
- StrokeNodeOperations2.cs
- PrivilegedConfigurationManager.cs
- ZipPackage.cs
- SqlCommand.cs
- DefaultParameterValueAttribute.cs
- LicenseManager.cs
- DataGridViewRowsRemovedEventArgs.cs
- CuspData.cs
- Module.cs
- NamespaceInfo.cs
- WriteableBitmap.cs
- Completion.cs