Beispiel #1
0
        // We need to treat MSAA's FOCUS winevents differently depending on the OBJID -
        // OBJID_CLIENT gets routed to the proxies; _MENU and _SYSMENU get speical treatment.
        private AutomationElement GetFocusedElementFromWinEvent(IntPtr hwnd, int idObject, int idChild)
        {
            try
            {
                IRawElementProviderSimple provider = null;
                // These are the only object types that oleacc proxies allow to take focus.
                // (Native IAccessibles can send focus for other custom OBJID valus, but those are no use
                // to us.)
                // Try and get providers for them ourself - if we don't get anything, then
                // defer to core to get the element for the HWND itself.
                if (idObject == UnsafeNativeMethods.OBJID_CLIENT)
                {
                    // regular focus - pass it off to a proxy...
                    provider = ProxyManager.ProxyProviderFromHwnd(NativeMethods.HWND.Cast(hwnd), idChild, UnsafeNativeMethods.OBJID_CLIENT);
                }
                else if (idObject == UnsafeNativeMethods.OBJID_MENU)
                {
                    // menubar focus - see if there's a menubar pseudo-proxy registered...
                    ClientSideProviderFactoryCallback factory = ProxyManager.NonClientMenuBarProxyFactory;
                    if (factory != null)
                    {
                        provider = factory(hwnd, idChild, idObject);
                    }
                }
                else if (idObject == UnsafeNativeMethods.OBJID_SYSMENU)
                {
                    // system menu box focus - see if there's a sysmenu pseudo-proxy registered...
                    ClientSideProviderFactoryCallback factory = ProxyManager.NonClientSysMenuProxyFactory;
                    if (factory != null)
                    {
                        provider = factory(hwnd, idChild, idObject);
                    }
                }
                else if (idObject <= 0)
                {
                    return(null);
                }
                else
                {
                    // This covers OBJID_CLIENT and custom OBJID cases.
                    // Pass it to the proxy manager: most proxies will just handle OBJID_CLIENT,
                    // but the MSAA proxy can potentally handle other OBJID values.
                    provider = ProxyManager.ProxyProviderFromHwnd(NativeMethods.HWND.Cast(hwnd), idChild, idObject);
                }

                if (provider != null)
                {
                    // Ask the fragment root if any of its children really have the focus
                    IRawElementProviderFragmentRoot fragment = provider as IRawElementProviderFragmentRoot;
                    if (fragment != null)
                    {
                        // if we get back something that is different than what we started with and its not null
                        // use that instead.  This is here to get the subset link in the listview but could be usefull
                        // for listview subitems as well.
                        IRawElementProviderSimple realFocus = fragment.GetFocus();
                        if (realFocus != null && !Object.ReferenceEquals(realFocus, provider))
                        {
                            provider = realFocus;
                        }
                    }

                    SafeNodeHandle hnode = UiaCoreApi.UiaNodeFromProvider(provider);
                    return(AutomationElement.Wrap(hnode));
                }
                else
                {
                    // Didn't find a proxy to handle this hwnd - pass off to core...
                    return(AutomationElement.FromHandle(hwnd));
                }
            }
            catch (Exception e)
            {
                if (Misc.IsCriticalException(e))
                {
                    throw;
                }

                return(null);
            }
        }
Beispiel #2
0
        // miscellaneous functions used with Accessible

        internal static bool CompareClass(IntPtr hwnd, string szClass)
        {
            return(ProxyManager.GetClassName(NativeMethods.HWND.Cast(hwnd)) == szClass);
        }
Beispiel #3
0
        // AddListener - Adds a listener for this client and notifies the UIA server.  All event
        // handler additions call through to this method.
        internal static void AddListener(AutomationElement rawEl, Delegate eventCallback, EventListener l)
        {
            lock (_classLock)
            {
                // If we are adding a listener then a proxy could be created as a result of an event so make sure they are loaded
                ProxyManager.LoadDefaultProxies();

                if (_listeners == null)
                {
                    // enough space for 16 AddXxxListeners (100 bytes)
                    _listeners = new ArrayList(16);
                }

                // Start the callback queue that gets us off the server's
                // UI thread when events arrive cross-proc
                CheckStartCallbackQueueing();

                //
                // The framework handles some events on behalf of providers; do those here
                //

                // If listening for BoundingRectangleProperty then may need to start listening on the
                // client-side for LocationChange WinEvent (only use *one* BoundingRectTracker instance).
                if (_winEventTrackers[(int)Tracker.BoundingRect] == null && HasProperty(AutomationElement.BoundingRectangleProperty, l.Properties))
                {
                    // There may be special cases to not map BoundingRect to WinEvent. One may be
                    // where rawEl is a non-top-level native implementation and TreeScope == Element.
                    // Another may be if rawEl is a native impl and TreeScope includes descendents then
                    // may not need to worry about BoundingRect prop change on hosted Win32 UI? I think the
                    // answer is 'yes' because BoundingRectangleProperty should fire events for the top-most
                    // element that moved in the hierarchy.  So if hosted Win32 content Rect changes w/o
                    // the host changing then it would fire this event.
                    // Note: Part of cleaning up WinEvent listeners is to move away from WinEvent handlers calling UIA client handlers
                    AddWinEventListener(Tracker.BoundingRect, new BoundingRectTracker());
                }

                // Start listening for menu event in order to raise MenuOpened/Closed events.
                if (_winEventTrackers [(int)Tracker.MenuOpenedOrClosed] == null && (l.EventId == AutomationElement.MenuOpenedEvent || l.EventId == AutomationElement.MenuClosedEvent))
                {
                    AddWinEventListener(Tracker.MenuOpenedOrClosed, new MenuTracker(new MenuHandler(OnMenuEvent)));
                }

                // Begin watching for hwnd open/close/show/hide so can advise of what events are being listened for.
                // Only advise UI contexts of events being added if the event might be raised by a provider.
                // TopLevelWindow event is raised by UI Automation framework so no need to track new UI.
                // Are there other events like this where Advise can be skipped?
                if (_winEventTrackers[(int)Tracker.WindowShowOrOpen] == null)
                {
                    AddWinEventListener(Tracker.WindowShowOrOpen, new WindowShowOrOpenTracker(new WindowShowOrOpenHandler(OnWindowShowOrOpen)));
                    AddWinEventListener(Tracker.WindowHideOrClose, new WindowHideOrCloseTracker(new WindowHideOrCloseHandler(OnWindowHideOrClose)));
                }

                // If listening for WindowInteractionStateProperty then may need to start listening on the
                // client-side for ObjectStateChange WinEvent.
                if (_winEventTrackers[(int)Tracker.WindowInteractionState] == null && HasProperty(WindowPattern.WindowInteractionStateProperty, l.Properties))
                {
                    AddWinEventListener(Tracker.WindowInteractionState, new WindowInteractionStateTracker());
                }

                // If listening for WindowVisualStateProperty then may need to start listening on the
                // client-side for ObjectLocationChange WinEvent.
                if (_winEventTrackers[(int)Tracker.WindowVisualState] == null && HasProperty(WindowPattern.WindowVisualStateProperty, l.Properties))
                {
                    AddWinEventListener(Tracker.WindowVisualState, new WindowVisualStateTracker());
                }

                // Wrap and store this record on the client...
                EventListenerClientSide ec = new EventListenerClientSide(rawEl, eventCallback, l);
                _listeners.Add(ec);

                // Only advise UI contexts of events being added if the event might be raised by
                // a provider.  TopLevelWindow event is raised by UI Automation framework.
                if (ShouldAdviseProviders(l.EventId))
                {
                    // .. then let the server know about this listener
                    ec.EventHandle = UiaCoreApi.UiaAddEvent(rawEl.RawNode, l.EventId.Id, ec.CallbackDelegate, l.TreeScope, PropertyArrayToIntArray(l.Properties), l.CacheRequest);
                }
            }
        }
        // AddListener - Adds a listener for this client and notifies the UIA server.  All event
        // handler additions call through to this method.
        internal static void AddListener(AutomationElement rawEl, Delegate eventCallback, EventListener l)
        {
            lock (_classLock)
            {
                // If we are adding a listener then a proxy could be created as a result of an event so make sure they are loaded
                ProxyManager.LoadDefaultProxies();

                if (_listeners == null)
                {
                    // enough space for 16 AddXxxListeners (100 bytes)
                    _listeners = new ArrayList(16);
                }

                // Start the callback queue that gets us off the server's
                // UI thread when events arrive cross-proc
                CheckStartCallbackQueueing();

                //
                // The framework handles some events on behalf of providers; do those here
                //

                // If listening for BoundingRectangleProperty then may need to start listening on the
                // client-side for LocationChange WinEvent (only use *one* BoundingRectTracker instance).
                if (_winEventTrackers[(int)Tracker.BoundingRect] == null && HasProperty(AutomationElement.BoundingRectangleProperty, l.Properties))
                {
                    //



                    AddWinEventListener(Tracker.BoundingRect, new BoundingRectTracker());
                }

                // Start listening for menu event in order to raise MenuOpened/Closed events.
                if (_winEventTrackers [(int)Tracker.MenuOpenedOrClosed] == null && (l.EventId == AutomationElement.MenuOpenedEvent || l.EventId == AutomationElement.MenuClosedEvent))
                {
                    AddWinEventListener(Tracker.MenuOpenedOrClosed, new MenuTracker(new MenuHandler(OnMenuEvent)));
                }

                // Begin watching for hwnd open/close/show/hide so can advise of what events are being listened for.
                // Only advise UI contexts of events being added if the event might be raised by a provider.
                // TopLevelWindow event is raised by UI Automation framework so no need to track new UI.
                //
                if (_winEventTrackers[(int)Tracker.WindowShowOrOpen] == null)
                {
                    AddWinEventListener(Tracker.WindowShowOrOpen, new WindowShowOrOpenTracker(new WindowShowOrOpenHandler(OnWindowShowOrOpen)));
                    AddWinEventListener(Tracker.WindowHideOrClose, new WindowHideOrCloseTracker(new WindowHideOrCloseHandler(OnWindowHideOrClose)));
                }

                // If listening for WindowInteractionStateProperty then may need to start listening on the
                // client-side for ObjectStateChange WinEvent.
                if (_winEventTrackers[(int)Tracker.WindowInteractionState] == null && HasProperty(WindowPattern.WindowInteractionStateProperty, l.Properties))
                {
                    AddWinEventListener(Tracker.WindowInteractionState, new WindowInteractionStateTracker());
                }

                // If listening for WindowVisualStateProperty then may need to start listening on the
                // client-side for ObjectLocationChange WinEvent.
                if (_winEventTrackers[(int)Tracker.WindowVisualState] == null && HasProperty(WindowPattern.WindowVisualStateProperty, l.Properties))
                {
                    AddWinEventListener(Tracker.WindowVisualState, new WindowVisualStateTracker());
                }

                // Wrap and store this record on the client...
                EventListenerClientSide ec = new EventListenerClientSide(rawEl, eventCallback, l);
                _listeners.Add(ec);

                // Only advise UI contexts of events being added if the event might be raised by
                // a provider.  TopLevelWindow event is raised by UI Automation framework.
                if (ShouldAdviseProviders(l.EventId))
                {
                    // .. then let the server know about this listener
                    ec.EventHandle = UiaCoreApi.UiaAddEvent(rawEl.RawNode, l.EventId.Id, ec.CallbackDelegate, l.TreeScope, PropertyArrayToIntArray(l.Properties), l.CacheRequest);
                }
            }
        }