//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods private void OnStateChange(IntPtr hwnd, int idObject, int idChild) { NativeMethods.HWND nativeHwnd = NativeMethods.HWND.Cast(hwnd); // Ignore windows that have been destroyed if (!SafeNativeMethods.IsWindow(nativeHwnd)) { return; } AutomationElement rawEl = AutomationElement.FromHandle(hwnd); try { rawEl.GetCurrentPattern(WindowPattern.Pattern); } catch (InvalidOperationException) { // Only raise this event for elements with the WindowPattern. return; } Object windowInteractionState = rawEl.GetPatternPropertyValue(WindowPattern.WindowInteractionStateProperty, false); // if has no state value just return if (!(windowInteractionState is WindowInteractionState)) { return; } WindowInteractionState state = (WindowInteractionState)windowInteractionState; // Filter... avoid duplicate events if (hwnd == _lastHwnd && state == _lastState) { return; } AutomationPropertyChangedEventArgs e = new AutomationPropertyChangedEventArgs( WindowPattern.WindowInteractionStateProperty, hwnd == _lastHwnd ? _lastState : WindowInteractionState.Running, state); ClientEventManager.RaiseEventInThisClientOnly(AutomationElement.AutomationPropertyChangedEvent, rawEl, e); // save the last hwnd/rect for filtering out duplicates _lastHwnd = hwnd; _lastState = state; }
private void HandleBoundingRectChange(IntPtr hwnd) { NativeMethods.HWND nativeHwnd = NativeMethods.HWND.Cast(hwnd); NativeMethods.RECT rc32 = new NativeMethods.RECT(0, 0, 0, 0); // if GetWindwRect fails, most likely the nativeHwnd is an invalid window, so just return. if (!Misc.GetWindowRect(nativeHwnd, out rc32)) { return; } // Filter... avoid duplicate events if (hwnd == _lastHwnd && Compare(rc32, _lastRect)) { return; } AutomationElement rawEl = AutomationElement.FromHandle(hwnd); // Problem with Avalon combo box & menus: // There was a windows issue where we get two events. One for the hwnd (LocationChange WinEvent) // and one for the [usually] DockPanel (Avalon BoundingRectangleProperty change). Both have the // same Rect value. It's unclear is this issue is still occuring and what (if anything) needs to be done. // Waiting for WPP redesign to investigate further how to filter out the duplicate which // happens to be the first (hwnd-based) event. // AutomationPropertyChangedEventArgs e = new AutomationPropertyChangedEventArgs( AutomationElement.BoundingRectangleProperty, Rect.Empty, new Rect(rc32.left, rc32.top, rc32.right - rc32.left, rc32.bottom - rc32.top)); // In the case of HWND hosted Avalon content, we will get a LocationChange WinEvent for the host // window when it's bounding rect changes (e.g. an Avalon window is resized) and we won't (that I've seen) // get a BoundingRect property change from the Avalon content. Therefore, we need to map the WinEvent. // In this case, rawEl is already the remote object. It's ol to call this locally since this is called // to handle a WinEvent (e.g. always called on client-side). Since rawEl may be local (proxied) or // remote (native) impl then use that version of RaiseEventInThisClientOnly ClientEventManager.RaiseEventInThisClientOnly(AutomationElement.AutomationPropertyChangedEvent, rawEl, e); // save the last hwnd/rect for filtering out duplicates _lastHwnd = hwnd; _lastRect = rc32; }
private void HandleBoundingRectChange(IntPtr hwnd) { NativeMethods.HWND nativeHwnd = NativeMethods.HWND.Cast(hwnd); NativeMethods.RECT rc32 = new NativeMethods.RECT(0, 0, 0, 0); // if GetWindwRect fails, most likely the nativeHwnd is an invalid window, so just return. if (!Misc.GetWindowRect(nativeHwnd, out rc32)) { return; } // Filter... avoid duplicate events if (hwnd == _lastHwnd && Compare(rc32, _lastRect)) { return; } AutomationElement rawEl = AutomationElement.FromHandle(hwnd); // // AutomationPropertyChangedEventArgs e = new AutomationPropertyChangedEventArgs( AutomationElement.BoundingRectangleProperty, Rect.Empty, new Rect(rc32.left, rc32.top, rc32.right - rc32.left, rc32.bottom - rc32.top)); // ClientEventManager.RaiseEventInThisClientOnly(AutomationElement.AutomationPropertyChangedEvent, rawEl, e); // save the last hwnd/rect for filtering out duplicates _lastHwnd = hwnd; _lastRect = rc32; }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods // HandleFocusChange - Called when a WinEvent we're listening to indicates the // focus has changed. This is where the callback to the client is queued. private void HandleFocusChange(IntPtr hwnd, Accessible acc, int idObject, int idChild, uint eventTime) { // If there is an hwnd then notify of a focus change if (hwnd != IntPtr.Zero) { Debug.Assert(acc != null, "HandleFocusChange got hwnd and null IAccessible"); // Create an event args and get the source logical element AutomationFocusChangedEventArgs e = new InternalAutomationFocusChangedEventArgs(idObject, idChild, eventTime); AutomationElement srcEl = GetFocusedElementFromWinEvent(hwnd, idObject, idChild); if (srcEl == null) { // Don't raise focus change events for UI that is gone. This has been seen when toolbar menus are // being manipulated (e.g. mnu.SubMenu("File").MenuItems("Close").Click() in MITA). We should be // seeing another focus change soon and with that event we can re-establish focus. return; } // Check that item is actually focused // Don't do this for statics - the controls in the color picker are statics, and // they get focus, but OLEACC assumes statics don't get focus, so never sets the // focus bit. So, for now, assume statics that send focus do actually have focus. if (!Accessible.IsStatic(hwnd) && !Accessible.IsComboDropdown(hwnd)) { // instead of depending on oleacc to see if something has focus ask provider if (!(bool)srcEl.GetCurrentPropertyValue(AutomationElement.HasKeyboardFocusProperty)) { return; } } // Do notifies ClientEventManager.RaiseEventInThisClientOnly(AutomationElement.AutomationFocusChangedEvent, srcEl, e); } // Keep track of where we are right now (may be unknown/null) _accCurrent = acc; }