首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用UI自动化从ListView或类似控件中获取文本?

如何使用UI自动化从ListView或类似控件中获取文本?
EN

Stack Overflow用户
提问于 2020-10-16 11:17:47
回答 1查看 954关注 0票数 1

我试图从外部应用程序中抓取一个类似于控件的ListView。现在我正在使用System.Windows.Automation。使用AutoIt v3,我提取了以下有关要从其中刮取文本的精确控件的信息:

代码语言:javascript
运行
复制
>>>> Control <<<<
Class:  WindowsForms10.Window.8.app.0.34f5582_r6_ad1
Instance:   20
ClassnameNN:    WindowsForms10.Window.8.app.0.34f5582_r6_ad120
Name:   
Advanced (Class):   [CLASS:WindowsForms10.Window.8.app.0.34f5582_r6_ad1; INSTANCE:20]
ID: 1510520
Text:   
Position:   182, 164
Size:   1411, 639
ControlClick Coords:    300, 202
Style:  0x56010000
ExStyle:    0x00000000
Handle: 0x0000000000170C78

现在,我注意到了ID = 1510520,通过使用它,我将能够获得控制

代码语言:javascript
运行
复制
AutomationElement element = AutomationElement.FromHandle(1510520);

这个控件看起来像一个ListView或者类似于它,但是我不能用它做任何其他的事情。

现在我如何才能获得此控件的内容?

更新:

感谢Jimi的推荐,Windows10SDK中的inspect.exe工作得最好!我能够钻到DataGridView。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-16 16:01:15

我假设您可以找到包含从其中提取数据的DataGridView的窗口。GeDataGridViewDataTable()方法需要该窗口的句柄。

让我们分解一下这些方法:

要获得感兴趣窗口的AutomationElement (当其句柄已知时),我们只需使用window = AutomationElement.FromHandle([Window Handle])即可。

这里我使用的是AndCodition,因为您可能有ProcessID和窗口标题,所以您可以使用AutomationElement.ProcessIdPropertyAutomationElement.NameProperty作为条件,而不是使用AutomationElement.ControlTypePropertyAutomationElement.NativeWindowHandleProperty进行过滤。

如果找到该窗口,则解析TreeScope.SubTree作用域中的第一个子元素(该窗口中的所有UI元素)以找到表类型的第一个元素(ControlType.Table)。

当然,该窗口可能承载多个DataGridView:在本例中,我们可以使用FindAll()而不是FindFirst(),然后确定使用其他条件(列数、标题文本、单元格内容、位置、大小、父容器等)是什么。

当发现感兴趣的DataGridView时,我们可以提取其细胞的内容。

接下来是第二个方法,GetDataGridViewRowsCollection()

  • 第一个OrCondition过滤掉网格的DataGridView滚动条和其他子控件(定制可能包括一些)。
  • 之后,我们检查DGV是否有一个标头:如果有,第一个子行元素名是Top Row.然后,我们可以使用头文本来命名DataTable的列,这些列将存储提取的数据。否则,只需添加一些默认名称。
  • 然后,对于每个Row元素,我们枚举它的子元素,表示单元格。我添加了一个ControlType.Header,过滤器来排除行标头单元格(如果有的话)。
  • 然后迭代单元格的集合,使用GetCurrentPropertyValue()方法提取它们的值,将属性类型设置为ValuePattern.ValueProperty,将这些值添加到将提供param数组参数的列表中
代码语言:javascript
运行
复制
private DataTable GeDataGridViewDataTable(IntPtr windowHwnd)
{
    var condition = new AndCondition(
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window),
        new PropertyCondition(AutomationElement.NativeWindowHandleProperty, windowHwnd.ToInt32())
    );
    var window = AutomationElement.RootElement.FindFirst(TreeScope.Children, condition);
    if (window == null) return null;
    var dgv = window.FindFirst(TreeScope.Subtree, 
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Table));

    if (dgv == null) return null;
    var dt = GetDataGridViewRowsCollection(dgv);
    return dt;
}

private DataTable GetDataGridViewRowsCollection(AutomationElement dgv)
{
    var dt = new DataTable();

    // Skips ScrollBars and other child elements
    var condition = new OrCondition(
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom),
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Header)
    );

    var rows = dgv.FindAll(TreeScope.Children, condition).OfType<AutomationElement>().ToList();
    bool hasColumnHeader = (rows[0].Current.Name == "Top Row");

    // First element is the Header (if there's one)
    var dgvHeaderColumns = rows[0].FindAll(TreeScope.Children, Condition.TrueCondition);
        
    // Skip the Top/Left header
    for (int i = 1; i < dgvHeaderColumns.Count; i++) {
        dt.Columns.Add(hasColumnHeader ? dgvHeaderColumns[i].Current.Name : "Column"+i);
    }

    // Skips the Row Header, if any
    var notCondition = new NotCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Header));
    foreach (AutomationElement row in rows) {
        var cells = row.FindAll(TreeScope.Children, notCondition);
        var values = new List<object>();
        foreach (AutomationElement cell in cells) {
            values.Add(cell.GetCurrentPropertyValue(ValuePattern.ValueProperty));
        }
        dt.Rows.Add(values.ToArray());
    }
    return dt;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64388120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档