如何从 UIAutomation 获取 hidden/private UI 元素,我可以在 Spy++ 中看到它但无法在代码中获取它,只有它是 parents 和兄弟姐妹

How to get hidden/private UI element from UIAutomation, I can see it in Spy++ but can't get to it in code, only it's parents and siblings

我正在尝试使用 System.Windows.Automation 访问 VLC 媒体播放器中的 UI 元素(特别是 left-most 角落中显示视频文件名的状态框目前正在播放)。我可以获得 parent 元素和一个同级元素,但是在 Spy++ 中,所有旁边有一个灰色图标的元素我无法在代码中访问...我假设灰色图标意味着它们是私有的或隐藏的或类似的东西。这是一张显示我的意思的图片:

请注意,我使用句柄 0x30826 引用了 parent,我从中执行了 FindAll()*,最后只有一个结果,即对 child 的引用句柄为 0x30858。您可以在 Spy++ 中看到 0x30826 有 5 个 children,但其中只有一个,我在执行 FindAll 时得到的那个,有一个全黑的图标,其他的有一个灰色的图标,我无法访问他们。另请注意,我想要的是 0x20908,它有一个灰色图标...

我怎样才能在代码中做到这一点?

*这是我用来尝试获取 0x30826 的所有 children 的代码:

    Dim aeDesktop As AutomationElement
    Dim aeVLC As AutomationElement
    Dim c As AutomationElementCollection
    Dim cd As New AndCondition(New PropertyCondition(AutomationElement.IsEnabledProperty, True), New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.StatusBar))

    aeVLC = aeDesktop.FindFirst(TreeScope.Children, New PropertyCondition(AutomationElement.NameProperty, "got s01e01.avi - VLC media player"))

    c = aeVLC.FindAll(TreeScope.Children, cd)

    c = c(0).FindAll(TreeScope.Children, Condition.TrueCondition)

第一个 FindAll() 只给我 0x30826,这很好,因为这就是我想要的,但是第二个 FindAll 没有指定条件,当我可以看到它时只给出 0x30858 加上 Spy++ 中的其他 4 个,包括我想要的。

您使用 Spy++ 而不是 Inspect Program 确实妨碍了您的工作。使用 Inspect,您可以很容易地看到目标元素是 text 元素的父元素 status bar 元素的父元素 window元素.

使用该信息,获取对目标 text 元素的引用非常简单。首先获取主要 window,然后是其状态栏,最后是状态栏的第一个文本元素。

' find the VLC process 
Dim targets As Process() = Process.GetProcessesByName("vlc")

If targets.Length > 0 Then

    ' assume its the 1st process 
    Dim vlcMainWindowHandle As IntPtr = targets(0).MainWindowHandle

    ' release all processes obtained
    For Each p As Process In targets
        p.Dispose()
    Next

    ' use vlcMainWindowHandle to get application window element
    Dim vlcMain As AutomationElement = AutomationElement.FromHandle(vlcMainWindowHandle)

    ' get the statusbar
    Dim getStatusBarCondition As Condition = New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.StatusBar)
    Dim statusBar As AutomationElement = vlcMain.FindFirst(TreeScope.Children, getStatusBarCondition)

    ' get the 1st textbox in the statusbar
    Dim getTextBoxCondition As Condition = New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text)
    Dim targetTextBox As AutomationElement = statusBar.FindFirst(TreeScope.Children, getTextBoxCondition)

    ' normally you use either a TextPattern.Pattern or ValuePattern.Pattern
    ' to obtain the text, but this textbox exposes neither and it uses the
    ' the Name property for the text.

    Dim textYouWant As String = targetTextBox.Current.Name

End If