C#System.Windows.Automation获取元素文本

问题描述 投票:5回答:2

我试图从C#中的Automation实现应用程序控件的文本/标签。

到目前为止,我能够使用此函数获取AutomationElement应用程序树(例如记事本):

    private void WalkControlElements(AutomationElement rootElement, TreeNode treeNode)
    {
        AutomationElement elementNode = TreeWalker.ContentViewWalker.GetFirstChild(rootElement);;

        while (elementNode != null)
        {
            TreeNode childTreeNode = treeNode.Nodes.Add(elementNode.Current.ControlType.LocalizedControlType);

            // here I want to get text from 'elementNode'

            WalkControlElements(elementNode, childTreeNode);
            elementNode = TreeWalker.ControlViewWalker.GetNextSibling(elementNode);
        }
    }

我试图遵循这篇文章http://msdn.microsoft.com/en-us/library/ms788751(v=vs.110).aspx但它只能获得文本属性作为字体名称,字体粗细等。

有人能指出正确的程序如何使用Automation获取元素文本?

c# ui-automation
2个回答
9
投票

该示例向您展示了如何获取文本属性,即有关UI中文本显示的信息,而不是实际显示的文本。获取一般应用程序的所有实际显示文本比首次出现更困难。

由于有多种方式获取文本并且应用程序和控件存在不一致的支持,因此很难实现。有两种使用方式,ValuePatternTextPattern。按照惯例,Name属性包含向用户显示的文本,但是对此的遵守是不一致的。下面是我在UI自动化中用于测试的辅助方法。它基本上通过这些模式检查控件的支持并回退到Name。

public static class AutomationExtensions
{
    public static string GetText(this AutomationElement element)
    {
        object patternObj;
        if (element.TryGetCurrentPattern(ValuePattern.Pattern, out patternObj))
        {
            var valuePattern = (ValuePattern)patternObj;
            return valuePattern.Current.Value;
        }
        else if (element.TryGetCurrentPattern(TextPattern.Pattern, out patternObj))
        {
            var textPattern = (TextPattern)patternObj;
            return textPattern.DocumentRange.GetText(-1).TrimEnd('\r'); // often there is an extra '\r' hanging off the end.
        }
        else
        {
            return element.Current.Name;
        }
    }
}

这需要从简单的控件中获取文本,例如标签,文本框(包括vanilla textbox和richtextbox)和按钮。像列表框和组合框(尤其是WPF中的)这样的控件可以很简单,因为它们的项可以虚拟化,因此在用户与它们交互之前它们可能不存在于自动化树中。您可能希望仅在某些UI自动化控件类型(例如包含文本的“编辑”,“文本”和“文档”)上筛选和调用此方法。


0
投票

Mike Zboray的回答很好。如果您有权访问模式匹配,这里是相同的(精简的)代码:

public static class AutomationExtensions
{
    public static string GetText(this AutomationElement element)
    => element.TryGetCurrentPattern(ValuePattern.Pattern, out object patternValue) ? ((ValuePattern)patternValue).Current.Value
        : element.TryGetCurrentPattern(TextPattern.Pattern, out object patternText) ? ((TextPattern)patternText).DocumentRange.GetText(-1).TrimEnd('\r') // often there is an extra '\r' hanging off the end.
        : element.Current.Name;
}
© www.soinside.com 2019 - 2024. All rights reserved.