UI 自动化 - 从 SysListView32(或任何列表视图)检索数据
UI Automation - Retrieving data from a SysListView32 (or any Listview)
我正在尝试使用以下代码从 SysListView32 对象中检索数据,但返回的是空字符串。
根据 Inspector 的打印,我需要检索的元素是那些以红色突出显示的元素,以及包含在其他 ControlType.ListItem
元素中的其他元素。
有人可以检查一下我的代码有什么问题吗?
Msgbox("Position the mouse cursor on the screen and press ENTER.")
Dim pt As POINTAPI
GetCursorPos(pt)
Dim hwnd As IntPtr = WindowFromPoint(pt)
Dim hwnd As IntPtr = 67202
Dim el As AutomationElement = AutomationElement.FromHandle(hwnd)
Dim walker As TreeWalker = TreeWalker.ContentViewWalker
Dim i As Integer = 0
Dim child As AutomationElement = walker.GetFirstChild(el)
While child IsNot Nothing
'
Dim k As Integer = 0
Dim child2 As AutomationElement = walker.GetFirstChild(child)
While child2 IsNot Nothing
Console.WriteLine(child2.Current.ToString)
child2 = walker.GetNextSibling(child2)
End While
child = walker.GetNextSibling(child)
End While
如果 SysListView32 的当前视图状态不是 LV_VIEW_DETAILS
, so we should temporarily (if the current view state is different), use the MultipleViewPattern of its AutomationElement to verify the view state and change it if necessary using the MultipleViewPattern.SetCurrentView() 方法,则它可能无法提供请求的信息。
SetCurrentView()
方法使用与 Win32 控件相同的值。
然后使用 AutomationElement FindAll() method of the to find all child elements of type ControlType.DataItem or ControlType.ListItem
(using an OrCondition)。
对于它们中的每一个,获取类型为 ControlType.Edit
和 ControlType.Text
的所有 child 项(使用另一个 OrCondition
)。
使用项目的 GridItemPattern, to access the Item's Row 属性 检索列表中每个项目的位置。
最后,如果必须更改它,我们将恢复以前的视图状态。
例子中的代码,填充了一个Dictionary(Of Integer, ListViewItem)
(sysListViewItems
),包含了所有的Items从 SysListView32 中提取。
- Integer Key表示一个Item在原始ListView中的位置
- ListViewItem 是一个 .Net object 从每个项目中提取的值数组(作为字符串)生成的。
如果不需要ListViewItem objects,可以只存储List(Of String)
,用itemsText
表示object,而不是在此处创建 ListViewItem:
sysListViewItems.Add(gridPattern.Current.Row, New ListViewItem(itemsText.ToArray())).
SysListView32 的句柄也可以通过 ClassName
.
枚举其顶级 Window 的 children 获得
AutomationElement.RootElement 提供当前桌面元素:
Dim parentWindow = AutomationElement.RootElement.FindFirst(
TreeScope.Children, New PropertyCondition(AutomationElement.NameProperty, "[Window Caption]"))
Dim sysListView32 = parentWindow.FindAll(
TreeScope.Subtree, New PropertyCondition(AutomationElement.ClassNameProperty, "SysListView32"))
如果发现多个SysListView32,按Header内容过滤,直接parentControlType
或ClassName
或任何其他允许挑出的内容。
UI 自动化需要引用 UIAutomationClient
和 UIAutomationTypes
程序集。
Imports System.Windows.Automation
Dim sysListViewHandle = [GetSysListView32Handle()]
Dim sysListViewElement = AutomationElement.FromHandle(sysListViewHandle)
If sysListViewElement Is Nothing Then Return
Dim sysListViewItems = New Dictionary(Of Integer, ListViewItem)()
Dim mulView As MultipleViewPattern = Nothing
Dim pattern As Object = Nothing
Dim currentView As Integer = -1
If sysListViewElement.TryGetCurrentPattern(MultipleViewPattern.Pattern, pattern) Then
mulView = DirectCast(pattern, MultipleViewPattern)
currentView = mulView.Current.CurrentView
If currentView <> ListViewWState.LV_VIEW_DETAILS Then
mulView.SetCurrentView(ListViewWState.LV_VIEW_DETAILS)
End If
End If
Dim childItemsCondition = New OrCondition(
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem),
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem))
Dim childItems = sysListViewElement.FindAll(TreeScope.Children, childItemsCondition)
If childItems.Count = 0 Then Return
Dim subItemsCondition = New OrCondition(
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text))
For Each item As AutomationElement In childItems
Dim itemsText = New List(Of String)()
Dim subItems = item.FindAll(TreeScope.Children, subItemsCondition)
For Each subItem As AutomationElement In subItems
itemsText.Add(subItem.Current.Name)
Next
Dim gridPattern = DirectCast(subItems(0).GetCurrentPattern(GridItemPattern.Pattern), GridItemPattern)
sysListViewItems.Add(gridPattern.Current.Row, New ListViewItem(itemsText.ToArray()))
Next
If mulView IsNot Nothing Then
mulView.SetCurrentView(currentView)
End If
Friend Enum ListViewWState
LV_VIEW_ICON = &H0
LV_VIEW_DETAILS = &H1
LV_VIEW_SMALLICON = &H2
LV_VIEW_LIST = &H3
LV_VIEW_TILE = &H4
End Enum
我正在尝试使用以下代码从 SysListView32 对象中检索数据,但返回的是空字符串。
根据 Inspector 的打印,我需要检索的元素是那些以红色突出显示的元素,以及包含在其他 ControlType.ListItem
元素中的其他元素。
有人可以检查一下我的代码有什么问题吗?
Msgbox("Position the mouse cursor on the screen and press ENTER.")
Dim pt As POINTAPI
GetCursorPos(pt)
Dim hwnd As IntPtr = WindowFromPoint(pt)
Dim hwnd As IntPtr = 67202
Dim el As AutomationElement = AutomationElement.FromHandle(hwnd)
Dim walker As TreeWalker = TreeWalker.ContentViewWalker
Dim i As Integer = 0
Dim child As AutomationElement = walker.GetFirstChild(el)
While child IsNot Nothing
'
Dim k As Integer = 0
Dim child2 As AutomationElement = walker.GetFirstChild(child)
While child2 IsNot Nothing
Console.WriteLine(child2.Current.ToString)
child2 = walker.GetNextSibling(child2)
End While
child = walker.GetNextSibling(child)
End While
如果 SysListView32 的当前视图状态不是 LV_VIEW_DETAILS
, so we should temporarily (if the current view state is different), use the MultipleViewPattern of its AutomationElement to verify the view state and change it if necessary using the MultipleViewPattern.SetCurrentView() 方法,则它可能无法提供请求的信息。
SetCurrentView()
方法使用与 Win32 控件相同的值。
然后使用 AutomationElement FindAll() method of the to find all child elements of type ControlType.DataItem or ControlType.ListItem
(using an OrCondition)。
对于它们中的每一个,获取类型为 ControlType.Edit
和 ControlType.Text
的所有 child 项(使用另一个 OrCondition
)。
使用项目的 GridItemPattern, to access the Item's Row 属性 检索列表中每个项目的位置。
最后,如果必须更改它,我们将恢复以前的视图状态。
例子中的代码,填充了一个Dictionary(Of Integer, ListViewItem)
(sysListViewItems
),包含了所有的Items从 SysListView32 中提取。
- Integer Key表示一个Item在原始ListView中的位置
- ListViewItem 是一个 .Net object 从每个项目中提取的值数组(作为字符串)生成的。
如果不需要ListViewItem objects,可以只存储List(Of String)
,用itemsText
表示object,而不是在此处创建 ListViewItem:
sysListViewItems.Add(gridPattern.Current.Row, New ListViewItem(itemsText.ToArray())).
SysListView32 的句柄也可以通过 ClassName
.
枚举其顶级 Window 的 children 获得
AutomationElement.RootElement 提供当前桌面元素:
Dim parentWindow = AutomationElement.RootElement.FindFirst(
TreeScope.Children, New PropertyCondition(AutomationElement.NameProperty, "[Window Caption]"))
Dim sysListView32 = parentWindow.FindAll(
TreeScope.Subtree, New PropertyCondition(AutomationElement.ClassNameProperty, "SysListView32"))
如果发现多个SysListView32,按Header内容过滤,直接parentControlType
或ClassName
或任何其他允许挑出的内容。
UI 自动化需要引用 UIAutomationClient
和 UIAutomationTypes
程序集。
Imports System.Windows.Automation
Dim sysListViewHandle = [GetSysListView32Handle()]
Dim sysListViewElement = AutomationElement.FromHandle(sysListViewHandle)
If sysListViewElement Is Nothing Then Return
Dim sysListViewItems = New Dictionary(Of Integer, ListViewItem)()
Dim mulView As MultipleViewPattern = Nothing
Dim pattern As Object = Nothing
Dim currentView As Integer = -1
If sysListViewElement.TryGetCurrentPattern(MultipleViewPattern.Pattern, pattern) Then
mulView = DirectCast(pattern, MultipleViewPattern)
currentView = mulView.Current.CurrentView
If currentView <> ListViewWState.LV_VIEW_DETAILS Then
mulView.SetCurrentView(ListViewWState.LV_VIEW_DETAILS)
End If
End If
Dim childItemsCondition = New OrCondition(
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem),
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem))
Dim childItems = sysListViewElement.FindAll(TreeScope.Children, childItemsCondition)
If childItems.Count = 0 Then Return
Dim subItemsCondition = New OrCondition(
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit),
New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text))
For Each item As AutomationElement In childItems
Dim itemsText = New List(Of String)()
Dim subItems = item.FindAll(TreeScope.Children, subItemsCondition)
For Each subItem As AutomationElement In subItems
itemsText.Add(subItem.Current.Name)
Next
Dim gridPattern = DirectCast(subItems(0).GetCurrentPattern(GridItemPattern.Pattern), GridItemPattern)
sysListViewItems.Add(gridPattern.Current.Row, New ListViewItem(itemsText.ToArray()))
Next
If mulView IsNot Nothing Then
mulView.SetCurrentView(currentView)
End If
Friend Enum ListViewWState
LV_VIEW_ICON = &H0
LV_VIEW_DETAILS = &H1
LV_VIEW_SMALLICON = &H2
LV_VIEW_LIST = &H3
LV_VIEW_TILE = &H4
End Enum