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); } }
private bool IsInsideOfCombo() { IntPtr hwndParent = NativeMethodsSetLastError.GetAncestor(_hwnd, NativeMethods.GA_PARENT); if (hwndParent == IntPtr.Zero) { return false; } // Test for combo NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (WindowsComboBox.GetComboInfo(hwndParent, ref cbInfo) && cbInfo.hwndItem == _hwnd) { return true; } return false; }
// Combo-specific events static private void RaiseEvents (IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { // ------------------------------------------------------///////////////////////////////////// // // Depending of the type of Combobox we will get different WinEvents // // Simple: No events // // DropDown: OBJ_STATECHANGE: for the dropbutton button (idChild == 2) // NOTE: that OBJECT_STATECHANGE will only be generated when user uses button to show the list // if user uses the button to hide the list, event will not be generated // // DropDownList: OBJ_STATECHANGE (same as above) // : OBJECT_VALUECHANGE - when using the keyboard to navigate between list children // - no need to handle it here, ListBox proxy will take care of that // // ------------------------------------------------------////////////////////////////////////// ProxySimple el = null; if (idProp is AutomationProperty && idProp == ExpandCollapsePattern.ExpandCollapseStateProperty) { // expand/collapse events are handled in WindowsListBox with the ComboLBox hwnd. // so just return here so we don't fire extraneous events return; } switch (idObject) { case NativeMethods.OBJID_CLIENT : { if (eventId == NativeMethods.EventObjectStateChange && idChild == 2) { // event came for combobutton // We will be getting 2 OBJECT_STATECHANGED event // one with button state pressed and another normal // both indicate the same invoke event // hence second event is a duplicate of the first one and we need to filter it out NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (WindowsComboBox.GetComboInfo(hwnd, ref cbInfo) && Misc.IsBitSet(NativeMethods.STATE_SYSTEM_PRESSED, cbInfo.stateButton)) { // The event could be for both the button and the combo WindowsComboBox cb = (WindowsComboBox) Create (hwnd, 0); cb.DispatchEvents (eventId, idProp, idObject, idChild); el = cb.CreateComboButton (); el.DispatchEvents (eventId, idProp, idObject, idChild); return; } } el = (ProxySimple) Create (hwnd, 0); break; } } if (el != null) { el.DispatchEvents (eventId, idProp, idObject, idChild); } }
private static void RaiseEventsOnWindow(IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { AutomationProperty automationProperty = idProp as AutomationProperty; ProxySimple el = null; if ((eventId == NativeMethods.EventObjectShow || eventId == NativeMethods.EventObjectHide) && (automationProperty != null && automationProperty == ExpandCollapsePattern.ExpandCollapseStateProperty)) { if (Misc.IsBitSet(Misc.GetWindowStyle(hwnd), NativeMethods.LBS_COMBOBOX)) { // List portion of combo: We'll hit it in the case when user hovers over it NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (WindowsComboBox.GetComboInfo(hwnd, ref cbInfo) && (cbInfo.hwndCombo != IntPtr.Zero)) { WindowsComboBox cb = (WindowsComboBox)WindowsComboBox.Create(cbInfo.hwndCombo, 0); if (!cb.IsSimpleCombo()) { el = cb; } } } } if (el != null) { el.DispatchEvents(eventId, idProp, idObject, idChild); } }
// create combo button private ProxySimple CreateComboButton () { NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo) && cbInfo.stateButton != NativeMethods.STATE_SYSTEM_INVISIBLE) { return new WindowsComboButton (_hwnd, this, (int) ComboChildren.Button); } return null; }
// create list portion of combo box private ProxySimple CreateListBox() { NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo) && (IntPtr.Zero != cbInfo.hwndList)) { return new WindowsListBox(cbInfo.hwndList, this, (int)ComboChildren.List, true); } return null; }
// expand the list portion static internal void Expand (IntPtr hwnd) { IntPtr hwndFocused = Misc.GetFocusedWindow(); NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); GetComboInfo(hwnd, ref cbInfo); // if the combobox does not already have focus, set the focus. if (hwndFocused != hwnd && hwndFocused != cbInfo.hwndCombo && hwndFocused != cbInfo.hwndItem && hwndFocused != cbInfo.hwndList) { Misc.SetFocus(hwnd); } Misc.ProxySendMessage(hwnd, NativeMethods.CB_SHOWDROPDOWN, new IntPtr(1), IntPtr.Zero); }
// Sets the text of the edit part of the Combo void IValueProvider.SetValue (string str) { // Ensure that the window and all its parents are enabled. Misc.CheckEnabled(_hwnd); // piggy-back on win32editbox proxy NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo) && SafeNativeMethods.IsWindowVisible(cbInfo.hwndItem)) { WindowsEditBox editBox = new WindowsEditBox(cbInfo.hwndItem, null, -1); IValueProvider valueProvider = (IValueProvider) editBox.GetPatternProvider (ValuePattern.Pattern); // try to set user-provided text valueProvider.SetValue (str); // Let the parent know that the value has change, to allow the parent to do any processing it needs // to do on value change. IntPtr hwndParent = Misc.GetParent(_hwnd); if (hwndParent != IntPtr.Zero) { int id = Misc.GetWindowId(_hwnd); IntPtr wParam = new IntPtr(NativeMethods.Util.MAKELONG(id, NativeMethods.CBN_EDITUPDATE)); Misc.ProxySendMessage(hwndParent, NativeMethods.WM_COMMAND, wParam, _hwnd); } return; } throw new InvalidOperationException(SR.Get(SRID.OperationCannotBePerformed)); }
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); } } }
// Returns a Proxy element corresponding to the specified screen coordinates. internal override ProxySimple ElementProviderFromPoint (int x, int y) { NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (GetComboInfo(_hwnd, ref cbInfo)) { // check for button if (Misc.MapWindowPoints(_hwnd, IntPtr.Zero, ref cbInfo.rcButton, 2)) { if (Misc.PtInRect(ref cbInfo.rcButton, x, y)) { return new WindowsComboButton(_hwnd, this, (int)ComboChildren.Button); } } // check for list if (SafeNativeMethods.IsWindowVisible(cbInfo.hwndList)) { NativeMethods.Win32Rect rcList = NativeMethods.Win32Rect.Empty; if (Misc.GetWindowRect(cbInfo.hwndList, ref rcList) && Misc.PtInRect(ref rcList, x, y)) { ProxySimple el = CreateListBox(cbInfo.hwndList); return ((WindowsListBox) el).ElementProviderFromPoint (x, y); } } } return this; }