我在自动化UI方面遇到了问题。 我有一个有效的代码,但很难调试 - 所以我创建了一个应该更舒服的代码,但在一种情况下,它将无法工作 - 这种情况下是一个自定义控件。
我无法弄清楚为什么一个代码可以工作,而另一个代码则不行! 我尝试了很多方法并在网上搜索(许多类似的东西,但对我来说还不够好)
这是有效的代码:
class ElementUtils
{
public ElementUtils()
{
}
public AutomationElement FindObjectFullPath(string parent, string childElements, string controlType)
{
string[] strElements = null;
if (!string.IsNullOrEmpty(childElements))
{
childElements = childElements.Trim();
strElements = childElements.Split(new string[] { "[", "]" }, StringSplitOptions.RemoveEmptyEntries);
if (string.IsNullOrEmpty(parent) && !(childElements.StartsWith("[") && childElements.EndsWith("]")))
throw new Exception("parent element and child elements are all empty. this input cannot be processed!");
if (string.IsNullOrEmpty(parent))
parent = strElements[0];
}
AutomationElement e = null;
AutomationElementCollection desktop = GetDesktopElements();
e = FindElement(desktop, parent);
if (e == null)
{
return null;
}
AutomationElement ae = e;
if (strElements != null) // ignore parent if you have full path element format
ae = LocateElement(strElements, e, controlType);
if (ae != null)
{
string fullPath = BuildElementFullNameForTest(ae);
return ae;
}
return null;
}
private AutomationElement LocateElement(string[] elements, AutomationElement ae, string controlType)
{
AutomationElement e = ae;
List<AutomationElement> eList = new List<AutomationElement>();
List<AutomationElement> newElemList = new List<AutomationElement>();
eList.Add(e);
for (int i = 0; i < elements.Length; i++)
{
if (elements[i] == "null")
continue;
if (elements[i] == "empty")
elements[i] = "";
newElemList.Clear();
newElemList.AddRange(eList);
eList.Clear();
foreach (AutomationElement ee in newElemList)
{
AutomationElementCollection c = GetObjectElements(ee);
bool exactMatch = false;
if (elements[i].StartsWith("#") && elements[i].EndsWith("#"))
{
elements[i] = elements[i].Substring(1, elements[i].Length - 2);
exactMatch = true;
}
if (i == elements.Length - 1 && !controlType.Equals("IGNORE") && !controlType.Equals(""))
{
eList.AddRange(FindAllSubElements(c, elements[i], StringToControlType(controlType), exactMatch));
}
else
{
eList.AddRange(FindAllSubElements(c, elements[i], null, exactMatch));
}
}
}
if (eList.Count == 0)
return null;
return eList[0];
}
private List<AutomationElement> FindAllSubElements(AutomationElementCollection c, string ae, ControlType controlType, bool exactMatch)
{
List<AutomationElement> eList = new List<AutomationElement>();
bool found = false;
for (int i = 0; i < c.Count; i++)
{
// name should be exactly as expected element name
if (exactMatch)
{
if (c[i].Current.Name.Equals(ae))
found = true;
}
else if (c[i].Current.Name.Contains(ae)) // name should be contained in expected element name
{
found = true;
}
if (found)
{
found = false;
if (controlType != null)
{
if (c[i].Current.ControlType.CompareTo(controlType) == 0)
{
eList.Add(c[i]);
}
}
else
{
eList.Add(c[i]);
}
}
}
return eList;
}
public AutomationElementCollection GetDesktopElements()
{
return AutomationElement.RootElement.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
}
public AutomationElementCollection GetObjectElements(AutomationElement e)
{
return e.FindAll(TreeScope.Subtree, System.Windows.Automation.Condition.TrueCondition);
}
private AutomationElement FindElement(AutomationElementCollection c, string name)
{
for (int i = 0; i < c.Count; i++)
{
if (c[i].Current.Name.Contains(name))
{
return c[i];
}
}
return null;
}
private AutomationElement FindElement(AutomationElementCollection c, string name, ControlType controlType)
{
for (int i = 0; i < c.Count; i++)
{
if (c[i].Current.Name.Contains(name) && c[i].Current.ControlType.CompareTo(controlType) == 0)
return c[i];
}
return null;
}
private AutomationElement FindElement(List<AutomationElement> elements, string name)
{
foreach (AutomationElement e in elements)
{
if (e.Current.Name.Contains(name))
return e;
}
return null;
}
private string BuildElementFullNameForTest(AutomationElement element)
{
TreeWalker walker = TreeWalker.ControlViewWalker;
AutomationElement elementParent;
AutomationElement node = element;
if (element == null)
{
return null;
}
string elementFullName = element.Current.Name + "]";
do
{
elementParent = walker.GetParent(node);
if (elementParent == AutomationElement.RootElement)
break;
if (!elementParent.Current.Name.Equals(""))
elementFullName = elementParent.Current.Name + "][" + elementFullName;
node = elementParent;
}
while (true);
return "[" + elementFullName;
}
private void WalkAllElements(AutomationElement rootElement, List<AutomationElement> collection)
{
TreeWalker walker = TreeWalker.ControlViewWalker;
AutomationElement e = walker.GetFirstChild(rootElement);
while (e != null)
{
collection.Add(e);
WalkAllElements(e, collection);
e = walker.GetNextSibling(e);
}
}
private ControlType StringToControlType(string controlType)
{
switch (controlType)
{
case "Button":
return ControlType.Button;
case "Calendar":
return ControlType.Calendar;
case "CheckBox":
return ControlType.CheckBox;
case "ComboBox":
return ControlType.ComboBox;
case "DataGrid":
return ControlType.DataGrid;
case "DataItem":
return ControlType.DataItem;
case "Document":
return ControlType.Document;
case "Edit":
return ControlType.Edit;
case "Group":
return ControlType.Group;
case "Header":
return ControlType.Header;
case "HeaderItem":
return ControlType.HeaderItem;
case "Hyperlink":
return ControlType.Hyperlink;
case "Image":
return ControlType.Image;
case "List":
return ControlType.List;
case "ListItem":
return ControlType.ListItem;
case "Menu":
return ControlType.Menu;
case "MenuBar":
return ControlType.MenuBar;
case "MenuItem":
return ControlType.MenuItem;
case "Pane":
return ControlType.Pane;
case "ProgressBar":
return ControlType.ProgressBar;
case "RadioButton":
return ControlType.RadioButton;
case "ScrollBar":
return ControlType.ScrollBar;
case "Separator":
return ControlType.Separator;
case "Slider":
return ControlType.Slider;
case "Spinner":
return ControlType.Spinner;
case "SplitButton":
return ControlType.SplitButton;
case "StatusBar":
return ControlType.StatusBar;
case "Tab":
return ControlType.Tab;
case "TabItem":
return ControlType.TabItem;
case "Table":
return ControlType.Table;
case "Text":
return ControlType.Text;
case "Thumb":
return ControlType.Thumb;
case "TitleBar":
return ControlType.TitleBar;
case "ToolBar":
return ControlType.ToolBar;
case "ToolTip":
return ControlType.ToolTip;
case "Tree":
return ControlType.Tree;
case "TreeItem":
return ControlType.TreeItem;
case "Window":
return ControlType.Window;
default:
return null;
}
}
}
这是不会的代码:
class ElementUtils
{
static TestLog tl;
static TestLog ofl = new TestLog("ObjectFinderLog.txt", true);
public ElementUtils(TestLog testLog)
{
tl = testLog;
}
private ControlType StringToControlType(string controlType)
{
switch (controlType)
{
case "Button":
return ControlType.Button;
case "Calendar":
return ControlType.Calendar;
case "CheckBox":
return ControlType.CheckBox;
case "ComboBox":
return ControlType.ComboBox;
case "DataGrid":
return ControlType.DataGrid;
case "DataItem":
return ControlType.DataItem;
case "Document":
return ControlType.Document;
case "Edit":
return ControlType.Edit;
case "Group":
return ControlType.Group;
case "Header":
return ControlType.Header;
case "HeaderItem":
return ControlType.HeaderItem;
case "Hyperlink":
return ControlType.Hyperlink;
case "Image":
return ControlType.Image;
case "List":
return ControlType.List;
case "ListItem":
return ControlType.ListItem;
case "Menu":
return ControlType.Menu;
case "MenuBar":
return ControlType.MenuBar;
case "MenuItem":
return ControlType.MenuItem;
case "Pane":
return ControlType.Pane;
case "ProgressBar":
return ControlType.ProgressBar;
case "RadioButton":
return ControlType.RadioButton;
case "ScrollBar":
return ControlType.ScrollBar;
case "Separator":
return ControlType.Separator;
case "Slider":
return ControlType.Slider;
case "Spinner":
return ControlType.Spinner;
case "SplitButton":
return ControlType.SplitButton;
case "StatusBar":
return ControlType.StatusBar;
case "Tab":
return ControlType.Tab;
case "TabItem":
return ControlType.TabItem;
case "Table":
return ControlType.Table;
case "Text":
return ControlType.Text;
case "Thumb":
return ControlType.Thumb;
case "TitleBar":
return ControlType.TitleBar;
case "ToolBar":
return ControlType.ToolBar;
case "ToolTip":
return ControlType.ToolTip;
case "Tree":
return ControlType.Tree;
case "TreeItem":
return ControlType.TreeItem;
case "Window":
return ControlType.Window;
default:
return null;
}
}
public AutomationElement FindObjectFullPath(string parent, string childElements, string controlType)
{
string[] strElements = null;
if (!string.IsNullOrEmpty(childElements))
{
childElements = childElements.Trim();
strElements = childElements.Split(new string[] { "[", "]" }, StringSplitOptions.RemoveEmptyEntries);
if (string.IsNullOrEmpty(parent) && !(childElements.StartsWith("[") && childElements.EndsWith("]")))
{
throw new Exception("parent element and child elements are all empty. this input cannot be processed!");
}
if (string.IsNullOrEmpty(parent))
parent = strElements[0];
}
AutomationElement parentAutomationElement = null;
AutomationElementCollection desktop = GetDesktopElements();
parentAutomationElement = FindElement(desktop, parent);
if (parentAutomationElement == null)
{
return null;
}
//Generate object list
ObjectFinderElement root = new ObjectFinderElement(parentAutomationElement, ofl);
root.PrintToLog("\n\nLog for object path " + childElements);
root.PrintToLog("\n" + root.PrintTree());
return LocateElement(strElements, root, controlType);
}
public AutomationElementCollection GetDesktopElements()
{
return AutomationElement.RootElement.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
}
private AutomationElement FindElement(AutomationElementCollection c, string name)
{
for (int i = 0; i < c.Count; i++)
{
if (c[i].Current.Name.Contains(name))
{
return c[i];
}
}
return null;
}
private AutomationElement LocateElement(string[] elements, ObjectFinderElement root, string controlType)
{
ObjectFinderElement objectPath = root;
String foundPath = "";
if (elements == null)
return objectPath.GetAutomationElement();
for (int i = 0; i < elements.Length; i++)
{
if (elements[i] == "null")
continue;
if (elements[i] == "empty")
elements[i] = "";
foundPath += "[" + elements[i] + "]";
Boolean exactMatch = false;
if (elements[i].StartsWith("#") && elements[i].EndsWith("#"))
{
elements[i] = elements[i].Substring(1, elements[i].Length - 2);
exactMatch = true;
}
ControlType ct = null;
if (i == elements.Length - 1 && !controlType.Equals("IGNORE") && !controlType.Equals(""))
{
ct = StringToControlType(controlType);
}
objectPath = objectPath.FindObjectFinderElement(elements[i], exactMatch, ct);
if (objectPath == null)
{
tl.AddLine("Error: FindObjectFullPath - Object path '" + foundPath + "' could not be found");
return null;
}
}
tl.AddLine("Success: FindObjectFullPath: Object path " + foundPath + " was found successfully!");
return objectPath.GetAutomationElement();
}
}
class ObjectFinderElement
{
private AutomationElement current;
private List<ObjectFinderElement> children = new List<ObjectFinderElement>();
private static TestLog ofl;
public ObjectFinderElement(AutomationElement current, TestLog testlog)
{
ofl = testlog;
this.current = current;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
foreach (AutomationElement child in childrenTemp)
children.Add(new ObjectFinderElement(child, ofl));
}
public String PrintTree()
{
return PrintTree("");
}
public String PrintTree(String preText)
{
String self = preText + GetExtendedInfo();
foreach (ObjectFinderElement child in children)
self += "\n" + child.PrintTree(" |" + preText);
return self;
}
public ObjectFinderElement FindObjectFinderElement(String name)
{
return FindObjectFinderElement(name, false, null);
}
public ObjectFinderElement FindObjectFinderElement(String name, Boolean exactMatch)
{
return FindObjectFinderElement(name, exactMatch, null);
}
public ObjectFinderElement FindObjectFinderElement(String name, Boolean exactMatch, ControlType controlType)
{
String ct = "IGNORE";
if (controlType != null)
ct = controlType.LocalizedControlType.ToString();
ofl.AddLine("Scanning for \"" + name + "\" - Exact Match: " + exactMatch + " Control Type: " + ct);
ObjectFinderElement res = FindObjectFinderElementIMP(name, exactMatch, controlType);
if (res != null)
{
ofl.AddLine("Found element \"" + res.GetName() + "\"");
}
return res;
}
public ObjectFinderElement FindObjectFinderElementIMP(String name, Boolean exactMatch, ControlType controlType)
{
ObjectFinderElement res = null;
ofl.AddLine("Scanning element \"" + current.Current.Name + "\"");
Boolean found = CompareElements(name, exactMatch, controlType);
if (found)
res = this;
else
{
foreach (ObjectFinderElement child in children)
{
res = child;
if (res.CompareElements(name, exactMatch, controlType))
return res;
}
foreach (ObjectFinderElement child in children)
{
res = child.FindObjectFinderElementIMP(name, exactMatch, controlType);
if (res != null)
{
found = true;
break;
}
}
}
if (found)
return res;
return null;
}
private Boolean CompareElements(String name, Boolean exactMatch, ControlType controlType)
{
Boolean found = false;
// name should be exactly as expected element name
if (exactMatch)
{
if (current.Current.Name.Equals(name))
found = true;
}
//name should be contained in expected element name
else if (current.Current.Name.Contains(name))
{
found = true;
}
//Test for control type, if needed
if (found == true && controlType != null)
{
if (current.Current.ControlType.CompareTo(controlType) != 0)
found = false;
}
return found;
}
public AutomationElement GetAutomationElement()
{
return current;
}
public String GetName()
{
return current.Current.Name;
}
public String GetExtendedInfo()
{
return "\"" + current.Current.Name + "\" - " + current.Current.ControlType.LocalizedControlType + " - " + children.Count + " Children";
}
public String GetFullInfo()
{
return "Name: \"" + current.Current.Name + "\" - Localized Control Type: " + current.Current.ControlType.LocalizedControlType + " - Bounding Rectangle: " + current.Current.BoundingRectangle + " - Is Content Element: " + current.Current.IsContentElement + " - Is Control Element: " + current.Current.IsControlElement + " - Is Enabled: " + current.Current.IsEnabled + " - Is Keyboard Focusable: " + current.Current.IsKeyboardFocusable + " - Is Offscreen: " + current.Current.IsOffscreen;
}
public void PrintToLog(String text)
{
ofl.AddLine(text);
}
}
我尝试过更改为树木步行者(原始),正如人们在这里建议的那样。不工作。 我还尝试更改ObjectFinderElement(坏名称,我知道,WIP - 它首先有一个不同的目标 - 仅打印找到的元素的树)来搜索后代而不是子项,甚至是整个子树,但它不起作用。
我会试着通过解释我想要做的事情来使事情更清楚。 在Outlook 2010中,左侧边栏包含文件夹名称。我想达到它。 完整路径(使用Inspect)如下: [Microsoft Outlook] [NUIDocumentWindow] [空字符串] [空字符串] [空字符串] [文件夹列表] [Outlook电子邮件地址] [收件箱]
现在我发现它的问题是,第二个“空字符串”是“自定义控件”类型 - 当我打印元素树时 - 它不会在那里,同样适用于它自己的孩子(我需要)。
然而,使用其他方法(第一个代码段)它似乎找到 - 即使我无法打印树,它确实发送鼠标点击它(代码段不包括实际的自动化)。 / p>
由此,我总结了问题出现的地方 - 元素搜索。 在第一个代码段中,如下所示:
public AutomationElementCollection GetObjectElements(AutomationElement e)
{
return e.FindAll(TreeScope.Subtree, System.Windows.Automation.Condition.TrueCondition);
}
在第二个代码段中,元素树的填充代码是;
public ObjectFinderElement(AutomationElement current, TestLog testlog)
{
ofl = testlog;
this.current = current;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
foreach (AutomationElement child in childrenTemp)
children.Add(new ObjectFinderElement(child, ofl));
}
所以我认为这是树木镜。但即使(出于测试目的)我将范围更改为子树(使列表变得疯狂并且具有多个元素) - 缺少的元素仍然不存在!
我会发布下面收到的树(当然还有treecope = Children):
2/10/2014 11:55:55 AM -
Log for object path [Folder List][Contacts]
2/10/2014 11:55:55 AM -
"Inbox - test320@****.com - Microsoft Outlook" - window - 11 Children
|"Frame Splitter" - pane - 0 Children
|"Frame Splitter" - pane - 0 Children
|"MsoDockTop" - pane - 1 Children
| |"Ribbon" - pane - 1 Children
| | |"Ribbon" - pane - 1 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 0 Children
|"MsoDockBottom" - pane - 1 Children
| |"Status Bar" - pane - 1 Children
| | |"Status Bar" - pane - 1 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 0 Children
|"" - pane - 0 Children
|"FolderBar" - pane - 1 Children
| |"NUIDocumentWindow" - pane - 1 Children
| | |"" - pane - 1 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 0 Children
|"NUIDocumentWindow" - pane - 1 Children
| |"" - pane - 0 Children
|"NUIDocumentWindow" - pane - 1 Children
| |"" - pane - 0 Children
|"" - pane - 2 Children
| |"" - pane - 1 Children
| | |"" - pane - 13 Children
| | | |"DAL=on" - tool bar - 0 Children
| | | |"" - text - 0 Children
| | | |"TestAppointment" - pane - 0 Children
| | | |"" - pane - 0 Children
| | | |"" - pane - 0 Children
| | | |"Required: " - pane - 0 Children
| | | |"" - pane - 0 Children
| | | |"When:" - pane - 0 Children
| | | |"Saturday, June 04, 2016 8:00 AM-8:30 AM" - pane - 0 Children
| | | |"Location:" - pane - 0 Children
| | | |"None" - pane - 0 Children
| | | |"" - pane - 2 Children
| | | | |"Vertical" - pane - 1 Children
| | | | | |"" - pane - 0 Children
| | | | |"Day View" - pane - 0 Children
| | | |"" - pane - 1 Children
| | | | |"" - pane - 2 Children
| | | | | |"Message" - pane - 0 Children
| | | | | |"Vertical" - pane - 1 Children
| | | | | | |"" - pane - 0 Children
| |"Microsoft Outlook Social Connector" - pane - 2 Children
| | |"" - pane - 0 Children
| | |"Click to expand the People Pane" - button - 0 Children
|"Table View" - pane - 1 Children
| |"Vertical" - pane - 1 Children
| | |"" - pane - 0 Children
|"Inbox - test320@****.com - Microsoft Outlook" - title bar - 4 Children
| |"System Menu Bar" - menu bar - 1 Children
| | |"System" - menu item - 0 Children
| |"Minimize" - button - 0 Children
| |"Restore" - button - 0 Children
| |"Close" - button - 0 Children
我想这是很多东西,但是非常感谢帮助。
更新: 我找到了另外一个提示 - 似乎为了找到所有元素,我需要使用“AutomationElement.RootElement.FindAll(TreeScope.Subtree,System.Windows.Automation.Condition.TrueCondition);”
所以我不能像树一样组织它!这太麻烦了......
PS。我很难将文字发布为代码...
答案 0 :(得分:0)
我已经解决了。我不知道怎么样,我暂时放弃它,所以我从头开始快速重写。 3-4分钟后,它的工作原理。
以下是感兴趣的人的代码;
using AutomationUtils;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Automation;
namespace GenericUIAutomation
{
class ElementTree
{
private AutomationElement current;
private List<ElementTree> children = new List<ElementTree>();
private List<String> ancestorNames = new List<String>();
private static TestLog ofl;
public ElementTree(TestLog testlog)
{
ofl = testlog;
this.current = AutomationElement.RootElement;
//This is the root element, no ancestors.
ancestorNames = null;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
List<String> childrenAncestors = new List<String>();
childrenAncestors.Add(this.current.Current.Name);
foreach (AutomationElement child in childrenTemp)
children.Add(new ElementTree(child, childrenAncestors));
childrenTemp = null;
}
public ElementTree(AutomationElement current, List<String> ancestorList)
{
this.current = current;
this.ancestorNames = ancestorList;
AutomationElementCollection childrenTemp = current.FindAll(TreeScope.Children, System.Windows.Automation.Condition.TrueCondition);
children.Capacity = childrenTemp.Count;
List<String> childrenAncestors = new List<String>();
childrenAncestors.AddRange(ancestorList);
childrenAncestors.Add(this.current.Current.Name);
foreach (AutomationElement child in childrenTemp)
children.Add(new ElementTree(child, childrenAncestors));
childrenTemp = null;
}
public ElementTree FindInTree(String name, ControlType controlType, String[] ancestorList)
{
String ct = "IGNORE";
if (controlType != null)
ct = controlType.LocalizedControlType.ToString();
ofl.AddLine("Scanning for \"" + name + "\" - " + " Control Type: " + ct);
ElementTree res = FindInTreeIMP(name, controlType, ancestorList);
if (res != null)
ofl.AddLine("Success! Found element \"" + res.GetName() + "\" - " + res.GetAutomationElement().Current.ControlType.LocalizedControlType);
else
ofl.AddLine("Error! No matching element found.");
return res;
}
public ElementTree FindInTreeIMP(String name, ControlType controlType, String[] ancestorList)
{
ofl.AddLine("Scanning element \"" + current.Current.Name + "\" - " + current.Current.ControlType.LocalizedControlType);
Boolean found = CompareElements(name, controlType, ancestorList);
if (found)
return this;
foreach (ElementTree child in children)
{
ElementTree res = child.FindInTreeIMP(name, controlType, ancestorList);
if (res != null)
return res;
}
return null;
}
private Boolean CompareElements(String name, ControlType controlType, String[] ancestorList)
{
Boolean found = false;
//name should be contained in expected element name
if (this.current.Current.Name.Contains(name))
{
PrintToLog("Name match found");
found = true;
}
//Test for control type, if needed
if (found == true && controlType != null)
{
PrintToLog("Control Type match found");
if (this.current.Current.ControlType.CompareTo(controlType) != 0)
found = false;
}
if (found == true && this.ancestorNames.Count >= ancestorList.Length)
{
PrintToLog("Searching for Ancestors");
found = CheckAncestors(ancestorList);
}
else
found = false;
return found;
}
private Boolean CheckAncestors(String[] ancestorList)
{
Boolean found = false;
foreach (String ancestorName in ancestorList)
{
PrintToLog("Scanning for ancestor " + ancestorName);
foreach (String ancestorListElement in ancestorList)
if (ancestorListElement.Contains(ancestorName))
{
PrintToLog("Found ancestor " + ancestorListElement);
found = true;
break;
}
if (found != true)
return found;
else
continue;
}
return found;
}
public String PrintTree()
{
return "\n" + PrintTree("");
}
public String PrintTree(String preText)
{
String self = preText + GetExtendedInfo();
foreach (ElementTree child in children)
self += "\n" + preText + child.PrintTree(preText + " |");
return self;
}
public AutomationElement GetAutomationElement()
{
return current;
}
public String GetName()
{
return current.Current.Name;
}
public String GetExtendedInfo()
{
int childrenCount = 0;
int ancestorsCount = 0;
String name = current.Current.Name;
String controlType = current.Current.ControlType.LocalizedControlType;
if (children != null)
childrenCount = children.Count;
if (ancestorNames != null)
ancestorsCount = ancestorNames.Count;
return "\"" + name + "\" - " + controlType + " - " + childrenCount + " Children" + " - " + ancestorsCount + " Ancestors";
}
public void PrintToLog(String text)
{
ofl.AddLine(text);
}
}
}
还有工作要做,但......有效。