Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / AccessibleTech / longhorn / Automation / Win32Providers / MS / Internal / AutomationProxies / Accessible.cs / 1 / Accessible.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Wraps some of IAccessible to support getting basic properties // and default action // // History: // 06/02/2003 : [....] Ported to WCP // 03/15/2004 : [....] enhanced to support a native MSAA fallback proxy // //--------------------------------------------------------------------------- // PRESHARP: In order to avoid generating warnings about unkown message numbers and unknown pragmas. #pragma warning disable 1634, 1691 using System; using System.Diagnostics; using System.Collections; using System.Globalization; using System.Threading; using System.Windows.Automation; using System.Windows; using Accessibility; using System.Text; using System.Runtime.InteropServices; using MS.Win32; namespace MS.Internal.AutomationProxies { // values return from IAccessible.get_accRole. internal enum AccessibleRole: int { TitleBar = 0x1, MenuBar = 0x2, ScrollBar = 0x3, Grip = 0x4, Sound = 0x5, Cursor = 0x6, Caret = 0x7, Alert = 0x8, Window = 0x9, Client = 0xa, MenuPopup = 0xb, MenuItem = 0xc, Tooltip = 0xd, Application = 0xe, Document = 0xf, Pane = 0x10, Chart = 0x11, Dialog = 0x12, Border = 0x13, Grouping = 0x14, Separator = 0x15, ToolBar = 0x16, StatusBar = 0x17, Table = 0x18, ColumnHeader = 0x19, RowHeader = 0x1a, Column = 0x1b, Row = 0x1c, Cell = 0x1d, Link = 0x1e, HelpBalloon = 0x1f, Character = 0x20, List = 0x21, ListItem = 0x22, Outline = 0x23, OutlineItem = 0x24, PageTab = 0x25, PropertyPage = 0x26, Indicator = 0x27, Graphic = 0x28, StaticText = 0x29, Text = 0x2a, PushButton = 0x2b, CheckButton = 0x2c, RadioButton = 0x2d, Combobox = 0x2e, DropList = 0x2f, ProgressBar = 0x30, Dial = 0x31, HotKeyField = 0x32, Slider = 0x33, SpinButton = 0x34, Diagram = 0x35, Animation = 0x36, Equation = 0x37, ButtonDropDown = 0x38, ButtonMenu = 0x39, ButtonDropDownGrid = 0x3a, Whitespace = 0x3b, PageTabList = 0x3c, Clock = 0x3d, SplitButton = 0x3e, IpAddress = 0x3f, OutlineButton = 0x40, } // values returned from IAccessible.get_accState. [Flags] internal enum AccessibleState: int { Normal = 0x00000000, Unavailable = 0x00000001, Selected = 0x00000002, Focused = 0x00000004, Pressed = 0x00000008, Checked = 0x00000010, Mixed = 0x00000020, ReadOnly = 0x00000040, HotTracked = 0x00000080, Default = 0x00000100, Expanded = 0x00000200, Collapsed = 0x00000400, Busy = 0x00000800, Floating = 0x00001000, Marqueed = 0x00002000, Animated = 0x00004000, Invisible = 0x00008000, Offscreen = 0x00010000, Sizeable = 0x00020000, Moveable = 0x00040000, SelfVoicing = 0x00080000, Focusable = 0x00100000, Selectable = 0x00200000, Linked = 0x00400000, Traversed = 0x00800000, Multiselectable = 0x01000000, ExtSelectable = 0x02000000, AlertLow = 0x04000000, AlertMedium = 0x08000000, AlertHigh = 0x10000000, Protected = 0x20000000, } internal class Accessible { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors // // called by Wrap to create a node Accessible that manages its children private Accessible(IAccessible acc, int idChild) { Debug.Assert(acc != null, "null IAccessible"); _acc = acc; _idChild = idChild; _accessibleChildrenIndex = -1; } // Here we are re-implementing AccessibleObjectFromEvent with a critical difference. // AccessibleObjectFromEvent, via AccessibleObjectFromWindow, will default to a standard implementation // of IAccessible if the window doesn't have a native implementation. // However we only want to succeed constructing the object if the window has a native implementation. internal static Accessible CreateNativeFromEvent(IntPtr hwnd, int idObject, int idChild) { // On Vista, pass PID as wParam - allows credUI scenario to work (OLEACC needs to know our PID to // DuplicateHandle back to this process.) IntPtr wParam = IntPtr.Zero; if(Environment.OSVersion.Version.Major >= 6) wParam = new IntPtr(UnsafeNativeMethods.GetCurrentProcessId()); // send the window a WM_GETOBJECT message requesting the specific object id. IntPtr lResult = Misc.ProxySendMessage(hwnd, NativeMethods.WM_GETOBJECT, wParam, new IntPtr(idObject)); if (lResult == IntPtr.Zero) { return null; } // unwrap the pointer that was returned IAccessible acc = null; int hr = NativeMethods.S_FALSE; try { hr = UnsafeNativeMethods.ObjectFromLresult(lResult, ref UnsafeNativeMethods.IID_IAccessible, wParam, ref acc); } catch (InvalidCastException) { // CLR remoting appears to be interfering in cases where the remote IAccessible is a Winforms control - // the object we get back is a __Transparent proxy, and casting that to IAccessible fails with an exception // (which is caught and ignored here). See bug #1110719 for details. // One way around this is to use AccessibleObjectFromWindow - that returns IAccessible instead of IUnknown - // in effect it does the case in unmanaged code, and seems to avoid this issue. Other winforms code in the // proxies uses this approach. AccessibleObjectFromWindow will return an OLEACC proxy if one is available, // however, so we can't use it here, as this code only wants to deal with native IAccessibles. return null; } // ObjectFromLresult returns an IAccessible from the remote process. If that impl is managed, however, then // the local CLR will set up a CLR-Remoting-based connection instead and bypass COM - this causes problems // because CLR Remoting typically isn't initalized, so calls fail with a RemotingException: "This remoting // proxy has no channel sink which means either the server has no registered server channels that are listening, // or this application has no suitable client channel to talk to the server." - see bug #1519030. The local CLR // detects that the remote object is a managed impl by QI'ing for a specifc interface (IManagedObject?). // We can prevent this from happening by dropping the IAccessible we've gotten back from ObjectFromLresult, // and instead use AccessibleObjectFromWindow: AOFW wraps the real IAccessible in a DynamicAnnotation wrapper // that passes through all IAccessible (and related interface) calls - but it doesn't pass through the // IManagedObject interface, so the CLR treats it as a COM object, and continues to use plain COM to access it, // avoiding the CLR Remoting issues. // // In effect, we're sending WM_GETOBJECT to the HWND to see if there's a native impl there, using ObjectFromLresult // just to free that object, and then using AccessibleObjectFromWindow on the window to get the IAccessible // that we actually use. (Can't just use AccessibleObjectFromWindow from the start, since that would return // an oleacc proxy for hwnds that don't support IAccessible natively, and we only care about actual IAccessible // impls here.) // // We used to do use AOFW below only if the acc we got back above was a managed object (checked using // !Marshal.IsComObject()) - that only protects us from managed IAccessibles we get back directly; we could // still hit the above issue if we get back a remote unmanaged impl that then returns a maanged impl via // navigation (Media Center does this). So we now use AOFW all the time. if(hr == NativeMethods.S_OK && acc != null) { object obj = null; hr = UnsafeNativeMethods.AccessibleObjectFromWindow(hwnd, idObject, ref UnsafeNativeMethods.IID_IUnknown, ref obj); acc = obj as IAccessible; } if (hr != NativeMethods.S_OK || acc == null) { return null; } // This takes care of calling get_accChild, if necessary... return AccessibleFromObject(idChild, acc); } #if DEBUG /* // strictly for debugging purposes: public override string ToString() { try { return string.Format( "{0} \"{1}\" {2} {3}", RoleText, Name, _idChild, Window ); } catch (Exception e) { return e.Message; } } [DllImport( "oleacc.dll" )] internal static extern int GetRoleText( int dwRole, StringBuilder lpszRole, int cchRoleMax ); private string RoleText { get { const int cch = 64; StringBuilder sb = new StringBuilder( cch ); int len = GetRoleText( (int)Role, sb, cch ); return sb.ToString().Substring( 0, len ); } } */ #endif #endregion Constructors //------------------------------------------------------ // // Internal Methods // //----------------------------------------------------- #region Internal Methods // returns a new Accessible for the IAccessible, or null if IAccessible is null internal static Accessible Wrap(IAccessible acc) { return Wrap(acc, NativeMethods.CHILD_SELF); } // returns a new Accessible for the IAccessible + child id, or null if IAccessible is null internal static Accessible Wrap(IAccessible acc, int idChild) { return acc != null ? new Accessible(acc, idChild) : null; } internal IAccessible IAccessible { get { return _acc; } } internal int ChildCount { get { return GetChildCount(_acc); } } internal int ChildId { get { return _idChild; } } internal string Description { get { return GetDescription(_acc, _idChild); } } internal string KeyboardShortcut { get { return GetKeyboardShortcut(_acc, _idChild); } } internal string Name { get { return GetName(_acc, _idChild); } } internal string DefaultAction { get { return GetDefaultAction(_acc, _idChild); } } internal AccessibleRole Role { get { return GetRole(_acc, _idChild); } } internal bool IsPassword { get { return HasState(AccessibleState.Protected); } } internal bool IsSelected { get { return HasState(AccessibleState.Selected); } } internal bool IsMultiSelectable { get { return HasState(AccessibleState.Multiselectable); } } internal bool IsIndeterminate { get { return HasState(AccessibleState.Mixed); } } internal bool IsChecked { get { return HasState(AccessibleState.Checked); } } internal bool IsReadOnly { get { return HasState(AccessibleState.ReadOnly); } } internal bool IsEnabled { get { return ! HasState(AccessibleState.Unavailable); } } internal bool IsFocused { get { return HasState(AccessibleState.Focused); } } internal bool IsOffScreen { get { return HasState(AccessibleState.Offscreen); } } internal Accessible FirstChild { get { return _idChild == NativeMethods.CHILD_SELF ? GetChildAt(_acc, null, 0) : null; } } internal Accessible LastChild { get { return _idChild == NativeMethods.CHILD_SELF ? GetChildAt(_acc, null, Accessible.GetChildCount(_acc) - 1) : null; } } internal Accessible NextSibling(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 < Accessible.GetChildCount(parent._acc)) { rval = GetChildAt(parent._acc, children, _accessibleChildrenIndex + 1); } return rval; } 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; } internal Accessible Parent { get { // // review: I think it might be better to throw an exception here than return a bogus value. IAccessible rval; if (_idChild != NativeMethods.CHILD_SELF) { rval = _acc; // parent is managing this child } else { try { rval = (IAccessible)_acc.accParent; } catch (Exception e) { if (HandleIAccessibleException(e)) { // PerSharp/PreFast will flag this as a warning, 6503/56503: Property get methods should not throw exceptions. // We are communicate with the underlying control to get the information. // The control may not be able to give us the information we need. // Throw the correct exception to communicate the failure. #pragma warning suppress 6503 throw; } return null; } } return Wrap(rval); } } 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 bool IsAvailableToUser { get { AccessibleState state = State; // From MSDN: // STATE_SYSTEM_INVISIBLE means the object is programmatically hidden. For example, menu items // are programmatically hidden until a user activates the menu. Because objects with this // state are not available to users, client applications should not communicate information // about the object to users. However, if client applications find an object with this state, // they should check to see if STATE_SYSTEM_OFFSCREEN is also set. If this second state is // defined, then clients can communicate the information about the object to users. // // We're not dealing with menus [in this version of NativeMsaaProxy] so won't worry about them // here. To "clean up" the tree we'll skip over IAccessibles that have the above states. // May revisit per user feedback. if (Accessible.HasState(state, AccessibleState.Invisible) && !Accessible.HasState(state, AccessibleState.Offscreen)) return false; return true; } } internal bool InSameHwnd(IntPtr hwnd) { bool inSameHwnd = Window != IntPtr.Zero && Window == hwnd; return inSameHwnd; } // returns true if accessible object should be exposed to UIA clients. // accessible objects are exposed UIA if they are visible, not offscreen, and do not correspond to a child window. internal bool IsExposedToUIA { get { bool rval = false; // if the accessible object is "available"... if (IsAvailableToUser) { // ... and is not a child window... // AccessibleRole role = Role; if (role != AccessibleRole.Window) { // ... and is not a child window that is trident ... // (special case since trident doesn't have a ROLE_SYSTEM_WINDOW object for its "Internet Explorer_Server" window. if (role != AccessibleRole.Client || Description != "MSAAHTML Registered Handler") { // then it is visible rval = true; } } } return rval; } } internal AccessibleState State { get { try { return (AccessibleState)_acc.get_accState(_idChild); } catch (Exception e) { if (HandleIAccessibleException(e)) { // PerSharp/PreFast will flag this as a warning, 6503/56503: Property get methods should not throw exceptions. // We are communicate with the underlying control to get the information. // The control may not be able to give us the information we need. // Throw the correct exception to communicate the failure. #pragma warning suppress 6503 throw; } return AccessibleState.Unavailable; } } } internal string Value { get { try { string value = FixBstr(_acc.get_accValue(_idChild)); // PerSharp/PreFast will flag this as warning 6507/56507: Prefer 'string.IsNullOrEmpty(value)' over checks for null and/or emptiness. // Need to convert nulls into an empty string, so need to just test for a null. // Therefore we can not use IsNullOrEmpty() here, suppress the warning. #pragma warning suppress 6507 return value != null ? value : ""; } catch (Exception e) { if (HandleIAccessibleException(e)) { // PerSharp/PreFast will flag this as a warning, 6503/56503: Property get methods should not throw exceptions. // We are communicate with the underlying control to get the information. // The control may not be able to give us the information we need. // Throw the correct exception to communicate the failure. #pragma warning suppress 6503 throw; } return ""; } } set { try { _acc.set_accValue(_idChild, value); } catch (Exception e) { if (HandleIAccessibleException(e)) { throw; } // throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed), e); } } } // Return the Rect that bounds this element in screen coordinates internal Rect Location { get { NativeMethods.Win32Rect rcW32 = GetLocation(_acc, _idChild); return rcW32.ToRect(false); } } 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 static AccessibleRole GetRole(IAccessible acc, int idChild) { AccessibleRole rval; try { object role = acc.get_accRole(idChild); // get_accRole can return a non-int! for example, Outlook 2003 SUPERGRID entries // can return the string "Table View". so we return an int if we got one otherwise // we convert it to the generic "client" role. rval = (role is int) ? (AccessibleRole)(int)role : AccessibleRole.Client; } catch (Exception e) { if (HandleIAccessibleException(e)) { throw; } rval = AccessibleRole.Client; } return rval; } // 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;i0) { aChildren = new object[childCount]; // Get the raw children because accNavigate doesn't work if (UnsafeNativeMethods.AccessibleChildren(accessibleObject, 0, childCount, aChildren, out childrenReturned) == NativeMethods.E_INVALIDARG) { System.Diagnostics.Debug.Assert(false, "Call to AccessibleChildren() returned E_INVALIDARG."); throw new ElementNotAvailableException(); } } return aChildren; } catch (Exception e) { if (HandleIAccessibleException(e)) { throw; } throw new ElementNotAvailableException(); } } #endregion #endregion Internal Methods //------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods // Returns a child by index private static Accessible GetChildAt(IAccessible parent, object [] children, int index) { // note: calling AccessibleChildren on Trident and asking for a single child can // result in a Fatal Execution Engine Error (79697ADA)(80121506). // Perhaps the implementation ignores the cChildren param? // To avoid the problem we always ask for all of the children and just // use the specific one we are interested in. if (children == null) { children = GetChildren(parent); } if (children == null) { return null; } // Paranoia that between calls accChildCount returns different counts if (index >= children.Length) index = children.Length - 1; Accessible nav = AccessibleFromObject(children[index], parent); if (nav != null) { nav._accessibleChildrenIndex = index; } return nav; } // Find _acc's index among its siblings with optimization to return children collection // if that would be needed later by the caller private object [] SetAccessibleChildrenIndexAndGetChildren(IAccessible parent) { // this is only called if the index hasn't been set yet. Debug.Assert(_accessibleChildrenIndex < 0); object [] children = GetChildren(parent); if (children == null) { return null; // unlikely to happen but... } // Try to figure out which child in this array '_acc' is for (int i=0;i
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ListViewPagedDataSource.cs
- SerializationInfo.cs
- CollectionType.cs
- DataGridRow.cs
- Model3D.cs
- PropertyTabAttribute.cs
- DescendentsWalker.cs
- LinqDataSource.cs
- PrintingPermission.cs
- _MultipleConnectAsync.cs
- SrgsGrammarCompiler.cs
- COSERVERINFO.cs
- StackBuilderSink.cs
- Pair.cs
- HttpHandlerActionCollection.cs
- Config.cs
- _OSSOCK.cs
- SmtpNtlmAuthenticationModule.cs
- AssemblyAssociatedContentFileAttribute.cs
- XmlTextReaderImpl.cs
- ScriptServiceAttribute.cs
- CharacterMetrics.cs
- TablePattern.cs
- SendMessageChannelCache.cs
- WindowsListViewGroup.cs
- DataBindingExpressionBuilder.cs
- HttpListenerPrefixCollection.cs
- SharedMemory.cs
- SizeIndependentAnimationStorage.cs
- WasHttpHandlersInstallComponent.cs
- HotSpot.cs
- ListBoxItem.cs
- ApplicationCommands.cs
- XmlException.cs
- EditorPartDesigner.cs
- DynamicMethod.cs
- SetMemberBinder.cs
- SplayTreeNode.cs
- XmlRootAttribute.cs
- NativeMethods.cs
- ObjectReaderCompiler.cs
- documentation.cs
- ProcessManager.cs
- TimeoutValidationAttribute.cs
- Figure.cs
- IPEndPoint.cs
- CheckBox.cs
- JsonUriDataContract.cs
- SqlDataSourceSelectingEventArgs.cs
- SafeNativeMethods.cs
- Underline.cs
- SQlBooleanStorage.cs
- CachingHintValidation.cs
- Misc.cs
- ServerValidateEventArgs.cs
- TreeNodeSelectionProcessor.cs
- KnownBoxes.cs
- storepermission.cs
- XmlSignificantWhitespace.cs
- FormViewUpdatedEventArgs.cs
- SqlCacheDependencySection.cs
- DiffuseMaterial.cs
- ActiveXContainer.cs
- AttributeConverter.cs
- BackgroundFormatInfo.cs
- MsmqDiagnostics.cs
- RightNameExpirationInfoPair.cs
- PageHandlerFactory.cs
- ListenerServiceInstallComponent.cs
- IEnumerable.cs
- XsltLibrary.cs
- DataMemberFieldEditor.cs
- Token.cs
- QuotedPrintableStream.cs
- WebPartManagerInternals.cs
- IndividualDeviceConfig.cs
- PathSegmentCollection.cs
- PointHitTestResult.cs
- ContextMenu.cs
- DesignObjectWrapper.cs
- RC2.cs
- WebRequestModuleElementCollection.cs
- PasswordBox.cs
- DocumentPageHost.cs
- ItemCollectionEditor.cs
- ObjectSet.cs
- CompiledIdentityConstraint.cs
- AuthenticationSchemesHelper.cs
- DSASignatureFormatter.cs
- EntityConnection.cs
- BinaryObjectReader.cs
- SmtpDigestAuthenticationModule.cs
- Label.cs
- LinkedResource.cs
- QueryTask.cs
- SqlDataAdapter.cs
- XsltInput.cs
- CapiSafeHandles.cs
- XamlParser.cs
- InteropBitmapSource.cs