// Static Create method called by the event tracker system // WinEvents are one throwns because items exist. so it makes sense to create the item and // check for details afterward. internal static void RaiseEvents(IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { // NOTE: List may be a portion of the Combobox // Use WindowsListBox.Create in order to set-up a correct parenthood chain switch (idObject) { case NativeMethods.OBJID_WINDOW: RaiseEventsOnWindow(hwnd, eventId, idProp, idObject, idChild); break; case NativeMethods.OBJID_CLIENT: RaiseEventsOnClient(hwnd, eventId, idProp, idObject, idChild); break; case NativeMethods.OBJID_VSCROLL: case NativeMethods.OBJID_HSCROLL: break; default: ProxySimple el = (ProxyHwnd)WindowsListBox.Create(hwnd, 0); if (el != null) { el.DispatchEvents(eventId, idProp, idObject, idChild); } break; } }
private static void RaiseEventsOnClient(IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { if (Misc.GetClassName(hwnd) == "ComboLBox") { ProxySimple el = (ProxySimple)WindowsListBox.Create(hwnd, idChild); if (el != null) { el.DispatchEvents(eventId, idProp, idObject, idChild); } } }
internal static IRawElementProviderSimple Create(IntPtr hwnd, int idChild) { bool parentedByCombo = false; ProxyFragment parent = null; int item = 0; try { int style = Misc.GetWindowStyle(hwnd); // If can not get windows style the hwnd is bad so do not create a proxy for it. if (style == 0) { return(null); } if (Misc.IsBitSet(style, NativeMethods.LBS_COMBOBOX)) { // List portion of combo box NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (WindowsComboBox.GetComboInfo(hwnd, ref cbInfo) && (cbInfo.hwndCombo != IntPtr.Zero)) { parent = (ProxyFragment)WindowsComboBox.Create(cbInfo.hwndCombo, 0); parentedByCombo = true; item = (int)WindowsComboBox.ComboChildren.List; } } } catch (ElementNotAvailableException) { return(null); } WindowsListBox listbox = new WindowsListBox(hwnd, parent, item, parentedByCombo); if (idChild == 0) { return(listbox); } else { return(listbox.CreateListboxItem(idChild - 1)); } }
internal override void AdviseEventRemoved(AutomationEvent eventId, AutomationProperty [] aidProps) { // remove combo-related events base.AdviseEventRemoved(eventId, aidProps); NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo)) { // remove edit and list specific events that got remapped into combo's events if (eventId == AutomationElement.AutomationPropertyChangedEvent) { // ComboBoxEx32 controls with the style CBS_DROPDOWNLIST are still editable. if (cbInfo.hwndItem != IntPtr.Zero && IsEditableCombo()) { // un-subscribe from edit-specific notifications // ValueAsString, ValueAsObject, IsReadOnly // create array containing events from which user wants to unsubscribe WinEventTracker.EvtIdProperty [] editPortionEvents; int counter; CreateEditPortionEvents(out editPortionEvents, out counter, aidProps); if (counter > 0) { WinEventTracker.RemoveToNotificationList(cbInfo.hwndItem, editPortionEvents, null, counter); } } } // Need to also remove the advise from the list portions of the combobox. if (cbInfo.hwndList != IntPtr.Zero) { WindowsListBox listbox = new WindowsListBox(cbInfo.hwndList, this, 0, true); listbox.AdviseEventRemoved(eventId, aidProps); } } }
// override the default implementation so we can handle the WinEvents that are send to the edit // portion of ComboBox (Combo proxy will hide edit portion from the user, but will take care of all // the features/functionality that Edit presents) and some(show, hide) events that are send to the List portion of combo // In both cases this events will be presented to the user as Combo's LE events internal override void AdviseEventAdded(AutomationEvent eventId, AutomationProperty [] aidProps) { // call the base class implementation first to add combo-specific things and register combo specific callback base.AdviseEventAdded(eventId, aidProps); NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo)) { if (eventId == AutomationElement.AutomationPropertyChangedEvent) { // ComboBoxEx32 controls with the style CBS_DROPDOWNLIST are still editable. if (cbInfo.hwndItem != IntPtr.Zero && IsEditableCombo()) { // subscribe to edit-specific notifications, that would be presented as combo le event // ValueAsString, ValueAsObject, IsReadOnly // create array containing events that user is interested in WinEventTracker.EvtIdProperty [] editPortionEvents; int counter; CreateEditPortionEvents(out editPortionEvents, out counter, aidProps); if (counter > 0) { WinEventTracker.AddToNotificationList(cbInfo.hwndItem, new WinEventTracker.ProxyRaiseEvents(EditPortionEvents), editPortionEvents, counter); } } } // Need to also advise the list portions of the combobox so that it can raise events. if (cbInfo.hwndList != IntPtr.Zero) { WindowsListBox listbox = new WindowsListBox(cbInfo.hwndList, this, 0, true); listbox.AdviseEventAdded(eventId, aidProps); } } }
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); } }
internal static IRawElementProviderSimple Create(IntPtr hwnd, int idChild) { bool parentedByCombo = false; ProxyFragment parent = null; int item = 0; try { int style = Misc.GetWindowStyle(hwnd); // If can not get windows style the hwnd is bad so do not create a proxy for it. if (style == 0) { return null; } if (Misc.IsBitSet(style, NativeMethods.LBS_COMBOBOX)) { // List portion of combo box NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (WindowsComboBox.GetComboInfo(hwnd, ref cbInfo) && (cbInfo.hwndCombo != IntPtr.Zero)) { parent = (ProxyFragment)WindowsComboBox.Create(cbInfo.hwndCombo, 0); parentedByCombo = true; item = (int)WindowsComboBox.ComboChildren.List; } } } catch (ElementNotAvailableException) { return null; } WindowsListBox listbox = new WindowsListBox (hwnd, parent, item, parentedByCombo); if (idChild == 0) { return listbox; } else { return listbox.CreateListboxItem(idChild - 1); } }
internal override void AdviseEventRemoved (AutomationEvent eventId, AutomationProperty [] aidProps) { // remove combo-related events base.AdviseEventRemoved (eventId, aidProps); NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo)) { // remove edit and list specific events that got remapped into combo's events if (eventId == AutomationElement.AutomationPropertyChangedEvent) { // ComboBoxEx32 controls with the style CBS_DROPDOWNLIST are still editable. if (cbInfo.hwndItem != IntPtr.Zero && IsEditableCombo()) { // un-subscribe from edit-specific notifications // ValueAsString, ValueAsObject, IsReadOnly // create array containing events from which user wants to unsubscribe WinEventTracker.EvtIdProperty [] editPortionEvents; int counter; CreateEditPortionEvents (out editPortionEvents, out counter, aidProps); if ( counter > 0 ) { WinEventTracker.RemoveToNotificationList( cbInfo.hwndItem, editPortionEvents, null, counter ); } } } // Need to also remove the advise from the list portions of the combobox. if (cbInfo.hwndList != IntPtr.Zero) { WindowsListBox listbox = new WindowsListBox(cbInfo.hwndList, this, 0, true); listbox.AdviseEventRemoved(eventId, aidProps); } } }
// override the default implementation so we can handle the WinEvents that are send to the edit // portion of ComboBox (Combo proxy will hide edit portion from the user, but will take care of all // the features/functionality that Edit presents) and some(show, hide) events that are send to the List portion of combo // In both cases this events will be presented to the user as Combo's LE events internal override void AdviseEventAdded (AutomationEvent eventId, AutomationProperty [] aidProps) { // call the base class implementation first to add combo-specific things and register combo specific callback base.AdviseEventAdded (eventId, aidProps); NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo)) { if (eventId == AutomationElement.AutomationPropertyChangedEvent) { // ComboBoxEx32 controls with the style CBS_DROPDOWNLIST are still editable. if (cbInfo.hwndItem != IntPtr.Zero && IsEditableCombo()) { // subscribe to edit-specific notifications, that would be presented as combo le event // ValueAsString, ValueAsObject, IsReadOnly // create array containing events that user is interested in WinEventTracker.EvtIdProperty [] editPortionEvents; int counter; CreateEditPortionEvents (out editPortionEvents, out counter, aidProps); if ( counter > 0 ) { WinEventTracker.AddToNotificationList( cbInfo.hwndItem, new WinEventTracker.ProxyRaiseEvents( EditPortionEvents ), editPortionEvents, counter ); } } } // Need to also advise the list portions of the combobox so that it can raise events. if (cbInfo.hwndList != IntPtr.Zero) { WindowsListBox listbox = new WindowsListBox(cbInfo.hwndList, this, 0, true); listbox.AdviseEventAdded(eventId, aidProps); } } }
private static void RaiseEventsOnScroll(IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { if ((idProp == ScrollPattern.VerticalScrollPercentProperty && idObject != NativeMethods.OBJID_VSCROLL) || (idProp == ScrollPattern.HorizontalScrollPercentProperty && idObject != NativeMethods.OBJID_HSCROLL)) { return; } ProxyFragment el = new NonClientArea(hwnd); if (el == null) { return; } if (idProp == InvokePattern.InvokedEvent) { NonClientItem item = idObject == NativeMethods.OBJID_HSCROLL ? NonClientItem.HScrollBar : NonClientItem.VScrollBar; int sbFlag = idObject == NativeMethods.OBJID_HSCROLL ? NativeMethods.SB_HORZ : NativeMethods.SB_VERT; ProxyFragment scrollBar = new WindowsScrollBar(hwnd, el, (int)item, sbFlag); if (scrollBar != null) { ProxySimple scrollBarBit = WindowsScrollBarBits.CreateFromChildId(hwnd, scrollBar, idChild, sbFlag); if (scrollBarBit != null) { scrollBarBit.DispatchEvents(eventId, idProp, idObject, idChild); } } return; } if (eventId == NativeMethods.EventObjectStateChange && idProp == ValuePattern.IsReadOnlyProperty) { if (idChild == 0) { // if (idObject == NativeMethods.OBJID_HSCROLL || idObject == NativeMethods.OBJID_VSCROLL) { idObject = NativeMethods.OBJID_WINDOW; } el.DispatchEvents(eventId, idProp, idObject, idChild); } return; } if (idProp == ValuePattern.ValueProperty && eventId == NativeMethods.EVENT_OBJECT_VALUECHANGE) { NonClientItem item = idObject == NativeMethods.OBJID_HSCROLL ? NonClientItem.HScrollBar : NonClientItem.VScrollBar; WindowsScrollBar scrollBar = new WindowsScrollBar(hwnd, el, (int)item, idObject == NativeMethods.OBJID_HSCROLL ? NativeMethods.SB_HORZ : NativeMethods.SB_VERT); scrollBar.DispatchEvents(0, ValuePattern.ValueProperty, NativeMethods.OBJID_CLIENT, 0); return; } if (Misc.GetClassName(hwnd) == "ComboLBox") { el = (ProxyFragment)WindowsListBox.Create(hwnd, 0); } if (el != null) { el.DispatchEvents(eventId, idProp, idObject, idChild); } }
private static void RaiseEventsOnScroll(IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { if ((idProp == ScrollPattern.VerticalScrollPercentProperty && idObject != NativeMethods.OBJID_VSCROLL) || (idProp == ScrollPattern.HorizontalScrollPercentProperty && idObject != NativeMethods.OBJID_HSCROLL)) { return; } ProxyFragment el = new NonClientArea(hwnd); if (el == null) { return; } if (idProp == InvokePattern.InvokedEvent) { NonClientItem item = idObject == NativeMethods.OBJID_HSCROLL ? NonClientItem.HScrollBar : NonClientItem.VScrollBar; int sbFlag = idObject == NativeMethods.OBJID_HSCROLL ? NativeMethods.SB_HORZ : NativeMethods.SB_VERT; ProxyFragment scrollBar = new WindowsScrollBar(hwnd, el, (int)item, sbFlag); if (scrollBar != null) { ProxySimple scrollBarBit = WindowsScrollBarBits.CreateFromChildId(hwnd, scrollBar, idChild, sbFlag); if (scrollBarBit != null) { scrollBarBit.DispatchEvents(eventId, idProp, idObject, idChild); } } return; } if (eventId == NativeMethods.EventObjectStateChange && idProp == ValuePattern.IsReadOnlyProperty) { if (idChild == 0) { // This code is never exercised. The code in User needs to change to send // EventObjectStateChange with a client ID of zero // // UIA works differently than MSAA. Events are set for elements rather than hwnd // Scroll bar are processed the same way whatever they are part of the non client area // or stand alone hwnd. OBJID_HSCROLL and OBJID_VSCROLL are mapped to OBJID_WINDOW // so they behave the same for NC and hwnd SB. // Parameters are setup so that the dispatch will send the proper notification and // recursively will send notifications to all of the children if (idObject == NativeMethods.OBJID_HSCROLL || idObject == NativeMethods.OBJID_VSCROLL) { idObject = NativeMethods.OBJID_WINDOW; } el.DispatchEvents(eventId, idProp, idObject, idChild); } return; } if (idProp == ValuePattern.ValueProperty && eventId == NativeMethods.EVENT_OBJECT_VALUECHANGE) { NonClientItem item = idObject == NativeMethods.OBJID_HSCROLL ? NonClientItem.HScrollBar : NonClientItem.VScrollBar; WindowsScrollBar scrollBar = new WindowsScrollBar(hwnd, el, (int)item, idObject == NativeMethods.OBJID_HSCROLL ? NativeMethods.SB_HORZ : NativeMethods.SB_VERT); scrollBar.DispatchEvents(0, ValuePattern.ValueProperty, NativeMethods.OBJID_CLIENT, 0); return; } if (Misc.GetClassName(hwnd) == "ComboLBox") { el = (ProxyFragment)WindowsListBox.Create(hwnd, 0); } if (el != null) { el.DispatchEvents(eventId, idProp, idObject, idChild); } }