Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Automation / Peers / AutomationPeer.cs / 2 / AutomationPeer.cs
using System; using System.Collections; using System.Security; using System.Security.Permissions; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Threading; using System.Collections.Generic; using System.Windows.Automation.Provider; using MS.Internal; using MS.Internal.Automation; using MS.Internal.Media; using MS.Internal.PresentationCore; using MS.Win32; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Automation.Peers { /// public enum PatternInterface { /// Invoke, /// Selection, /// Value, /// RangeValue, /// Scroll, /// ScrollItem, /// ExpandCollapse, /// Grid, /// GridItem, /// MultipleView, /// Window, /// SelectionItem, /// Dock, /// Table, /// TableItem, /// Toggle, /// Transform, /// Text, } /// public enum AutomationOrientation { /// None = 0, /// Horizontal, /// Vertical, } /// public enum AutomationControlType { /// Button, /// Calendar, /// CheckBox, /// ComboBox, /// Edit, /// Hyperlink, /// Image, /// ListItem, /// List, /// Menu, /// MenuBar, /// MenuItem, /// ProgressBar, /// RadioButton, /// ScrollBar, /// Slider, /// Spinner, /// StatusBar, /// Tab, /// TabItem, /// Text, /// ToolBar, /// ToolTip, /// Tree, /// TreeItem, /// Custom, /// Group, /// Thumb, /// DataGrid, /// DataItem, /// Document, /// SplitButton, /// Window, /// Pane, /// Header, /// HeaderItem, /// Table, /// TitleBar, /// Separator, } /// public enum AutomationEvents { /// ToolTipOpened, /// ToolTipClosed, /// MenuOpened, /// MenuClosed, /// AutomationFocusChanged, /// InvokePatternOnInvoked, /// SelectionItemPatternOnElementAddedToSelection, /// SelectionItemPatternOnElementRemovedFromSelection, /// SelectionItemPatternOnElementSelected, /// SelectionPatternOnInvalidated, /// TextPatternOnTextSelectionChanged, /// TextPatternOnTextChanged, /// AsyncContentLoaded, /// PropertyChanged, /// StructureChanged, } ///This is a helper class to facilate the storage of Security critical data ( aka "Plutonium") /// It's primary purpose is to do put a [SecurityCritical] on all access to the data. /// What is "critical data" ? This is any data created that required an Assert for it's creation. /// As an example - the passage of hosted Hwnd between some AutomationPeer and UIA infrastructure. public sealed class HostedWindowWrapper { ////// This is the only public constructor on this class. /// It requires "Full Trust" level of security permissions to be executed, since this /// class is wrappign an HWND direct access to which is a critical asset. /// ////// Critical - as this accesses _hwnd which is Critical. /// Safe - as the caller already got the critical value. /// In addition, we prevent creating this class by external callers who does not have UnmanagedCode permission. /// [SecurityCritical, SecurityTreatAsSafe] public HostedWindowWrapper(IntPtr hwnd) { (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Demand(); _hwnd = hwnd; } //// Critical "by definition" - this class is intended to store critical data. // [SecurityCritical] private HostedWindowWrapper() { _hwnd = IntPtr.Zero; } //// Critical "by definition" - this class is intended to store critical data. // [SecurityCritical] internal static HostedWindowWrapper CreateInternal(IntPtr hwnd) { HostedWindowWrapper wrapper = new HostedWindowWrapper(); wrapper._hwnd = hwnd; return wrapper; } //// Critical "by definition" - this class is intended to store critical data. // internal IntPtr Handle { [SecurityCritical] get { return _hwnd; } } ////// Critical - by definition as this is a wrapper for Critical data. /// [SecurityCritical] private IntPtr _hwnd; } /// public abstract class AutomationPeer: DispatcherObject { /// protected AutomationPeer() { if (!s_initialized) { Initialize(); } } // // VIRTUAL CALLBACKS // /// abstract protected ListGetChildrenCore(); /// abstract public object GetPattern(PatternInterface patternInterface); // // PUBLIC METHODS // /// public void InvalidatePeer() { if(_invalidated) return; Dispatcher.BeginInvoke(DispatcherPriority.Background, _updatePeer, this); _invalidated = true; } /// /// Used to check if Automation is indeed listening for the event. /// Typical usage is to check this before even creating the peer that will fire the event. /// Basically, this is a performance measure since if the Automation does not listen for the event, /// it does not make sense to create a peer to fire one. /// NOTE: the method is static and only answers if there is some listener in Automation, /// not specifically for some element. The Automation can hook up "broadcast listeners" so the /// per-element info is basically unavailable. /// static public bool ListenerExists(AutomationEvents eventId) { return (EventMap.HasRegisteredEvent(eventId)); } ////// Used by peer implementation to raise an event for Automation /// // Never inline, as we don't want to unnecessarily link the automation DLL. [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] public void RaiseAutomationEvent(AutomationEvents eventId) { AutomationEvent eventObject = EventMap.GetRegisteredEvent(eventId); if (eventObject == null) { // nobody is listening to this event return; } IRawElementProviderSimple provider = ProviderFromPeer(this); if (provider != null) { AutomationInteropProvider.RaiseAutomationEvent( eventObject, provider, new AutomationEventArgs(eventObject)); } } ////// This method is called by implementation of the peer to raise the automation propertychange notifications /// Typically, the peers that implement automation patterns liek IScrollProvider need to raise events specified by /// the particular pattern in case specific properties are changing. /// // Never inline, as we don't want to unnecessarily link the automation DLL via the ScrollPattern reference. [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] public void RaisePropertyChangedEvent(AutomationProperty property, object oldValue, object newValue) { // Only send the event if there are listeners for this property change if (AutomationInteropProvider.ClientsAreListening) { RaisePropertyChangedInternal(ProviderFromPeer(this), property,oldValue,newValue); } } ////// This method is called by implementation of the peer to raise the automation "async content loaded" notifications /// // Never inline, as we don't want to unnecessarily link the automation DLL. [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] public void RaiseAsyncContentLoadedEvent(AsyncContentLoadedEventArgs args) { if(args == null) throw new ArgumentNullException("args"); if (EventMap.HasRegisteredEvent(AutomationEvents.AsyncContentLoaded)) { IRawElementProviderSimple provider = ProviderFromPeer(this); if(provider != null) { AutomationInteropProvider.RaiseAutomationEvent( AutomationElementIdentifiers.AsyncContentLoadedEvent, provider, args); } } } internal static void RaiseFocusChangedEventHelper(IInputElement newFocus) { // Callers have only checked if automation clients are present so filter for any interest in this particular event. if (EventMap.HasRegisteredEvent(AutomationEvents.AutomationFocusChanged)) { AutomationPeer peer = AutomationPeerFromInputElement(newFocus); if (peer != null) { peer.RaiseAutomationEvent(AutomationEvents.AutomationFocusChanged); } else //non-automated element got focus, same as focus lost { //No focused peer. Just don't report anything. } } } // helper method. Makes attempt to find an automation peer corresponding to the given IInputElement... internal static AutomationPeer AutomationPeerFromInputElement(IInputElement focusedElement) { AutomationPeer peer = null; UIElement uie = focusedElement as UIElement; if (uie != null) { peer = UIElementAutomationPeer.CreatePeerForElement(uie); } else { ContentElement ce = focusedElement as ContentElement; if (ce != null) { peer = ContentElementAutomationPeer.CreatePeerForElement(ce); } else { UIElement3D uie3D = focusedElement as UIElement3D; if (uie3D != null) { peer = UIElement3DAutomationPeer.CreatePeerForElement(uie3D); } } } if (peer != null) { // ValidateConnected ensures that EventsSource is initialized peer.ValidateConnected(peer); // always use event source when available if (peer.EventsSource != null) { peer = peer.EventsSource; } } return peer; } // We can only return peers to UIA that are properly connected to the UIA tree already // This means they should have _hwnd and _parent already set and _parent should point to the // peer which would have this peer returned from its GetChildrenCore. This method checks if the // peer is already connected, and if not then it walks the tree of peers from the top down, calling // GetChildren and trying to find itself in someone's children. Once this succeeds, the peer is connected // (because GetChildren will connect it). In this case this method will return "this". // However if the search does not find the peer, that means the peer // would never be exposed by specific context even though it is createable on the element (the decision to expose // children is on parent peers and parent peer may decide not to expose subpart of itself). In this case, // this method returns null. // ConnectedPeer parameter is some peer which is known to be connected (typically root, but if not, this method will // walk up from the given connectedPeer up to find a root) ////// Critical - Accessing _hwnd /// TreatAsSafe - _hwnd is used internally and not exposed. /// [SecurityCritical, SecurityTreatAsSafe] internal AutomationPeer ValidateConnected(AutomationPeer connectedPeer) { if(connectedPeer == null) throw new ArgumentNullException("connectedPeer"); if(_parent != null && _hwnd != IntPtr.Zero) return this; if((connectedPeer._hwnd) != IntPtr.Zero) { while(connectedPeer._parent != null) connectedPeer = connectedPeer._parent; //now connectedPeer is the root if ((connectedPeer == this) || isDescendantOf(connectedPeer)) return this; } //last effort - find across all roots //only start fault in the tree from the root if we are not in the recursive sync update //Otherwise it will go through the peers that are currently on the stack ContextLayoutManager lm = ContextLayoutManager.From(this.Dispatcher); if(lm != null && lm.AutomationSyncUpdateCounter == 0) { AutomationPeer[] roots = lm.GetAutomationRoots(); for(int i = 0; i < roots.Length; i++) { AutomationPeer root = roots[i]; if (root != null) { if((root == this) || isDescendantOf(root)) return this; } } } return null; } private bool isDescendantOf(AutomationPeer parent) { if(parent == null) throw new ArgumentNullException("parent"); Listchildren = parent.GetChildren(); if(children == null) return false; int cnt = children.Count; for(int i = 0; i < cnt; ++i) { AutomationPeer child = children[i]; //depth first if(child == this || this.isDescendantOf(child)) return true; } return false; } /// /// Outside of hosting scenarios AutomationPeers shoudl not override this method. /// It is needed for peers that implement their own host HWNDs /// for these HWNDs to appear in a proper place in the UIA tree. /// Without this interface being omplemented, the HWND is parented by UIA as a child /// of the HwndSource that hosts whole Avalon app. Instead, it is usually desirable /// to override this defautl behavior and tell UIA to parent hosted HWND as a child /// somewhere in Avlaon tree where it is actually hosted. /// ////// Automation infrastructure provides necessary hookup, the AutomationPeer of the element that /// immediately hosts the HWND should implement this interface to be properly wired in. /// In addition to that, it should return this peer as IRawElementProviderSimple as a response to /// WM_GETOBJECT coming to the hosted HWND. /// /// To obtain the IRawElementProviderSimple interface, the peer should use /// System.Windows.Automation.AutomationInteropProvider.HostProviderFromHandle(hwnd). /// /// Critical - Calls critical AutomationPeer.Hwnd. /// TreatAsSafe - Critical data is used internally and not explosed /// [SecurityCritical, SecurityTreatAsSafe] virtual protected HostedWindowWrapper GetHostRawElementProviderCore() { HostedWindowWrapper host = null; //in normal Avalon subtrees, only root peers should return wrapped HWND if(GetParent() == null) { // this way of creating HostedWindowWrapper does not require FullTrust host = HostedWindowWrapper.CreateInternal(Hwnd); } return host; } internal HostedWindowWrapper GetHostRawElementProvider() { return GetHostRawElementProviderCore(); } ////// Returns 'true' only if this is a peer that hosts HWND in Avalon (WindowsFormsHost or Popup for example). /// Such peers also have to override GetHostRawElementProviderCore method. /// virtual protected internal bool IsHwndHost { get { return false; }} // // P R O P E R T I E S // /// abstract protected Rect GetBoundingRectangleCore(); /// abstract protected bool IsOffscreenCore(); /// abstract protected AutomationOrientation GetOrientationCore(); /// abstract protected string GetItemTypeCore(); /// abstract protected string GetClassNameCore(); /// abstract protected string GetItemStatusCore(); /// abstract protected bool IsRequiredForFormCore(); /// abstract protected bool IsKeyboardFocusableCore(); /// abstract protected bool HasKeyboardFocusCore(); /// abstract protected bool IsEnabledCore(); /// abstract protected bool IsPasswordCore(); /// abstract protected string GetAutomationIdCore(); /// abstract protected string GetNameCore(); /// abstract protected AutomationControlType GetAutomationControlTypeCore(); /// virtual protected string GetLocalizedControlTypeCore() { ControlType controlType = GetControlType(); return controlType.LocalizedControlType; } /// abstract protected bool IsContentElementCore(); /// abstract protected bool IsControlElementCore(); /// abstract protected AutomationPeer GetLabeledByCore(); /// abstract protected string GetHelpTextCore(); /// abstract protected string GetAcceleratorKeyCore(); /// abstract protected string GetAccessKeyCore(); /// abstract protected Point GetClickablePointCore(); /// abstract protected void SetFocusCore(); // // INTERNAL STUFF - NOT OVERRIDABLE // /// public Rect GetBoundingRectangle() { if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; _boundingRectangle = GetBoundingRectangleCore(); } finally { _publicCallInProgress = false; } return _boundingRectangle; } /// public bool IsOffscreen() { if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; _isOffscreen = IsOffscreenCore(); } finally { _publicCallInProgress = false; } return _isOffscreen; } /// public AutomationOrientation GetOrientation() { AutomationOrientation result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetOrientationCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetItemType() { string result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetItemTypeCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetClassName() { string result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetClassNameCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetItemStatus() { if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; _itemStatus = GetItemStatusCore(); } finally { _publicCallInProgress = false; } return _itemStatus; } /// public bool IsRequiredForForm() { bool result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = IsRequiredForFormCore(); } finally { _publicCallInProgress = false; } return result; } /// public bool IsKeyboardFocusable() { bool result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = IsKeyboardFocusableCore(); } finally { _publicCallInProgress = false; } return result; } /// public bool HasKeyboardFocus() { bool result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = HasKeyboardFocusCore(); } finally { _publicCallInProgress = false; } return result; } /// public bool IsEnabled() { if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; _isEnabled = IsEnabledCore(); } finally { _publicCallInProgress = false; } return _isEnabled; } /// public bool IsPassword() { bool result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = IsPasswordCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetAutomationId() { string result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetAutomationIdCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetName() { if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; _name = GetNameCore(); } finally { _publicCallInProgress = false; } return _name; } /// public AutomationControlType GetAutomationControlType() { AutomationControlType result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetAutomationControlTypeCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetLocalizedControlType() { string result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetLocalizedControlTypeCore(); } finally { _publicCallInProgress = false; } return result; } /// public bool IsContentElement() { bool result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = IsContentElementCore(); } finally { _publicCallInProgress = false; } return result; } /// public bool IsControlElement() { bool result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = IsControlElementCore(); } finally { _publicCallInProgress = false; } return result; } /// public AutomationPeer GetLabeledBy() { AutomationPeer result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetLabeledByCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetHelpText() { string result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetHelpTextCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetAcceleratorKey() { string result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetAcceleratorKeyCore(); } finally { _publicCallInProgress = false; } return result; } /// public string GetAccessKey() { string result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetAccessKeyCore(); } finally { _publicCallInProgress = false; } return result; } /// public Point GetClickablePoint() { Point result; if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; result = GetClickablePointCore(); } finally { _publicCallInProgress = false; } return result; } /// public void SetFocus() { if (_publicSetFocusInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicSetFocusInProgress = true; SetFocusCore(); } finally { _publicSetFocusInProgress = false; } } /// public AutomationPeer GetParent() { return _parent; } /// public ListGetChildren() { if (_publicCallInProgress) throw new InvalidOperationException(SR.Get(SRID.Automation_RecursivePublicCall)); try { _publicCallInProgress = true; EnsureChildren(); } finally { _publicCallInProgress = false; } return _children; } /// public void ResetChildrenCache() { UpdateChildren(); } /// internal int[] GetRuntimeId() { return new int [] { 7, SafeNativeMethods.GetCurrentProcessId(), this.GetHashCode() }; } /// internal string GetFrameworkId() { return ("WPF"); } // internal AutomationPeer GetFirstChild() { AutomationPeer peer = null; EnsureChildren(); if (_children != null && _children.Count > 0) { peer = _children[0]; } return peer; } // /// /// Critical - Accessing _hwnd /// TreatAsSafe - _hwnd is used internally and not exposed. /// [SecurityCritical, SecurityTreatAsSafe] private void EnsureChildren() { if(!_childrenValid) { _children = GetChildrenCore(); if (_children != null) { int count = _children.Count; for (int i = 0; i < count; ++i) { _children[i]._parent = this; _children[i]._index = i; _children[i]._hwnd = _hwnd; } } _childrenValid = true; } } // internal AutomationPeer GetLastChild() { AutomationPeer peer = null; EnsureChildren(); if (_children != null && _children.Count > 0) { peer = _children[_children.Count - 1]; } return peer; } // [FriendAccessAllowed] // Built into Core, also used by Framework. internal virtual InteropAutomationProvider GetInteropChild() { return null; } // internal AutomationPeer GetNextSibling() { AutomationPeer sibling = null; AutomationPeer parent = GetParent(); if (parent != null) { parent.EnsureChildren(); if ( parent._children != null && _index + 1 < parent._children.Count && parent._children[_index] == this ) { sibling = parent._children[_index + 1]; } } return sibling; } // internal AutomationPeer GetPreviousSibling() { AutomationPeer sibling = null; AutomationPeer parent = GetParent(); if (parent != null) { parent.EnsureChildren(); if ( parent._children != null && _index - 1 >= 0 && _index < parent._children.Count && parent._children[_index] == this ) { sibling = parent._children[_index - 1]; } } return sibling; } // internal ControlType GetControlType() { ControlType controlType = null; AutomationControlType type = GetAutomationControlTypeCore(); switch (type) { case AutomationControlType.Button: controlType = ControlType.Button; break; case AutomationControlType.Calendar: controlType = ControlType.Calendar; break; case AutomationControlType.CheckBox: controlType = ControlType.CheckBox; break; case AutomationControlType.ComboBox: controlType = ControlType.ComboBox; break; case AutomationControlType.Edit: controlType = ControlType.Edit; break; case AutomationControlType.Hyperlink: controlType = ControlType.Hyperlink; break; case AutomationControlType.Image: controlType = ControlType.Image; break; case AutomationControlType.ListItem: controlType = ControlType.ListItem; break; case AutomationControlType.List: controlType = ControlType.List; break; case AutomationControlType.Menu: controlType = ControlType.Menu; break; case AutomationControlType.MenuBar: controlType = ControlType.MenuBar; break; case AutomationControlType.MenuItem: controlType = ControlType.MenuItem; break; case AutomationControlType.ProgressBar: controlType = ControlType.ProgressBar; break; case AutomationControlType.RadioButton: controlType = ControlType.RadioButton; break; case AutomationControlType.ScrollBar: controlType = ControlType.ScrollBar; break; case AutomationControlType.Slider: controlType = ControlType.Slider; break; case AutomationControlType.Spinner: controlType = ControlType.Spinner; break; case AutomationControlType.StatusBar: controlType = ControlType.StatusBar; break; case AutomationControlType.Tab: controlType = ControlType.Tab; break; case AutomationControlType.TabItem: controlType = ControlType.TabItem; break; case AutomationControlType.Text: controlType = ControlType.Text; break; case AutomationControlType.ToolBar: controlType = ControlType.ToolBar; break; case AutomationControlType.ToolTip: controlType = ControlType.ToolTip; break; case AutomationControlType.Tree: controlType = ControlType.Tree; break; case AutomationControlType.TreeItem: controlType = ControlType.TreeItem; break; case AutomationControlType.Custom: controlType = ControlType.Custom; break; case AutomationControlType.Group: controlType = ControlType.Group; break; case AutomationControlType.Thumb: controlType = ControlType.Thumb; break; case AutomationControlType.DataGrid: controlType = ControlType.DataGrid; break; case AutomationControlType.DataItem: controlType = ControlType.DataItem; break; case AutomationControlType.Document: controlType = ControlType.Document; break; case AutomationControlType.SplitButton: controlType = ControlType.SplitButton; break; case AutomationControlType.Window: controlType = ControlType.Window; break; case AutomationControlType.Pane: controlType = ControlType.Pane; break; case AutomationControlType.Header: controlType = ControlType.Header; break; case AutomationControlType.HeaderItem: controlType = ControlType.HeaderItem; break; case AutomationControlType.Table: controlType = ControlType.Table; break; case AutomationControlType.TitleBar: controlType = ControlType.TitleBar; break; case AutomationControlType.Separator: controlType = ControlType.Separator; break; default: break; } return controlType; } internal AutomationPeer GetPeerFromPoint(Point point) { AutomationPeer found = null; if(!IsOffscreen()) { Listchildren = GetChildren(); if(children != null) { int count = children.Count; for(int i = count-1; (i >= 0) && (found == null); --i) { found = children[i].GetPeerFromPoint(point); } } if(found == null) { Rect bounds = GetBoundingRectangle(); if(bounds.Contains(point)) found = this; } } return found; } /// /// Creates an element provider (proxy) from a peer. Some patterns require returning objects of type /// IRawElementProviderSimple - this is an Automation-specific wrapper interface that corresponds to a peer. /// To wrap an AutomationPeer into the wrapper that exposes this interface, use this method. /// protected internal IRawElementProviderSimple ProviderFromPeer(AutomationPeer peer) { AutomationPeer referencePeer = this; //replace itself with _eventsSource if we are aggregated and hidden from the UIA if((peer == this) && (_eventsSource != null)) { referencePeer = peer = _eventsSource; } return ElementProxy.StaticWrap(peer, referencePeer); } private IRawElementProviderSimple ProviderFromPeerNoDelegation(AutomationPeer peer) { AutomationPeer referencePeer = this; return ElementProxy.StaticWrap(peer, referencePeer); } ////// When one AutomationPeer is using the pattern of another AutomationPeer instead of exposing /// it in the children collection (example - ListBox exposes IScrollProvider from internal ScrollViewer /// but does not expose the ScrollViewerAutomationPeer as its child) - then before returning the pattern /// interface from GetPattern, the "main" AutomationPeer should call this method to set up itself as /// "source" for the events fired by the pattern on the subordinate AutomationPeer. /// Otherwise, the hidden subordinate AutomationPeer will fire pattern's events from its own identity which /// will confuse UIA since its identity is not exposed to UIA. /// public AutomationPeer EventsSource { get { return _eventsSource; } set { _eventsSource = value; } } ////// Returns AutomationPeer corresponding to the given provider. /// protected AutomationPeer PeerFromProvider(IRawElementProviderSimple provider) { ElementProxy proxy = provider as ElementProxy; if (proxy != null) { return (proxy.Peer); } return null; } //called on a root peer of a tree when it's time to fire automation events //walks down the tree, updates caches and fires automation events // internal void FireAutomationEvents() { UpdateSubtree(); } // internal handling of structure chanegd events private void RaisePropertyChangedInternal(IRawElementProviderSimple provider, AutomationProperty propertyId, object oldValue, object newValue) { // Callers have only checked if automation clients are present so filter for any interest in this particular event. if ( provider != null && EventMap.HasRegisteredEvent(AutomationEvents.PropertyChanged) ) { AutomationPropertyChangedEventArgs e = new AutomationPropertyChangedEventArgs(propertyId, oldValue, newValue); AutomationInteropProvider.RaiseAutomationPropertyChangedEvent(provider, e); } } // internal handling of structure changed events private void UpdateChildren() { ListoldChildren = _children; List addedChildren = null; Hashtable ht = null; _childrenValid = false; EnsureChildren(); // Callers have only checked if automation clients are present so filter for any interest in this particular event. if (!EventMap.HasRegisteredEvent(AutomationEvents.StructureChanged)) return; //store old children in a hashtable if(oldChildren != null) { ht = new Hashtable(); for(int count = oldChildren.Count, i = 0; i < count; i++) { ht.Add(oldChildren[i], null); } } //walk over new children, remove the ones that were in the old collection from hash table //and add new ones into addedChildren list int addedCount = 0; if(_children != null) { for(int count = _children.Count, i = 0; i < count; i++) { AutomationPeer child = _children[i]; if(ht != null && ht.ContainsKey(child)) { ht.Remove(child); //same child, nothing to notify } else { if(addedChildren == null) addedChildren = new List (); //stop accumulatin new children here because the notification //is going to become "bulk anyways and exact set of chidlren is not //needed, only count. ++addedCount; if(addedCount <= AutomationInteropProvider.InvalidateLimit) addedChildren.Add(child); } } } //now the ht only has "removed" children. If the count does not yet //calls for "bulk" notification, use per-child notification, otherwise use "bulk" int removedCount = (ht == null ? 0 : ht.Count); if(removedCount + addedCount > AutomationInteropProvider.InvalidateLimit) //bilk invalidation { StructureChangeType flags; // Set bulk event type depending on if these were adds, removes or a mix if (addedCount == 0) flags = StructureChangeType.ChildrenBulkRemoved; else if ( removedCount == 0 ) flags = StructureChangeType.ChildrenBulkAdded; else flags = StructureChangeType.ChildrenInvalidated; IRawElementProviderSimple provider = ProviderFromPeerNoDelegation(this); if(provider != null) { int [] rid = this.GetRuntimeId(); //use runtimeID of parent for bulk notifications AutomationInteropProvider.RaiseStructureChangedEvent( provider, new StructureChangedEventArgs(flags, rid)); } } else if(removedCount > 0) { //for children removed, provider is the parent IRawElementProviderSimple provider = ProviderFromPeerNoDelegation(this); if(provider != null) { //ht contains removed children by now foreach(object key in ht.Keys) { AutomationPeer removedChild = (AutomationPeer)key; int [] rid = removedChild.GetRuntimeId(); AutomationInteropProvider.RaiseStructureChangedEvent( provider, new StructureChangedEventArgs(StructureChangeType.ChildRemoved, rid)); } } } else if(addedCount > 0) { //ht contains removed children by now foreach(AutomationPeer addedChild in addedChildren) { //for children added, provider is the child itself IRawElementProviderSimple provider = ProviderFromPeerNoDelegation(addedChild); if(provider != null) { int [] rid = addedChild.GetRuntimeId(); AutomationInteropProvider.RaiseStructureChangedEvent( provider, new StructureChangedEventArgs(StructureChangeType.ChildAdded, rid)); } } } } // [FriendAccessAllowed] // Built into Core, also used by Framework. internal void UpdateSubtree() { ContextLayoutManager lm = ContextLayoutManager.From(this.Dispatcher); if(lm != null) { lm.AutomationSyncUpdateCounter = lm.AutomationSyncUpdateCounter + 1; try { IRawElementProviderSimple provider = null; bool notifyPropertyChanged = EventMap.HasRegisteredEvent(AutomationEvents.PropertyChanged); bool notifyStructureChanged = EventMap.HasRegisteredEvent(AutomationEvents.StructureChanged); // did anybody ask for property changed norification? if (notifyPropertyChanged) { string itemStatus = GetItemStatusCore(); if (itemStatus != _itemStatus) { if(provider == null) provider = ProviderFromPeerNoDelegation(this); RaisePropertyChangedInternal(provider, AutomationElementIdentifiers.ItemStatusProperty, _itemStatus, itemStatus); _itemStatus = itemStatus; } string name = GetNameCore(); if (name != _name) { if(provider == null) provider = ProviderFromPeerNoDelegation(this); RaisePropertyChangedInternal(provider, AutomationElementIdentifiers.NameProperty, _name, name); _name = name; } bool isOffscreen = IsOffscreenCore(); if (isOffscreen != _isOffscreen) { if(provider == null) provider = ProviderFromPeerNoDelegation(this); RaisePropertyChangedInternal(provider, AutomationElementIdentifiers.IsOffscreenProperty, _isOffscreen, isOffscreen); _isOffscreen = isOffscreen; } bool isEnabled = IsEnabledCore(); if (isEnabled != _isEnabled) { if(provider == null) provider = ProviderFromPeerNoDelegation(this); RaisePropertyChangedInternal(provider, AutomationElementIdentifiers.IsEnabledProperty, _isEnabled, isEnabled); _isEnabled = isEnabled; } } // did anybody ask for structure changed norification? // if somebody asked for property changed then structure must be updated if (_childrenValid || notifyStructureChanged || notifyPropertyChanged) { UpdateChildren(); for(AutomationPeer peer = GetFirstChild(); peer != null; peer = peer.GetNextSibling()) { peer.UpdateSubtree(); } } _invalidated = false; } finally { lm.AutomationSyncUpdateCounter = lm.AutomationSyncUpdateCounter - 1; } } } private static object UpdatePeer(object arg) { AutomationPeer peer = (AutomationPeer)arg; peer.UpdateSubtree(); return null; } internal void AddToAutomationEventList() { if(!_addedToEventList) { ContextLayoutManager lm = ContextLayoutManager.From(this.Dispatcher); lm.AutomationEvents.Add(this); //this adds the root peer into the list of roots, for deferred event firing _addedToEventList = true; } } /// /// Critical - provides access to critial data. /// internal IntPtr Hwnd { [SecurityCritical] get { return _hwnd; } [SecurityCritical] set { _hwnd = value; } } // internal object GetWrappedPattern(int patternId) { object result = null; PatternInfo info = (PatternInfo)s_patternInfo[patternId]; if (info != null) { object iface = GetPattern(info.PatternInterface); if (iface != null) { result = info.WrapObject(this, iface); } } return result; } // internal object GetPropertyValue(int propertyId) { object result = null; GetProperty getProperty = (GetProperty)s_propertyInfo[propertyId]; if (getProperty != null) { result = getProperty(this); } return result; } // internal bool IsInteropPeer { get { return _isInteropPeer; } set { _isInteropPeer = value; } } private static void Initialize() { // initializeing patterns s_patternInfo = new Hashtable(); s_patternInfo[InvokePatternIdentifiers.Pattern.Id] = new PatternInfo(InvokePatternIdentifiers.Pattern.Id, new WrapObject(InvokeProviderWrapper.Wrap), PatternInterface.Invoke); s_patternInfo[SelectionPatternIdentifiers.Pattern.Id] = new PatternInfo(SelectionPatternIdentifiers.Pattern.Id, new WrapObject(SelectionProviderWrapper.Wrap), PatternInterface.Selection); s_patternInfo[ValuePatternIdentifiers.Pattern.Id] = new PatternInfo(ValuePatternIdentifiers.Pattern.Id, new WrapObject(ValueProviderWrapper.Wrap), PatternInterface.Value); s_patternInfo[RangeValuePatternIdentifiers.Pattern.Id] = new PatternInfo(RangeValuePatternIdentifiers.Pattern.Id, new WrapObject(RangeValueProviderWrapper.Wrap), PatternInterface.RangeValue); s_patternInfo[ScrollPatternIdentifiers.Pattern.Id] = new PatternInfo(ScrollPatternIdentifiers.Pattern.Id, new WrapObject(ScrollProviderWrapper.Wrap), PatternInterface.Scroll); s_patternInfo[ScrollItemPatternIdentifiers.Pattern.Id] = new PatternInfo(ScrollItemPatternIdentifiers.Pattern.Id, new WrapObject(ScrollItemProviderWrapper.Wrap), PatternInterface.ScrollItem); s_patternInfo[ExpandCollapsePatternIdentifiers.Pattern.Id] = new PatternInfo(ExpandCollapsePatternIdentifiers.Pattern.Id, new WrapObject(ExpandCollapseProviderWrapper.Wrap), PatternInterface.ExpandCollapse); s_patternInfo[GridPatternIdentifiers.Pattern.Id] = new PatternInfo(GridPatternIdentifiers.Pattern.Id, new WrapObject(GridProviderWrapper.Wrap), PatternInterface.Grid); s_patternInfo[GridItemPatternIdentifiers.Pattern.Id] = new PatternInfo(GridItemPatternIdentifiers.Pattern.Id, new WrapObject(GridItemProviderWrapper.Wrap), PatternInterface.GridItem); s_patternInfo[MultipleViewPatternIdentifiers.Pattern.Id] = new PatternInfo(MultipleViewPatternIdentifiers.Pattern.Id, new WrapObject(MultipleViewProviderWrapper.Wrap), PatternInterface.MultipleView); s_patternInfo[WindowPatternIdentifiers.Pattern.Id] = new PatternInfo(WindowPatternIdentifiers.Pattern.Id, new WrapObject(WindowProviderWrapper.Wrap), PatternInterface.Window); s_patternInfo[SelectionItemPatternIdentifiers.Pattern.Id] = new PatternInfo(SelectionItemPatternIdentifiers.Pattern.Id, new WrapObject(SelectionItemProviderWrapper.Wrap), PatternInterface.SelectionItem); s_patternInfo[DockPatternIdentifiers.Pattern.Id] = new PatternInfo(DockPatternIdentifiers.Pattern.Id, new WrapObject(DockProviderWrapper.Wrap), PatternInterface.Dock); s_patternInfo[TablePatternIdentifiers.Pattern.Id] = new PatternInfo(TablePatternIdentifiers.Pattern.Id, new WrapObject(TableProviderWrapper.Wrap), PatternInterface.Table); s_patternInfo[TableItemPatternIdentifiers.Pattern.Id] = new PatternInfo(TableItemPatternIdentifiers.Pattern.Id, new WrapObject(TableItemProviderWrapper.Wrap), PatternInterface.TableItem); s_patternInfo[TogglePatternIdentifiers.Pattern.Id] = new PatternInfo(TogglePatternIdentifiers.Pattern.Id, new WrapObject(ToggleProviderWrapper.Wrap), PatternInterface.Toggle); s_patternInfo[TransformPatternIdentifiers.Pattern.Id] = new PatternInfo(TransformPatternIdentifiers.Pattern.Id, new WrapObject(TransformProviderWrapper.Wrap), PatternInterface.Transform); s_patternInfo[TextPatternIdentifiers.Pattern.Id] = new PatternInfo(TextPatternIdentifiers.Pattern.Id, new WrapObject(TextProviderWrapper.Wrap), PatternInterface.Text); // initializeing properties s_propertyInfo = new Hashtable(); s_propertyInfo[AutomationElementIdentifiers.IsControlElementProperty.Id] = new GetProperty(IsControlElement); s_propertyInfo[AutomationElementIdentifiers.ControlTypeProperty.Id] = new GetProperty(GetControlType); s_propertyInfo[AutomationElementIdentifiers.IsContentElementProperty.Id] = new GetProperty(IsContentElement); s_propertyInfo[AutomationElementIdentifiers.LabeledByProperty.Id] = new GetProperty(GetLabeledBy); s_propertyInfo[AutomationElementIdentifiers.NativeWindowHandleProperty.Id] = new GetProperty(GetNativeWindowHandle); s_propertyInfo[AutomationElementIdentifiers.AutomationIdProperty.Id] = new GetProperty(GetAutomationId); s_propertyInfo[AutomationElementIdentifiers.ItemTypeProperty.Id] = new GetProperty(GetItemType); s_propertyInfo[AutomationElementIdentifiers.IsPasswordProperty.Id] = new GetProperty(IsPassword); s_propertyInfo[AutomationElementIdentifiers.LocalizedControlTypeProperty.Id] = new GetProperty(GetLocalizedControlType); s_propertyInfo[AutomationElementIdentifiers.NameProperty.Id] = new GetProperty(GetName); s_propertyInfo[AutomationElementIdentifiers.AcceleratorKeyProperty.Id] = new GetProperty(GetAcceleratorKey); s_propertyInfo[AutomationElementIdentifiers.AccessKeyProperty.Id] = new GetProperty(GetAccessKey); s_propertyInfo[AutomationElementIdentifiers.HasKeyboardFocusProperty.Id] = new GetProperty(HasKeyboardFocus); s_propertyInfo[AutomationElementIdentifiers.IsKeyboardFocusableProperty.Id] = new GetProperty(IsKeyboardFocusable); s_propertyInfo[AutomationElementIdentifiers.IsEnabledProperty.Id] = new GetProperty(IsEnabled); s_propertyInfo[AutomationElementIdentifiers.BoundingRectangleProperty.Id] = new GetProperty(GetBoundingRectangle); s_propertyInfo[AutomationElementIdentifiers.ProcessIdProperty.Id] = new GetProperty(GetCurrentProcessId); s_propertyInfo[AutomationElementIdentifiers.RuntimeIdProperty.Id] = new GetProperty(GetRuntimeId); s_propertyInfo[AutomationElementIdentifiers.ClassNameProperty.Id] = new GetProperty(GetClassName); s_propertyInfo[AutomationElementIdentifiers.HelpTextProperty.Id] = new GetProperty(GetHelpText); s_propertyInfo[AutomationElementIdentifiers.ClickablePointProperty.Id] = new GetProperty(GetClickablePoint); s_propertyInfo[AutomationElementIdentifiers.CultureProperty.Id] = new GetProperty(GetCultureInfo); s_propertyInfo[AutomationElementIdentifiers.IsOffscreenProperty.Id] = new GetProperty(IsOffscreen); s_propertyInfo[AutomationElementIdentifiers.OrientationProperty.Id] = new GetProperty(GetOrientation); s_propertyInfo[AutomationElementIdentifiers.FrameworkIdProperty.Id] = new GetProperty(GetFrameworkId); s_propertyInfo[AutomationElementIdentifiers.IsRequiredForFormProperty.Id] = new GetProperty(IsRequiredForForm); s_propertyInfo[AutomationElementIdentifiers.ItemStatusProperty.Id] = new GetProperty(GetItemStatus); s_initialized = true; } private delegate object WrapObject(AutomationPeer peer, object iface); private class PatternInfo { internal PatternInfo(int id, WrapObject wrapObject, PatternInterface patternInterface) { Id = id; WrapObject = wrapObject; PatternInterface = patternInterface; } internal int Id; internal WrapObject WrapObject; internal PatternInterface PatternInterface; } private delegate object GetProperty(AutomationPeer peer); private static object IsControlElement(AutomationPeer peer) { return peer.IsControlElement(); } private static object GetControlType(AutomationPeer peer) { ControlType controlType = peer.GetControlType(); return controlType.Id; } private static object IsContentElement(AutomationPeer peer) { return peer.IsContentElement(); } private static object GetLabeledBy(AutomationPeer peer) { AutomationPeer byPeer = peer.GetLabeledBy(); return ElementProxy.StaticWrap(byPeer, peer); } private static object GetNativeWindowHandle(AutomationPeer peer) { return null /* not used? */; } private static object GetAutomationId(AutomationPeer peer) { return peer.GetAutomationId(); } private static object GetItemType(AutomationPeer peer) { return peer.GetItemType(); } private static object IsPassword(AutomationPeer peer) { return peer.IsPassword(); } private static object GetLocalizedControlType(AutomationPeer peer) { return peer.GetLocalizedControlType(); } private static object GetName(AutomationPeer peer) { return peer.GetName(); } private static object GetAcceleratorKey(AutomationPeer peer) { return peer.GetAcceleratorKey(); } private static object GetAccessKey(AutomationPeer peer) { return peer.GetAccessKey(); } private static object HasKeyboardFocus(AutomationPeer peer) { return peer.HasKeyboardFocus(); } private static object IsKeyboardFocusable(AutomationPeer peer) { return peer.IsKeyboardFocusable(); } private static object IsEnabled(AutomationPeer peer) { return peer.IsEnabled(); } private static object GetBoundingRectangle(AutomationPeer peer) { return peer.GetBoundingRectangle(); } private static object GetCurrentProcessId(AutomationPeer peer) { return SafeNativeMethods.GetCurrentProcessId(); } private static object GetRuntimeId(AutomationPeer peer) { return peer.GetRuntimeId(); } private static object GetClassName(AutomationPeer peer) { return peer.GetClassName(); } private static object GetHelpText(AutomationPeer peer) { return peer.GetHelpText(); } private static object GetClickablePoint(AutomationPeer peer) { Point pt = peer.GetClickablePoint(); return new double[] {pt.X, pt.Y}; } private static object GetCultureInfo(AutomationPeer peer) { return null; } private static object IsOffscreen(AutomationPeer peer) { return peer.IsOffscreen(); } private static object GetOrientation(AutomationPeer peer) { return peer.GetOrientation(); } private static object GetFrameworkId(AutomationPeer peer) { return peer.GetFrameworkId(); } private static object IsRequiredForForm(AutomationPeer peer) { return peer.IsRequiredForForm(); } private static object GetItemStatus(AutomationPeer peer) { return peer.GetItemStatus(); } private static bool s_initialized; private static Hashtable s_patternInfo; private static Hashtable s_propertyInfo; private int _index; ////// Critical - once stored, this hwnd will be used for subsequent automation operations. /// [SecurityCritical] private IntPtr _hwnd; private List_children; private AutomationPeer _parent; private AutomationPeer _eventsSource; private Rect _boundingRectangle; private string _itemStatus; private string _name; private bool _isOffscreen; private bool _isEnabled; private bool _invalidated; private bool _childrenValid; private bool _addedToEventList; private bool _publicCallInProgress; private bool _publicSetFocusInProgress; private bool _isInteropPeer; private static DispatcherOperationCallback _updatePeer = new DispatcherOperationCallback(UpdatePeer); } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- LocalizableAttribute.cs
- StyleBamlRecordReader.cs
- SchemaImporter.cs
- WebServiceHost.cs
- webproxy.cs
- Line.cs
- AssemblyBuilder.cs
- WebPermission.cs
- MetadataArtifactLoaderComposite.cs
- SqlClientFactory.cs
- ContainerAction.cs
- InternalConfigHost.cs
- ResourceDisplayNameAttribute.cs
- SafeTokenHandle.cs
- RIPEMD160.cs
- SelectionEditingBehavior.cs
- Sentence.cs
- CommunicationException.cs
- PolyQuadraticBezierSegment.cs
- WebConfigurationHostFileChange.cs
- MarkupWriter.cs
- StreamAsIStream.cs
- Accessible.cs
- CodeTypeDelegate.cs
- DataGridViewRowsAddedEventArgs.cs
- VoiceChangeEventArgs.cs
- TextRenderer.cs
- PrimitiveXmlSerializers.cs
- DataMisalignedException.cs
- XmlChildEnumerator.cs
- PriorityItem.cs
- IndexedWhereQueryOperator.cs
- Transform3D.cs
- DebugView.cs
- CommandBindingCollection.cs
- CompilerParameters.cs
- OleAutBinder.cs
- CornerRadiusConverter.cs
- StrokeCollection.cs
- RawStylusInputCustomData.cs
- HTTPAPI_VERSION.cs
- TableRowsCollectionEditor.cs
- HostProtectionException.cs
- StretchValidation.cs
- SmtpSpecifiedPickupDirectoryElement.cs
- TableLayoutStyle.cs
- DbMetaDataCollectionNames.cs
- Highlights.cs
- UpDownBase.cs
- QilFunction.cs
- MediaEntryAttribute.cs
- XhtmlBasicLabelAdapter.cs
- UIElementHelper.cs
- DrawingBrush.cs
- InvokeMethodActivityDesigner.cs
- DispatcherOperation.cs
- DocumentPageViewAutomationPeer.cs
- sqlnorm.cs
- Variable.cs
- DetailsViewDeleteEventArgs.cs
- SystemColorTracker.cs
- _DomainName.cs
- EmptyCollection.cs
- CodeStatementCollection.cs
- ObjectHandle.cs
- TimelineClockCollection.cs
- XmlNodeComparer.cs
- IndentTextWriter.cs
- WebPartDisplayModeCollection.cs
- mactripleDES.cs
- SortQuery.cs
- DelegatingConfigHost.cs
- StylusPlugin.cs
- PrintController.cs
- TypedDataSourceCodeGenerator.cs
- SQLStringStorage.cs
- GCHandleCookieTable.cs
- KeyProperty.cs
- EventProviderClassic.cs
- ChtmlSelectionListAdapter.cs
- Binding.cs
- TrackBarDesigner.cs
- SamlAuthenticationClaimResource.cs
- ProcessHostMapPath.cs
- Menu.cs
- XmlElementAttributes.cs
- XsltOutput.cs
- SchemaInfo.cs
- DoubleLinkListEnumerator.cs
- CryptoHandle.cs
- InternalControlCollection.cs
- DataGridViewImageColumn.cs
- AutoResetEvent.cs
- HtmlEmptyTagControlBuilder.cs
- OleDbError.cs
- PasswordBoxAutomationPeer.cs
- MatrixCamera.cs
- DesignerDataRelationship.cs
- AnonymousIdentificationModule.cs
- ObjectHandle.cs