TestStack / White

DEPRECATED - no longer actively maintained
Other
1.02k stars 487 forks source link

teststack.white support .net framework 4.8 combobox/listbox items. #671

Closed denhaandrei closed 2 years ago

denhaandrei commented 3 years ago

Need update DescendantFinder to

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Automation;

namespace TestStack.White.AutomationElementSearch
{
    public class DescendantFinder : IDescendantFinder
    {
        private readonly AutomationElement automationElement;

        public DescendantFinder(AutomationElement automationElement)
        {
            if (automationElement == null) throw new ArgumentNullException("automationElement");
            this.automationElement = automationElement;
        }

        public virtual AutomationElement Descendant(AutomationSearchCondition automationSearchCondition)
        {
            return Descendant(automationSearchCondition.Condition);
        }

        public virtual AutomationElement Descendant(Condition condition)
        {
            return automationElement.FindFirst(TreeScope.Descendants, condition);
        }

        public virtual List<AutomationElement> Descendants(AutomationSearchCondition automationSearchCondition)
        {
            var collection = automationElement.FindAll(TreeScope.Descendants, automationSearchCondition.Condition);
            if(collection.Count == 0)
                collection = GetWinFormComboBoxListItems(automationElement);
            var enumerable = collection.Cast<AutomationElement>();
            return new List<AutomationElement>(enumerable);
        }

        private AutomationElementCollection GetWinFormComboBoxListItems(AutomationElement comboBox)
        {
            if (comboBox is null) return null;
            if (comboBox.Current.FrameworkId != "WinForm")
            {
                throw new ArgumentException("Not a WinForm Control");
            }

            var cboInfo = new COMBOBOXINFO();
            cboInfo.Init();

            if (GetComboBoxInfo((IntPtr)comboBox.Current.NativeWindowHandle, ref cboInfo))
            {
                var listElement = AutomationElement.FromHandle(cboInfo.hwndList);
                if (listElement != null)
                {
                    var items = listElement.FindAll(TreeScope.Children, Automation.RawViewCondition);
                    return items;
                }
            }
            return null;
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        internal static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern int SendMessage(IntPtr hWnd, uint uMsg, int wParam, int lParam);

        private const int LB_GETCUSEL = 0x0188;

        [StructLayout(LayoutKind.Sequential)]
        internal struct COMBOBOXINFO
        {
            public int cbSize;
            public Rectangle rcItem;
            public Rectangle rcButton;
            public int buttonState;
            public IntPtr hwndCombo;
            public IntPtr hwndEdit;
            public IntPtr hwndList;
            public void Init() => this.cbSize = Marshal.SizeOf<COMBOBOXINFO>();
        }

        internal static IntPtr GetComboBoxListInternal(IntPtr cboHandle)
        {
            var cbInfo = new COMBOBOXINFO();
            cbInfo.Init();
            GetComboBoxInfo(cboHandle, ref cbInfo);
            return cbInfo.hwndList;
        }
    }

}
denhaandrei commented 2 years ago

don`t want fix