Windows UI 自动化无法识别按钮控件

Windows UI Automation doesn't recognize button controls

我在尝试通过 Windows UI Automation 识别 通知区域 [ 中的按钮控件时遇到问题=33=] window (类名: ToolbarWindow32):

我通过部署在 Windows SDK 中的 Windows UI 自动化 工具进行了验证那些 "icons" 是 ControlType.Button 类型的控件,但是当我尝试 运行 下面的代码时,我得到一个空引用异常,因为我使用的搜索条件没有得到任何控制。

我做错了什么,或者我在 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.

有什么解决办法吗?

I verified via the Windows UI Automation tools deployed in the Windows SDK that those "icons" are controls of type ControlType.Button

你是正确的有点。从技术上讲,它们 不在 ToolbarWindow32 中,而是 Shell_TrayWnd。我检查了该区域并发现,这些按钮实际上在 ToolBar 中,因此您需要寻找 ControlType.ToolBar。接下来,您需要 FindAll 这将 return 所有满足 PropertyCondition...

的 AutomationElements

注意:第一个循环是获取User Promoted Notification Area。下一个有趣的循环是获取 运行 应用程序按钮...(代码在 WIN7、WIN8 和 WIN10 上运行)

在我下面的例子中,我追求 Shell_TrayWnd 这将得到我们需要的东西。然后我找到 ToolBar 我们想要的东西,然后遍历 FindAll ControlTypes of 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

如果您有任何问题,请告诉我。下图(出于安全原因我注释掉了一些内容)