在C#中创建自定义UIAutomation属性的实现咨询
在C#中为UI Automation添加自定义属性的实现方案
好问题!在C#里实现UI Automation自定义属性不需要手动做托管到非托管的封送处理——.NET的UI Automation框架已经帮我们封装好了类型转换的细节,你只需要按照正确的步骤注册属性并处理请求即可。下面是具体的实现步骤:
1. 注册自定义UI Automation属性
首先你需要通过AutomationProperty.Register方法创建一个自定义属性,这个方法会自动帮你分配合法的属性ID(无需手动指定0x80000000及以上的数值),同时关联对应的类型。
比如我们注册几个不同类型的自定义属性示例:
// 注册字符串类型的自定义属性 public static readonly AutomationProperty CustomDocumentPathProperty = AutomationProperty.Register( "CustomDocumentPath", typeof(string), typeof(YourPaneProvider), // 你的提供者类类型 new AutomationPropertyMetadata( string.Empty, // 默认值 AutomationPropertyOptions.None)); // 注册布尔类型的自定义属性 public static readonly AutomationProperty IsDocumentModifiedProperty = AutomationProperty.Register( "IsDocumentModified", typeof(bool), typeof(YourPaneProvider), new AutomationPropertyMetadata( false, AutomationPropertyOptions.None)); // 注册整数类型的自定义属性 public static readonly AutomationProperty DocumentRevisionProperty = AutomationProperty.Register( "DocumentRevision", typeof(int), typeof(YourPaneProvider), new AutomationPropertyMetadata( 0, AutomationPropertyOptions.None));
这里的类型要和你提到的UIAutomationType一一对应:
bool→ UIAutomationType_Boolint→ UIAutomationType_Intstring→ UIAutomationType_Stringdouble→ UIAutomationType_DoubleSystem.Windows.Point→ UIAutomationType_PointAutomationElement→ UIAutomationType_Element
2. 在GetPropertyValue中处理自定义属性请求
接下来在你现有的GetPropertyValue方法中,添加对自定义属性ID的判断逻辑,返回对应的值即可:
public object GetPropertyValue(int propertyId) { // 先处理系统属性(保留你原有的代码) if (propertyId == AutomationElementIdentifiers.NameProperty.Id) { return View.Document.FullName; } else if (propertyId == AutomationElementIdentifiers.ControlTypeProperty.Id) { return ControlType.Pane.Id; } else if (propertyId == AutomationElementIdentifiers.IsContentElementProperty.Id) { return true; } else if (propertyId == AutomationElementIdentifiers.IsControlElementProperty.Id) { return true; } else if (propertyId == AutomationElementIdentifiers.IsKeyboardFocusableProperty.Id) { return false; } // 处理自定义属性 else if (propertyId == CustomDocumentPathProperty.Id) { return View.Document.FilePath; // 返回你的自定义字符串值 } else if (propertyId == IsDocumentModifiedProperty.Id) { return View.Document.IsModified; // 返回布尔值 } else if (propertyId == DocumentRevisionProperty.Id) { return View.Document.RevisionNumber; // 返回整数值 } else { // 不支持的属性返回null return null; } }
关键细节说明
- 为什么不需要手动封送?.NET的
IRawElementProviderFragment等接口是COM互操作的包装类,框架会自动将你返回的托管类型(如string、bool)转换为UIA需要的非托管类型(对应UIAutomationType_*),完全不需要你手动写封送代码。 - 自定义属性的可见性:注册后的自定义属性会被Ranorex、Test Complete等工具识别,你可以通过工具的属性查看器或者脚本获取这些属性值。
- 属性ID范围:如果你不想用
AutomationProperty.Register,也可以手动指定ID,但必须使用0x80000000到0xFFFFFFFF之间的数值(系统属性使用0x00000000到0x7FFFFFFF),不过推荐用Register方法,避免ID冲突。
内容的提问来源于stack exchange,提问作者ForgetfulChimp




