我试图从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获取元素文本?
该示例向您展示了如何获取文本属性,即有关UI中文本显示的信息,而不是实际显示的文本。获取一般应用程序的所有实际显示文本比首次出现更困难。
由于有多种方式获取文本并且应用程序和控件存在不一致的支持,因此很难实现。有两种使用方式,ValuePattern
和TextPattern
。按照惯例,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自动化控件类型(例如包含文本的“编辑”,“文本”和“文档”)上筛选和调用此方法。
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;
}