无法使用 FindFirst 方法 (VBA) 找到 UIA 元素

问题描述 投票:0回答:1

我有一个应用程序,当它们通过

GetFocusedElement
方法获得 VBA UIAutomation 焦点时,我可以找到它的文本框,这应该表明它们可以被 UIAutomation 检测到,但我无法使用
FindFirst
FindAll
找到它们方法,如以下代码所示:

Public Wnd As IUIAutomationElement
Public Element As IUIAutomationElement
Public H_wnd As Long, PropValue(30003 To 30005)
Declare PtrSafe Function GetForegroundWindow Lib "user32" () As Long

Sub GetFocused()
  Tasks(MyApp).Activate
  H_wnd = GetForegroundWindow
  Set Element = UIauto.GetFocusedElement
  For i = 30003 To 30005 'ControlType, ?, Name
    PropValue(i) = Element.GetCurrentPropertyValue(i)
    'works good
    Debug.Print PropValue(i)
  Next
End Sub

Sub FindElement()
  Set Wnd = UIauto.ElementFromHandle(ByVal H_wnd)
  For i = 30003 To 30005
    'searching with the previously saved property values
    Debug.Print Wnd.FindFirst(TreeScope_Descendants, _
      UIauto.CreatePropertyCondition(i, PropValue(i))) Is Nothing
    'prints True to all
  Next
End Sub

第一个 Sub 成功找到焦点元素,并将其属性打印到直接窗格中。但第二个 Sub 没有发现任何内容,并对所有查询打印

True
。如果我将
TreeScope_Descendants
替换为
TreeScope
的任何其他值,这不会改变。

那么是否有可能在不聚焦的情况下找到这些元素?我尝试通过它们的名称或属性来控制它们,而不是通过获得聚焦控件,因为当我使用此代码时它们将不会聚焦。

vba ms-word ui-automation
1个回答
0
投票

事实证明该应用程序有多个实例,并且控件是窗口的后代,该窗口大多数时候不是控件所在窗口的子窗口(即,当它们处于焦点时,

GetForegroundWindow
返回) ),如 Winspector 的屏幕截图所示(类似于 Spy++)。

作为控件的祖父母的窗口没有名称,并且它的类名不是唯一的,正如您从上面的屏幕截图中看到的那样。所以我不得不使用

GetWindow
方法来循环遍历所有窗口。

更复杂的是,该窗口有时是前景窗口的子窗口,如第二个屏幕截图所示。

现在,如果我从父窗口搜索,FindFirst 找不到任何内容,因此我需要通过 FindWindowEx 获取子窗口,然后才能使用

FindFirst
方法。

以下代码完成了这项工作:

Declare PtrSafe Function FindWindowA Lib "user32" _
   (ByVal Class As String, ByVal WindowName As String) As Long
Declare PtrSafe Function FindWindowW Lib "user32" _
   (ByVal Class As LongPtr, ByVal WindowName As LongPtr) As Long
Declare PtrSafe Function GetWindow Lib "user32.dll"  _
    (ByVal hwnd As Long, ByVal wFlag As Long) As Long
Declare PtrSafe Function FindWindowExA Lib "user32" _
   (ByVal ParentHWnd As Long, ByVal symbol As Long, _
    ByVal Class As String, ByVal WindowName As String) As Long
Public UIAuto As New CUIAutomation
Public Wnd As IUIAutomationElement
Public MyControl As IUIAutomationElement
Public H_wnd As Long

Sub Find_Control()
  If Tasks.Exists(AppName) = False Then Exit Sub
  H_wnd = FindWindowA("Chrome_WidgetWin_0", "")

  Do
    If FindWindowExA(H_wnd, x&, "Chrome_RenderWidgetHostHWND", _
      "Chrome Legacy Window") > 0 Then Exit Do
    H_wnd = GetWindow(H_wnd, 2)
    If H_wnd = 0 Then
      'FindWindow with unicode characters
      H_wnd = FindWindowW(StrPtr("Chrome_WidgetWin_0"), StrPtr(AppName))
      If H_wnd = 0 Then Stop 'will replace with error handler
    End If
  Loop

  Set Wnd = UIAuto.ElementFromHandle(ByVal FindWindowExA(H_wnd, x&, _
    "Chrome_RenderWidgetHostHWND", "Chrome Legacy Window"))
  Set MyControl = Wnd.FindFirst(TreeScope_Descendants, _
    UIAuto.CreatePropertyCondition(UIA_NamePropertyId, CtrlName))
  If MyControl Is Nothing Then Stop 'will replace with error handler
End Sub
© www.soinside.com 2019 - 2024. All rights reserved.