C # System.Windows.Automation получить текст элемента

Я пытаюсь получить текст / метки из элементов управления приложения с помощью автоматизации на C #.

Пока я могу получить дерево приложения 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%28v=vs.110%29.aspx, но он может получать только текстовые атрибуты, такие как имя шрифта, его вес и т. д.

Может ли кто-нибудь указать мне правильную процедуру получения текста элемента с помощью автоматизации?


person Cockootec    schedule 24.05.2014    source источник


Ответы (2)


В этом примере показано, как получить текстовые атрибуты, то есть информацию об отображении текста в пользовательском интерфейсе, а не фактический отображаемый текст. Получить весь фактически отображаемый текст для общего приложения сложнее, чем он может появиться сначала.

Это усложняется тем фактом, что есть несколько способов получить текст, а поддержка приложениями и элементами управления непоследовательна. Есть два шаблона, которые могут быть полезны: ValuePattern и TextPattern. По соглашению свойство 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;
        }
    }
}

Это позволяет получить текст из простых элементов управления, таких как метки, текстовые поля (как ванильное текстовое поле, так и расширенное текстовое поле) и кнопки. Элементы управления, такие как списки и поля со списком (особенно в WPF), могут быть хитрыми, потому что их элементы могут быть виртуализированы, поэтому они могут не существовать в дереве автоматизации, пока пользователь не взаимодействует с ними. Вы можете фильтровать и вызывать этот метод только для определенных типов элементов управления UI Automation, таких как Edit, Text и Document, которые, как вы знаете, содержат текст.

person Mike Zboray    schedule 25.05.2014
comment
Спасибо, это работает. Просто в 3-й строке у вас есть ошибка в двойных статических ключевых словах, я предполагаю, что вторая должна быть строкой. В 6-й строке отсутствует закрывающая скобка в конце строки. - person Cockootec; 25.05.2014

Ответ Майка Зборая работает нормально. Если у вас есть доступ к сопоставлению с образцом, вот тот же (сжатый) код:

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;
}
person Dinosaure    schedule 26.02.2019