我正在尝试在编码的 UI 测试中选择一个树项,但我不知道整个层次结构。
例子:
- mssql 连接
- 表
- 未知
- 名
有没有办法在不指定整个路径的情况下搜索此 FirstName 树项并指定它的深度如此之多?
看起来任何搜索配置属性都不会执行此操作。
我正在尝试在编码的 UI 测试中选择一个树项,但我不知道整个层次结构。
例子:
- mssql 连接
- 表
- 未知
- 名
有没有办法在不指定整个路径的情况下搜索此 FirstName 树项并指定它的深度如此之多?
看起来任何搜索配置属性都不会执行此操作。
如果 FirstName 在树中是唯一的,那么您可以使用 PInvoke,并且您不需要指定深度:
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
var result = new List<IntPtr>();
var listHandle = GCHandle.Alloc(result);
try
{
var childProc = new User32.EnumWindowsProc(EnumWindow);
User32.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
var gch = GCHandle.FromIntPtr(pointer);
var list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// Modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowsProc callback, IntPtr i);
// sample usage:
public void findWindowUser32()
{
foreach (IntPtr child in GetChildWindows(User32.FindWindow(null, "Untitled - Notepad")))
{
StringBuilder sb = new StringBuilder(100);
User32.GetClassName(child, sb, sb.Capacity);
if (sb.ToString() == "Edit")
{
uint wparam = 0 << 29 | 0;
User32.PostMessage(child, WindowsConstants.WM_KEYDOWN, (IntPtr)Keys.H, (IntPtr)wparam);
}
}
}
当您的控件映射到 UI 映射中时,可能使用了完整的层次结构,例如
mssql 连接 -Tables --Unknown1 ---FirstName
导致 4 个映射控件。
您可以手动编辑 uimap .xml 文件,小心删除 -Unknown1 元素,并确保关闭 MatchExactHierarchy。这样搜索最初会失败,继续使用启发式方法在树中查找比直接子级更深的元素,并且应该找到您的控件。
public static UITestControl GetTreeItem(UITestControl TreeControl, string ItemName, bool ContainsTrue = true)
{
AutomationElement tree = AutomationElement.FromHandle(TreeControl.WindowHandle);
System.Windows.Automation.ControlType controlType = tree.Current.ControlType;
//Get collection of tree nodes.
AutomationElementCollection treeNodeCollection = null;
treeNodeCollection = tree.FindAll(TreeScope.Descendants,
new System.Windows.Automation.PropertyCondition(AutomationElement.ControlTypeProperty,
System.Windows.Automation.ControlType.TreeItem));
UITestControl ReqTreeItem = new UITestControl();
foreach (AutomationElement item in treeNodeCollection)
{
if ((item.Current.Name == ItemName) && (!ContainsTrue))
{
ReqTreeItem = UITestControlFactory.FromNativeElement(item, "UIA");
break;
}
if ((item.Current.Name.Contains(ItemName)) && (ContainsTrue))
{
ReqTreeItem = UITestControlFactory.FromNativeElement(item, "UIA");
break;
}
}
return ReqTreeItem;
}