Windows UI Automation не распознает элементы управления кнопками

У меня возникают проблемы с попыткой идентифицировать с помощью Windows UI Automation кнопки, которые находятся внутри окна области уведомлений (имя класса: ToolbarWindow32):

введите описание изображения здесь

Я проверил с помощью инструментов автоматизации Windows UI, развернутых в SDK Windows, что эти "значки" являются элементами управления типа ControlType.Button, однако, когда я пытаюсь запустить код ниже, я получаю исключение с использованием NULL, потому что условие поиска я использование не получает никакого контроля.

Я делаю что-то неправильно, или, может быть, я нашел какое-то ограничение в Windows UI Automation?

Это код, я смешал его с вызовами WinAPI, чтобы облегчить задачу для вспомогательных пользователей, которые, возможно, предпочитают использовать эту методологию.

Dim tskBarClassName As String = "Shell_TrayWnd"
Dim tskBarHwnd As IntPtr = NativeMethods.FindWindow(tskBarClassName, Nothing)

Dim systrayBarClassName As String = "TrayNotifyWnd"
Dim systrayBarHwnd As IntPtr = NativeMethods.FindWindowEx(tskBarHwnd, IntPtr.Zero, systrayBarClassName, Nothing)

Dim ntfyBarClassName As String = "ToolbarWindow32"
Dim ntfyBarHwnd As IntPtr = NativeMethods.FindWindowEx(systrayBarHwnd, IntPtr.Zero, ntfyBarClassName, Nothing)

Dim window As AutomationElement = AutomationElement.FromHandle(ntfyBarHwnd)
Dim condition As New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button)
Dim button As AutomationElement = window.FindFirst(TreeScope.Descendants, condition)

MsgBox(button.Current.Name) ' Here throws the null-reference exception.

Любое решение для этого?

Ответ 1

Я проверил с помощью средств автоматизации Windows UI, развернутых в SDK Windows, что эти "значки" являются элементами управления типа ControlType.Button

Вы правы несколько. Технически они не находятся в ToolbarWindow32, а скорее в Shell_TrayWnd. Я проверил область и выяснил, что эти кнопки на самом деле находятся в ToolBar, поэтому вам нужно искать ControlType.ToolBar. Затем вам нужно FindAll, которое вернет все AutomationElements, которые удовлетворяют PropertyCondition...

Примечание. Первый цикл - это получить зону расширенного пользовательского уведомления. Следующий цикл для развлечения - это кнопки Running Application... (КОД РАБОТАЕТ НА WIN7, WIN8 и WIN10)

Здесь, в моем примере ниже, я иду за Shell_TrayWnd, который доставит нам то, что нам нужно. Затем я просматриваю и обнаруживаю, что ToolBar мы после, затем прокручиваем и FindAll ControlTypes Button...

Dim arrText As New List(Of String)
        Dim tskBarClassName As String = "Shell_TrayWnd"
        Dim tskBarHwnd As IntPtr = FindWindow(tskBarClassName, Nothing)
        Dim window As AutomationElement = AutomationElement.FromHandle(tskBarHwnd)
        Dim condition As New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar)
        Dim elementCollection As AutomationElementCollection = window.FindAll(TreeScope.Descendants, condition)

        'for fun get all we can...
        For Each aE As AutomationElement In elementCollection
            If aE.Current.Name.Equals("User Promoted Notification Area") Then
                For Each ui As AutomationElement In aE.FindAll(TreeScope.Descendants, New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button))
                    arrText.Add("Notification Area - " & Replace(ui.Current.HelpText, Chr(10), " "c)) 'removed line break as when shown it would show some on a new line in messagebox
                Next
            ElseIf aE.Current.Name.Equals("Running applications") Then
                For Each ui As AutomationElement In aE.FindAll(TreeScope.Descendants, New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button))
                    arrText.Add("Toolbar Area - " & Replace(ui.Current.Name, Chr(10), " "c)) 'removed line break as when shown it would show some on a new line in messagebox
                Next
            End If

        Next

If arrText.Count > 0 Then
            MessageBox.Show(String.Join(Environment.NewLine, arrText.ToArray))
        End If

Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать. Изображение ниже (некоторые вещи, которые я прокомментировал по соображениям безопасности)

введите описание изображения здесь