public override void RaiseAutomationPropertyChangedEvent(AutomationPropertyChangedEventArgs e) { if (e.Property == AutomationElementIdentifiers.ControlTypeProperty) { //We remove the current Adapter and add it again to reflect the ControlType change StructureChangedEventArgs args = new StructureChangedEventArgs(StructureChangeType.ChildRemoved, new int[] { 0 }); //TODO: Fix ? AutomationInteropProvider.RaiseStructureChangedEvent(Provider, args); args = new StructureChangedEventArgs(StructureChangeType.ChildAdded, new int[] { 0 }); //TODO: Fix ? AutomationInteropProvider.RaiseStructureChangedEvent(Provider, args); } if (e.Property == TogglePatternIdentifiers.ToggleStateProperty) { //if it's a toggle, it should not be a basic Button class, but CheckBox or other throw new NotSupportedException("Toggle events should not land here (should not be reached)"); } else { base.RaiseAutomationPropertyChangedEvent(e); } }
private static void HandleStructureChangedEventWindow(ProxySimple el, IntPtr hwnd, int eventId) { if (eventId == NativeMethods.EventObjectReorder) { AutomationInteropProvider.RaiseStructureChangedEvent(el, new StructureChangedEventArgs(StructureChangeType.ChildrenReordered, el.MakeRuntimeId())); } }
internal static void RaiseStructureChangedEvent(StructureChangeType type, IRawElementProviderFragment provider) { if (AutomationInteropProvider.ClientsAreListening) { int [] runtimeId = null; if (type == StructureChangeType.ChildRemoved) { if (provider.FragmentRoot == null) //FIXME: How to fix it? { runtimeId = provider.GetRuntimeId(); } else { runtimeId = provider.FragmentRoot.GetRuntimeId(); } } else if (type == StructureChangeType.ChildrenBulkAdded || type == StructureChangeType.ChildrenBulkRemoved) { runtimeId = new int[] { 0 } } ; else { runtimeId = provider.GetRuntimeId(); } var invalidatedArgs = new StructureChangedEventArgs(type, runtimeId); AutomationInteropProvider.RaiseStructureChangedEvent(provider, invalidatedArgs); } }
/// <summary> /// Responds to a removal from the UI Automation tree structure /// by raising an event. /// </summary> /// <param name="list"> /// The list from which the item was removed. /// </param> /// <remarks> /// For the runtime Id of the list, pass 0 because the provider cannot know /// what its actual runtime ID is. /// </remarks> public static void OnStructureChangeRemove(CustomListControl list) { if (AutomationInteropProvider.ClientsAreListening) { int[] fakeRuntimeId = { 0 }; StructureChangedEventArgs args = new StructureChangedEventArgs(StructureChangeType.ChildrenBulkRemoved, fakeRuntimeId); AutomationInteropProvider.RaiseStructureChangedEvent( (IRawElementProviderSimple)list.Provider, args); } }
private static void HandleStructureChangedEventClient(ProxySimple el, IntPtr hwnd, int eventId) { if (eventId == NativeMethods.EventObjectCreate) { AutomationInteropProvider.RaiseStructureChangedEvent(el, new StructureChangedEventArgs(StructureChangeType.ChildAdded, el.MakeRuntimeId())); } else if (eventId == NativeMethods.EventObjectDestroy) { AutomationInteropProvider.RaiseStructureChangedEvent(el, new StructureChangedEventArgs(StructureChangeType.ChildRemoved, el.MakeRuntimeId())); } else if (eventId == NativeMethods.EventObjectReorder) { IGridProvider grid = el.GetPatternProvider(GridPattern.Pattern) as IGridProvider; if (grid == null) { return; } AutomationInteropProvider.RaiseStructureChangedEvent(el, new StructureChangedEventArgs(StructureChangeType.ChildrenInvalidated, el.MakeRuntimeId())); } }
public override void RaiseAutomationPropertyChangedEvent(AutomationPropertyChangedEventArgs e) { if (e.Property == AutomationElementIdentifiers.ControlTypeProperty) { //We remove the current Adapter and add it again to reflect the ControlType change StructureChangedEventArgs args = new StructureChangedEventArgs(StructureChangeType.ChildRemoved, new int[] { 0 }); //TODO: Fix ? AutomationInteropProvider.RaiseStructureChangedEvent(Provider, args); args = new StructureChangedEventArgs(StructureChangeType.ChildAdded, new int[] { 0 }); //TODO: Fix ? AutomationInteropProvider.RaiseStructureChangedEvent(Provider, args); } else { base.RaiseAutomationPropertyChangedEvent(e); } }
// fire the structure change event if there is a client listening for it. private void MaybeFireStructureChangeEvent(int eventId, Hashtable eventTable, IntPtr hwnd, int idObject, int idChild) { // if the 2-nd level table contains an entry for this event and element is not the root // (the host hwnd provider takes care of structure changed events for the root.) if (eventTable.ContainsKey(AutomationElement.StructureChangedEvent) && !IsClientObject(idObject, idChild)) { // Note: src element for ChildRemoved cases needs to be the parent, but the runtime id is the child! // the type of structure changed event that we will fire depends on which event we are receiving. // the type then determines the src element -- either the parent or the child -- and the runtime id // -- either the parent or the child -- for the event arguments. IRawElementProviderFragment srcElement; int[] runtimeId = null; StructureChangeType type = StructureChangeType.ChildAdded; // Actual value is assigned below; any value will do here, to init the var switch (eventId) { case NativeMethods.EVENT_OBJECT_CREATE: case NativeMethods.EVENT_OBJECT_SHOW: // src element is child. runtime id is child. srcElement = (IRawElementProviderFragment)MsaaNativeProvider.Create(hwnd, idChild, idObject); if (srcElement != null) { runtimeId = srcElement.GetRuntimeId(); type = StructureChangeType.ChildAdded; } break; //case NativeMethods.EVENT_OBJECT_DESTROY: // src element is parent. runtime id is child. // There is nothing we can do in this case. Since the object is destroyed we can't instantiate // it in order to get its runtime ID. Even if it had a non-zero child id such that we could // instantiate its parent we still couldn't determine the runtime ID of the child that was destroyed. // There's also no guarantee that an EVENT_OBJECT_DESTROY will have a corresponding EVENT_OBJECT_CREATE // and even if it did it might use a different object id so we can't cache the information either. // (Trident for example uses a cyclic counter to generate object ids so the object id can vary for // the same object from one event to the next!) case NativeMethods.EVENT_OBJECT_HIDE: // src element is parent. runtime id is child. srcElement = (IRawElementProviderFragment)MsaaNativeProvider.Create(hwnd, idChild, idObject); if (srcElement != null) { runtimeId = srcElement.GetRuntimeId(); srcElement = (IRawElementProviderFragment)srcElement.Navigate(NavigateDirection.Parent); type = StructureChangeType.ChildRemoved; } break; default: Debug.Assert(eventId == NativeMethods.EVENT_OBJECT_REORDER); // src element is parent. runtime id is parent. srcElement = (IRawElementProviderFragment)MsaaNativeProvider.Create(hwnd, idChild, idObject); if (srcElement != null) { runtimeId = srcElement.GetRuntimeId(); type = StructureChangeType.ChildrenReordered; } break; } if (srcElement != null) { // fire the event StructureChangedEventArgs eventArgs = new StructureChangedEventArgs(type, runtimeId); //Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Firing structure change event for {0}", hwnd), "NativeMsaaProxy"); AutomationInteropProvider.RaiseStructureChangedEvent(srcElement, eventArgs); } } }
private static void RaiseEventsOnClient(IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { ProxySimple el = null; WindowsListBox wlb = (WindowsListBox)WindowsListBox.Create(hwnd, 0); // Upon creation, a single selection Listbox can have no selection to start with // however once an item has been selection, the selection cannot be removed. // This WinEvent can only be received once, on the first selection. // Once the notification is received the notification handler is removed to not get it a // second time. if ((eventId == NativeMethods.EventObjectSelection || eventId == NativeMethods.EventObjectSelectionAdd) && (idProp as AutomationProperty) == SelectionPattern.IsSelectionRequiredProperty) { // This array must be kept in sync with the array in PropertyToWinEvent WinEventTracker.EvtIdProperty[] aEvtIdProperties = new WinEventTracker.EvtIdProperty[] { new WinEventTracker.EvtIdProperty(NativeMethods.EventObjectSelection, SelectionPattern.IsSelectionRequiredProperty) }; WinEventTracker.RemoveToNotificationList(hwnd, aEvtIdProperties, null, aEvtIdProperties.Length); el = wlb; } else if (eventId == NativeMethods.EventObjectSelection || eventId == NativeMethods.EventObjectSelectionRemove || eventId == NativeMethods.EventObjectSelectionAdd) { bool isMultipleSelection = wlb.IsMultipleSelection(); // User should send SelectionAdd for a Multiselect listbox but it sends instead // Selection. The code below fixes the if (eventId == NativeMethods.EventObjectSelection && isMultipleSelection && wlb.HasOtherSelections(idChild - 1)) { eventId = NativeMethods.EventObjectSelectionAdd; } // The spec says a ElementSelectionEvent should be fired when action causes only one // selection. if ((eventId == NativeMethods.EventObjectSelectionRemove || eventId == NativeMethods.EventObjectSelectionAdd) && isMultipleSelection && wlb.GetSelectionCount() == 1) { // The net result of the user action is that there is only one item selected in the // listbox, so change the event to an EventObjectSelected. idProp = SelectionItemPattern.ElementSelectedEvent; eventId = NativeMethods.EventObjectSelection; // Now need to find what item is selected. int selection = wlb.GetOtherSelection(idChild - 1); if (selection != NativeMethods.LB_ERR) { idChild = selection; } } el = wlb.CreateListboxItem(idChild - 1); } else { el = wlb; } // Special case for logical element change for listbox item if ((idProp as AutomationEvent) == AutomationElement.StructureChangedEvent && (eventId == NativeMethods.EventObjectDestroy || eventId == NativeMethods.EventObjectCreate)) { // Since children are referenced by position in the tree, addition and removal // of items leads to different results when asking properties for the same element // On removal, item + 1 is now item! // Use Children Invalidated to let the client knows that all the cached AutomationInteropProvider.RaiseStructureChangedEvent(wlb, new StructureChangedEventArgs(StructureChangeType.ChildrenInvalidated, wlb.MakeRuntimeId())); return; } if (el != null) { el.DispatchEvents(eventId, idProp, idObject, idChild); } }
private void AddProvider(IRawElementProviderSimple provider) { AutomationInteropProvider.RaiseStructureChangedEvent(provider, new StructureChangedEventArgs(StructureChangeType.ChildAdded, new int [0])); }