我有一个应用程序,当它们通过
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
的任何其他值,这不会改变。
那么是否有可能在不聚焦的情况下找到这些元素?我尝试通过它们的名称或属性来控制它们,而不是通过获得聚焦控件,因为当我使用此代码时它们将不会聚焦。
事实证明该应用程序有多个实例,并且控件是窗口的后代,该窗口大多数时候不是控件所在窗口的子窗口(即,当它们处于焦点时,
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