Doggie系列文章介绍1(底层所用的UI Aumation技术)

程序底层基于的是微软.net Framework 3.0所出的UI Automation. 关于他完整的介绍当然是看msdn了http://msdn.microsoft.com/en-us/library/ms747327.aspx。不过我会罗列我认为有用的信息。

1. 使用很简单,

第一步:在VS项目->添加引用->选择UIAutomationClient, UIAutomationTypes, UIAutomationProvider。

第二步:在项目cs文件中引用其namespace ( using System.Windows.Automation;)

第三步:就开始在代码中用吧,包括AutomationElement,PropertyCondition 等

2. 其拥有的类的简介

2.1 简介

2.1.1 UIAutomation认为每一个控件都是一个AutomationElement. 只是不同的控件有这不同的属性值如name, text等。

2.1.2 桌面被认为是根节点,固定的用AutomationElement.RootElement可以得到桌面

2.1.3 从桌面开始到其下每个程序,程序下的控件,控件包括的子控件。这些AutomationElement一级一级的扩展,他们有兄弟姐妹,父母子女。形成一个由桌面为尖顶的树。

2.1.4 既然AutomationElement之间有着一定的关系,自然而然的我们可以通过一定的条件把想要的Element找出来。一般是通过一个或多个PropertyCondition查找到想要的Element

2.1.5 如果这个AutomationElement及其子孙对象在程序中多处都会需要时,你可以利用cacheRequest将他们放到cache中,来提高他们的访问速度。

2.2 AutomationElement,可以认为他是UIAutomation的精元。假设已经new了一个对象AutomationElement ae =null;

2.2.1 非常有用的属性是Current,你可以查看他的name,IsEnabled等信息. 如ae.Current.Name,ae.Current.AutomationId.

这里需要解释一下name一般是c#控件的text属性值,automationId一般是c#控件的name属性值。如果使用了非标准控件的话需要注意有时候UIAutomation查不出automationId是什么所以为空或者为动态的数字,这时候需要处理依靠别的属性来定位

2.2.2 经常用到的方法有三个:FindAll,FindFirst,TryGetCurrentPattern.。

FindAll和FindFirst都需要两个两个参数,一个是查找范围TreeScope,一个是查找条件Condition。两者不同顾名思义第一个是返回所有满足条件的collection,第二个是返回符合条件的第一个AutomationElement.

2.2.3 使用实例,以下方法可以遍历桌面的程序界面对象。

string name = string.Empty;

foreach (AutomationElement ae in AutomationElement.RootElement.FindAll(TreeScope.Children, Condition.TrueCondition))

{

name +=ae.Current.Name+"\r\n";

}

2.3 枚举类型TreeScope。常用的是Children(所有子), Descendants(所有子孙)

2.4 条件Condition,

2.4.1 简单的有直接true (Condition.TrueCondition)和false (Condition.FalseCondition).

2.4.2复杂点的为PropertyCondition,就是设置属性值条件,

如PropertyCondition pc= new PropertyCondition(AutomationElement.NameProperty, value);

2.4.3 各种条件的交集就是符合所有条件都可以, 如AndCondition pcTarget = null;

pcTarget = new AndCondition(

new PropertyCondition(AutomationElement.AutomationIdProperty, nodeAutomationId.InnerText),

new PropertyCondition(AutomationElement.NameProperty, nodeName.InnerText),

new PropertyCondition(AutomationElement.HelpTextProperty, nodeHelpText.InnerText),

new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.LookupById(int.Parse(nodeControlType.InnerText))));

2.4.4 各种条件的并集就是符合任一条件就可以,如OrCondition pcTarget = null;

pcTarget = newOrCondition(

new PropertyCondition(AutomationElement.AutomationIdProperty, nodeAutomationId.InnerText),

new PropertyCondition(AutomationElement.NameProperty, nodeName.InnerText),

new PropertyCondition(AutomationElement.HelpTextProperty, nodeHelpText.InnerText),

new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.LookupById(int.Parse(nodeControlType.InnerText))));

2.5 Pattern,可以理解是对于控件的操作。比如button会有InvokePattern,对应的就是click。CheckBox会有TogglePattern,对应的是check操作。需要注意的是在xp上在模态窗口上invoke操作会被阻塞,所以这时候的操作需要选择用api模拟鼠标点击。win7上没有这个问题。实例

InvokePattern ipItem = null;

object temp;

if (ae.TryGetCurrentPattern(InvokePattern.Pattern, out temp))

{

ipItem = temp as InvokePattern;

try

{

ipItem.Invoke();

}

catch (Exception ex)

{

Console.WriteLine("Inovke引发exception:" + ex.Message);

return ClickByMouse(ae);

}

}

Pattern一般对应是操作,但是对于控件中用户的输入值有些控件并不是显示在name属性上,而是有专门的TextPattern或者ValuePattern。这个需要自己在UISpy上看看到底是什么pattern。

类的理解不复杂,直接上实例:

object objTemp;

if (ae.TryGetCurrentPattern(ValuePattern.Pattern, out objTemp))

{

ValuePattern vp = (ValuePattern)objTemp;

return vp.Current.Value;

}

2.6 CacheRequest,将某个对象及其子或子孙放到cache中提高速度。如果有个对象需要经常使用查找子孙对象时可是使用。

使用注意事项:放到cache可以提速但是cache容量有限所以存放时存放太多的对象,如果子孙有上百个时,不建议使用。实例:

CacheRequestcr = new CacheRequest();

cr.TreeFilter = Automation.RawViewCondition;

cr.TreeScope = TreeScope.Subtree;

AutomationElement aeGrandPa;

aeGrandPa = this._element.GetFirstElement(dwGrandPaId);

using (cr.Activate())

{

aeParent = this._element.GetFirstElement(aeGrandPa, range, type, conditionValue);

}

GetFirstElement为自己写的一个封装了FindFirst的方法

3. 辅助工具介绍

微软发布了一个类似Spy++的工具叫做UISpy。工具使用就不介绍了。

你可能感兴趣的:(UI,windows,cache,XP,Microsoft)