//------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors // primary ctor used to create all providers for IAccessible objects. // hwnd is the window this object belongs to. // root is a provider for the OBJID_CLIENT of the window. may be null if it is not yet known. // don't call this constructor directly -- call a Create or Wrap function below. protected MsaaNativeProvider(Accessible acc, IntPtr hwnd, MsaaNativeProvider parent, MsaaNativeProvider knownRoot, RootStatus isRoot) { Debug.Assert(acc != null, "acc"); Debug.Assert(hwnd != IntPtr.Zero); _acc = acc; _hwnd = hwnd; _parent = parent; // can be null if not known. _knownRoot = knownRoot; // can be null if not known. _isRoot = isRoot; // can be RootStatus.Unknown // _controlType defaults to null. computed on demand. }
// ------------------------------------------------------ // // Constructors // // ------------------------------------------------------ #region Constructors internal WindowsStatusBar(IntPtr hwnd, ProxyFragment parent, int item, Accessible acc) : base(hwnd, parent, item) { _acc = acc; _cControlType = ControlType.StatusBar; _fHasGrip = StatusBarGrip.HasGrip(hwnd); _sAutomationId = "StatusBar"; // This string is a non-localizable string // support for events _createOnEvent = new WinEventTracker.ProxyRaiseEvents (RaiseEvents); }
// ------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors // Contructor for Button Proxy class. // param "hwnd", Windows handle // param "parent", Proxy Parent. Null if it is a root fragment // param "type", Button / Checkbox / Radio / Group // param "style", Button Style (BS_*) also used as the Proxy ID // Made internal so that WinFormsHelper.CreateButton can use. internal WindowsButton (IntPtr hwnd, ProxyFragment parent, ButtonType type, int style, Accessible acc) : base( hwnd, parent, 0) { _type = type; _fIsKeyboardFocusable = true; _style = style; _acc = acc; // support for events _createOnEvent = new WinEventTracker.ProxyRaiseEvents (RaiseEvents); // Set ControlType based on type // Note: Do not call LocalizedName() within the constructor // since it is a virtual method. Calling a virtual method // in a constructor would have unintended consequences for // derived classes. if(type == ButtonType.PushButton) { _cControlType = ControlType.Button; _fControlHasLabel = false; } else if(type == ButtonType.CheckBox) { _cControlType = ControlType.CheckBox; // If a check box has non-empty text, it has no associated label. _fControlHasLabel = string.IsNullOrEmpty(GetLocalizedName()); } else if(type == ButtonType.RadioButton) { _cControlType = ControlType.RadioButton; // If a radio button has non-empty text, it has no associated label. _fControlHasLabel = string.IsNullOrEmpty(GetLocalizedName()); } else if (type == ButtonType.GroupBox) { _cControlType = ControlType.Group; _fIsKeyboardFocusable = false; // If a group box has non-empty text, it has no associated label. _fControlHasLabel = string.IsNullOrEmpty(GetLocalizedName()); } else { _cControlType = ControlType.Custom; } }
// ------------------------------------------------------ // // Constructors // // ------------------------------------------------------ #region Constructors internal ToolbarItemAsMenuItem(IntPtr hwnd, ProxyFragment parent, int item, int idCommand, Accessible acc) : base(hwnd, parent, item, idCommand) { _acc = acc; // Set the control type based on the IAccessible role. AccessibleRole role = acc.Role; if (role == AccessibleRole.MenuItem) { _cControlType = ControlType.MenuItem; } else { System.Diagnostics.Debug.Assert(false, "Unexpected role " + role); } // MenuItems are by default KeyboardFocusable. _fIsKeyboardFocusable = true; }
// ------------------------------------------------------ // // Constructors // // ------------------------------------------------------ #region Constructors internal WindowsToolbarAsMenu(IntPtr hwnd, ProxyFragment parent, int item, Accessible acc) : base( hwnd, parent, item ) { _acc = acc; // Set the control type based on the IAccessible role. AccessibleRole role = acc.Role; if (role == AccessibleRole.MenuBar) { _cControlType = ControlType.MenuBar; _sAutomationId = "MenuBar"; // This string is a non-localizable string } else if (role == AccessibleRole.MenuPopup) { _cControlType = ControlType.Menu; _sAutomationId = "MenuPopup"; // This string is a non-localizable string } else { System.Diagnostics.Debug.Assert(false, "Unexpected role " + role); } }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods // the creation of any msaa-based provider funnels through this function. // it creates an object of the base or correct derived class for the specified IAccessible object. private static MsaaNativeProvider Wrap(Accessible acc, IntPtr hwnd, MsaaNativeProvider parent, MsaaNativeProvider knownRoot, RootStatus isRoot) { // if acc is null then return null. if (acc == null) return null; // check that parent is actually our parent - sometimes hit-test and navigation skip layers, so we // may need to reconstruct the parent chain to account for skipped-over ancestors: keep climbing // upwards till we reach the 'parent' that was passed in... MsaaNativeProvider parentChain = parent; if (parent != null) { ArrayList actualParentChain = null; Accessible scan = acc.Parent; while (scan != null) { if (Accessible.Compare(scan, parent._acc)) break; // found actual parent // found intermediate ancestor - add to list... if (actualParentChain == null) actualParentChain = new ArrayList(); actualParentChain.Add(scan); scan = scan.Parent; } if (actualParentChain != null) { // if we found intermediate ancestors, process them top-down, creating // MsaaNativeProviders for each in turn, using the bottom-most one as // our own actual parent... for (int i = actualParentChain.Count - 1; i >= 0; i--) { Accessible ancestor = (Accessible)actualParentChain[i]; parentChain = new MsaaNativeProvider(ancestor, hwnd, parentChain, knownRoot, isRoot); } } } return new MsaaNativeProvider(acc, hwnd, parentChain, knownRoot, isRoot); }
// wraps another Accessible object from the same window that we jumped to directly somehow. // we don't know who the parent is or whether it is root. internal MsaaNativeProvider Wrap(Accessible acc) { return Wrap(acc, _hwnd, null /*unknown parent*/, _knownRoot, RootStatus.Unknown); }
// Overload for IAccessibles, much user friendly. internal static int AccessibleObjectFromWindow(IntPtr hwnd, int idObject, ref Accessible acc) { IAccessible accObject = null; acc = null; try { object obj = null; int hr = UnsafeNativeMethods.AccessibleObjectFromWindow(hwnd, idObject, ref UnsafeNativeMethods.IID_IUnknown, ref obj); accObject = obj as IAccessible; if (hr != NativeMethods.S_OK || accObject == null) { return NativeMethods.S_FALSE; } acc = Accessible.Wrap(accObject); return hr; } catch (Exception e) { if (HandleIAccessibleException(e)) { throw; } return NativeMethods.S_FALSE; } }
// compare 2 Accessible objects internal static bool Compare(Accessible acc1, Accessible acc2) { return acc1==acc2 || acc1.Compare(acc2._acc, acc2._idChild); }
// Get the selected children in a container internal Accessible [] GetSelection() { // object obj = null; try { obj = _acc.accSelection; } catch (Exception e) { if (HandleIAccessibleException(e)) { throw; } obj = null; } if (obj == null) { return null; } Accessible [] children = null; if (obj is int) { children = new Accessible[1]; children[0] = AccessibleFromObject(obj, _acc); } else if (obj is object) { children = new Accessible[1]; children[0] = AccessibleFromObject(obj, _acc); } else if (obj is object []) { object [] objs = (object [])obj; children = new Accessible[objs.Length]; for (int i=0;i<objs.Length;i++) { children[i] = AccessibleFromObject(objs[i], _acc); } } return children; }
internal static Accessible GetFullAccessibleChildByIndex(Accessible accParent, int index) { int childCount = 0; object[] accChildren = Accessible.GetAccessibleChildren(accParent.IAccessible, out childCount); if (accChildren != null && 0 <= index && index < accChildren.Length) { object child = accChildren[index]; IAccessible accChild = child as IAccessible; if (accChild != null) { return Accessible.Wrap(accChild); } else if (child is int) { int idChild = (int)child; return Accessible.Wrap(accParent.IAccessible, idChild); } } return null; }
internal int AccessibleChildrenIndex(Accessible parent) { // if this is the first time we are called then compute the value and cache it. if (_accessibleChildrenIndex < 0) { SetAccessibleChildrenIndexAndGetChildren(parent._acc); } return _accessibleChildrenIndex; }
internal Accessible PreviousSibling(Accessible parent) { Debug.Assert(parent != null); // if this object doesn't yet have an index into parent's children find it object[] children = null; // if we need to get children to find an index; re-use them if (_accessibleChildrenIndex == -1) { children = SetAccessibleChildrenIndexAndGetChildren(parent._acc); // if unable to find this child (broken IAccessible impl?) bail ( if (_accessibleChildrenIndex == -1) { Debug.Assert(false); return null; } } Accessible rval = null; if (_accessibleChildrenIndex - 1 >= 0) { rval = GetChildAt(parent._acc, children, _accessibleChildrenIndex - 1); } return rval; }
// ------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors internal WindowsStatusBarPane (IntPtr hwnd, ProxyFragment parent, int item, Accessible acc) : base (hwnd, parent, item) { _acc = acc; _cControlType = ControlType.Edit; _sAutomationId = "StatusBar.Pane" + item.ToString(CultureInfo.CurrentCulture); // This string is a non-localizable string }