コード例 #1
0
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        internal override void WinEventProc(int eventId, IntPtr hwnd, int idObject, int idChild, uint eventTime)
        {
            // ignore any event not pertaining directly to the window
            if (idObject != UnsafeNativeMethods.OBJID_WINDOW)
            {
                return;
            }

            // Ignore if this is a bogus hwnd (shouldn't happen)
            if (hwnd == IntPtr.Zero)
            {
                return;
            }

            NativeMethods.HWND nativeHwnd = NativeMethods.HWND.Cast(hwnd);

            // Purposefully including windows that have been destroyed (e.g. IsWindow will return
            // false here for EVENT_OBJECT_DESTROY) because we need that notification.
            if (eventId == NativeMethods.EVENT_OBJECT_HIDE && !SafeNativeMethods.IsWindow(nativeHwnd))
            {
                return;
            }

            int[]             runtimeId;
            AutomationElement rawEl;

            if (eventId == NativeMethods.EVENT_OBJECT_DESTROY)
            {
                // If the window has been destroyed just report the RuntimeId with the event.
                runtimeId = HwndProxyElementProvider.MakeRuntimeId(nativeHwnd);
                rawEl     = null;
            }
            else
            {
                // If the window is just being hidden then can create (and return as event src) a real element
                rawEl     = AutomationElement.FromHandle(hwnd);
                runtimeId = rawEl.GetRuntimeId();
            }

            // Do the notify.  Note that this handler is used to notify client-side UIAutomation providers of windows
            // being destroyed or hidden.  The delegate called here is itself protected by a lock.  This delegate may
            // call out to proxies but also calls ClientEventManager.RaiseEventInThisClientOnly which properly
            // queues the actual callout to client code.
            object[] handlers = GetHandlers();
            Debug.Assert(handlers.Length <= 1, "handlers.Length");
            if (handlers.Length > 0)
            {
                ((WindowHideOrCloseHandler)handlers [0])(hwnd, rawEl, runtimeId);
            }
        }
コード例 #2
0
        /// <summary>
        /// Called by a client to add a listener for pattern or custom events.
        /// </summary>
        /// <param name="eventId">A control pattern or custom event identifier.</param>
        /// <param name="element">Element on which to listen for control pattern or custom events.</param>
        /// <param name="scope">Specifies whether to listen to property changes events on the specified element, and/or its ancestors and children.</param>
        /// <param name="eventHandler">Delegate to call when the specified event occurs.</param>
        ///
        /// <outside_see conditional="false">
        /// This API does not work inside the secure execution environment.
        /// <exception cref="System.Security.Permissions.SecurityPermission"/>
        /// </outside_see>
        public static void AddAutomationEventHandler(
            AutomationEvent eventId,
            AutomationElement element,
            TreeScope scope,
            AutomationEventHandler eventHandler
            )
        {
            Misc.ValidateArgumentNonNull(element, "element");
            Misc.ValidateArgumentNonNull(eventHandler, "eventHandler");
            Misc.ValidateArgument(eventId != AutomationElement.AutomationFocusChangedEvent, SRID.EventIdMustNotBeAutomationFocusChanged);
            Misc.ValidateArgument(eventId != AutomationElement.StructureChangedEvent, SRID.EventIdMustNotBeStructureChanged);
            Misc.ValidateArgument(eventId != AutomationElement.AutomationPropertyChangedEvent, SRID.EventIdMustNotBeAutomationPropertyChanged);

            if (eventId == WindowPattern.WindowClosedEvent)
            {
                // Once a window closes and the hwnd is destroyed we won't be able to determine where it was in the
                // Automation tree; therefore only support WindowClosed events for all windows (eg. src==root and scope
                // is descendants) or a specific WindowPattern element (src==root of a Window and scope is the element).
                // Also handle odd combinations (eg. src==specific element and scope is subtree|ancestors).

                bool paramsValidated = false;

                if (Misc.Compare(element, AutomationElement.RootElement))
                {
                    // For root element need to have Descendants scope set (Note: Subtree includes Descendants)
                    if ((scope & TreeScope.Descendants) == TreeScope.Descendants)
                    {
                        paramsValidated = true;
                    }
                }
                else
                {
                    // otherwise non-root elements must have the entire tree (Anscestors, Element and Descendants)...
                    if ((scope & (TreeScope.Ancestors | TreeScope.Element | TreeScope.Descendants)) == (TreeScope.Ancestors | TreeScope.Element | TreeScope.Descendants))
                    {
                        paramsValidated = true;
                    }
                    else if ((scope & TreeScope.Element) == TreeScope.Element)
                    {
                        // ...OR Element where the element implements WindowPattern
                        // PRESHARP will flag this as warning 56506/6506:Parameter 'element' to this public method must be validated: A null-dereference can occur here.
                        // False positive, element is checked, see above
#pragma warning suppress 6506
                        object val = element.GetCurrentPropertyValue(AutomationElement.NativeWindowHandleProperty);
                        if (val != null && val is int && (int)val != 0)
                        {
                            if (HwndProxyElementProvider.IsWindowPatternWindow(NativeMethods.HWND.Cast(new IntPtr((int)val))))
                            {
                                paramsValidated = true;
                            }
                        }
                    }
                }

                if (!paramsValidated)
                {
                    throw new ArgumentException(SR.Get(SRID.ParamsNotApplicableToWindowClosedEvent));
                }
            }

            // Add a client-side Handler for for this event request
            EventListener l = new EventListener(eventId, scope, null, CacheRequest.CurrentUiaCacheRequest);
            ClientEventManager.AddListener(element, eventHandler, l);
        }
コード例 #3
0
        // OnWindowShowOrOpen - Called by the WindowShowOrOpenTracker class when UI is shown or created
        private static void OnWindowShowOrOpen(IntPtr hwnd, AutomationElement rawEl)
        {
            bool doWindowOpenedEvent     = false;
            bool doStructureChangedEvent = false;

            lock ( _classLock )
            {
                if (_listeners != null)
                {
                    // if rawEl is w/in the scope of any listeners then register for events in the new UI
                    for (int i = 0; i < _listeners.Count; i++)
                    {
                        EventListenerClientSide ec = (EventListenerClientSide)_listeners[i];

                        EventListener l = ec.EventListener;
                        if (l.EventId == WindowPattern.WindowOpenedEvent)
                        {
                            doWindowOpenedEvent = true;
                        }
                        if (l.EventId == AutomationElement.StructureChangedEvent)
                        {
                            doStructureChangedEvent = true;
                        }

                        // Only advise UI contexts if the provider might raise that event.
                        if (!ShouldAdviseProviders(l.EventId))
                        {
                            continue;
                        }

                        // Only advise UI contexts if the element is w/in scope of the reference element
                        if (!ec.WithinScope(rawEl))
                        {
                            continue;
                        }

                        // Notify the server side
                        UiaCoreApi.UiaEventAddWindow(ec.EventHandle, hwnd);
                    }
                }
            }

            // Piggy-back on the listener for Windows hiding or closing to raise WindowClosed and StructureChanged events.
            if (doWindowOpenedEvent)
            {
                if (HwndProxyElementProvider.IsWindowPatternWindow(NativeMethods.HWND.Cast(hwnd)))
                {
                    // Go ahead and raise a client-side only WindowOpenedEvent (if anyone is listening)
                    AutomationEventArgs e = new AutomationEventArgs(WindowPattern.WindowOpenedEvent);
                    RaiseEventInThisClientOnly(WindowPattern.WindowOpenedEvent, rawEl, e);
                }
            }
            if (doStructureChangedEvent)
            {
                // Filter on the control elements.  Otherwise, this is extremely noisy.  Consider not filtering if there is feedback.
                //ControlType ct = (ControlType)rawEl.GetPropertyValue( AutomationElement.ControlTypeProperty );
                //if ( ct != null )
                {
                    // Last,raise an event for structure changed
                    StructureChangedEventArgs e = new StructureChangedEventArgs(StructureChangeType.ChildAdded, rawEl.GetRuntimeId());
                    RaiseEventInThisClientOnly(AutomationElement.StructureChangedEvent, rawEl, e);
                }
            }
        }
コード例 #4
0
        // OnWindowHideOrClose - Called by the WindowHideOrCloseTracker class when UI is hidden or destroyed
        private static void OnWindowHideOrClose(IntPtr hwnd, AutomationElement rawEl, int [] runtimeId)
        {
            bool doWindowClosedEvent     = false;
            bool doStructureChangedEvent = false;

            lock ( _classLock )
            {
                if (_listeners != null)
                {
                    // if an hwnd is hidden or closed remove event listeners for the window's provider
                    for (int i = 0; i < _listeners.Count; i++)
                    {
                        EventListenerClientSide ec = (EventListenerClientSide)_listeners[i];

                        EventListener l = ec.EventListener;
                        if (l.EventId == WindowPattern.WindowClosedEvent)
                        {
                            doWindowClosedEvent = true;
                        }
                        if (l.EventId == AutomationElement.StructureChangedEvent)
                        {
                            doStructureChangedEvent = true;
                        }

                        // Only advise UI contexts if the provider still exists
                        // (but keep looking to see if need to do a WindowClosedEvent)
                        if (rawEl == null)
                        {
                            continue;
                        }

                        // Only advise UI contexts if the provider might raise that event.
                        if (!ShouldAdviseProviders(l.EventId))
                        {
                            continue;
                        }

                        // Only advise UI contexts if the element is w/in scope of the reference element
                        if (!ec.WithinScope(rawEl))
                        {
                            continue;
                        }

                        // Notify the server-side that this event is no longer interesting
                        UiaCoreApi.UiaEventRemoveWindow(ec.EventHandle, hwnd);
                    }
                }
            }

            // Piggy-back on the listener for Windows hiding or closing to raise WindowClosed and StructureChanged events.
            // When the hwnd behind rawEl is being destroyed, it can't be determined that rawEl once had the
            // WindowPattern interface.  Therefore raise an event for any window close.
            if (doWindowClosedEvent)
            {
                // When the hwnd is just hidden, rawEl will not be null, so can test if this would support WindowPattern
                // and throw this event away if the window doesn't support that CP
                if (rawEl != null && !HwndProxyElementProvider.IsWindowPatternWindow(NativeMethods.HWND.Cast(hwnd)))
                {
                    return;
                }

                // Go ahead and raise a client-side only WindowClosedEvent (if anyone is listening)
                WindowClosedEventArgs e = new WindowClosedEventArgs(runtimeId);
                RaiseEventInThisClientOnly(WindowPattern.WindowClosedEvent, runtimeId, e);
            }
            if (doStructureChangedEvent)
            {
                // Raise an event for structure changed.  This element has essentially gone away so there isn't an
                // opportunity to do filtering here.  So, just like WindowClosed, this event will be very noisy.
                StructureChangedEventArgs e = new StructureChangedEventArgs(StructureChangeType.ChildRemoved, runtimeId);
                RaiseEventInThisClientOnly(AutomationElement.StructureChangedEvent, runtimeId, e);
            }
        }