4

在下图中,有一个区域,其中有一个未知(自定义)类。那不是网格或表格。

在此处输入图像描述

我需要能够:

  • 选择此区域中的行
  • 从每个单元格中获取一个值

问题是因为这不是一个常见的类型元素 - 我不知道如何用谷歌搜索这个问题或自己解决它。到目前为止,代码如下:

Process[] proc = Process.GetProcessesByName("programname");
AutomationElement window = AutomationElement.FromHandle(proc [0].MainWindowHandle);
PropertyCondition xEllist2 = new PropertyCondition(AutomationElement.ClassNameProperty, "CustomListClass", PropertyConditionFlags.IgnoreCase);
AutomationElement targetElement = window.FindFirst(TreeScope.Children, xEllist2);

我已经尝试将这个区域作为一个文本框、一个网格、一个组合框来威胁,但到目前为止还没有解决我的问题。有人对如何从该区域获取数据并遍历行有任何建议吗?

编辑:对不起,我做了一个错误的假设。实际上,该区域的标题(第 1 列、第 2 列、第 3 列)和“下半部分”是不同的控件类型

感谢 Wininspector,我能够挖掘有关这些控件类型的更多信息:

  • 标头具有以下属性: HeaderControl 0x056407DC (90441692) Atom: #43288 0xFFFFFFFF (-1)
  • 下半部分有这些: ListControl 0x056408A4 (90441892) Atom: #43288 0x02A6FDA0 (44498336)

我之前展示的代码 - 仅检索“列表”元素,所以这里是更新:

Process[] proc = Process.GetProcessesByName("programname");
AutomationElement window = AutomationElement.FromHandle(proc [0].MainWindowHandle);
//getting the header
PropertyCondition xEllist3 = new PropertyCondition(AutomationElement.ClassNameProperty, "CustomHeaderClass", PropertyConditionFlags.IgnoreCase);
AutomationElement headerEl = XElAE.FindFirst(TreeScope.Children, xEllist3);
//getting the list
PropertyCondition xEllist2 = new PropertyCondition(AutomationElement.ClassNameProperty, "CustomListClass", PropertyConditionFlags.IgnoreCase);
AutomationElement targetElement = window.FindFirst(TreeScope.Children, xEllist2);

在进一步考虑之后,我尝试获取所有列名:

AutomationElementCollection headerLines = headerEl.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.HeaderItem));
string headertest = headerLines[0].GetCurrentPropertyValue(AutomationElement.NameProperty) as string;
textBox2.AppendText("Header 1: " + headertest + Environment.NewLine);

不幸的是,在调试模式下,“headerLines”中的元素计数为 0,因此程序会引发错误。

编辑 2:感谢下面的答案 - 我安装了非托管 UI 自动化,它比默认 UIA 拥有更好的可能性。http://uiacomwrapper.codeplex.com/ 如何使用遗留模式从未知控件类型中获取数据?

if((bool)datagrid.GetCurrentPropertyValue(AutomationElementIdentifiers.IsLegacyIAccessiblePatternAvailableProperty))
{
var pattern = ((LegacyIAccessiblePattern)datagrid.GetCurrentPattern(LegacyIAccessiblePattern.Pattern));
var state = pattern.Current.State;
}

编辑 3. IUIAutoamtion 方法(目前不工作)

        _automation = new CUIAutomation();
        cacheRequest = _automation.CreateCacheRequest();
        cacheRequest.AddPattern(UiaConstants.UIA_LegacyIAccessiblePatternId);
        cacheRequest.AddProperty(UiaConstants.UIA_LegacyIAccessibleNamePropertyId);
        cacheRequest.TreeFilter = _automation.ContentViewCondition;
        trueCondition = _automation.CreateTrueCondition();


        Process[] ps = Process.GetProcessesByName("program");
        IntPtr hwnd = ps[0].MainWindowHandle;
        IUIAutomationElement elementMailAppWindow = _automation.ElementFromHandle(hwnd);


        List<IntPtr> ls = new List<IntPtr>();

        ls = GetChildWindows(hwnd);

        foreach (var child in ls)
        {
            IUIAutomationElement iuiae = _automation.ElementFromHandle(child);
            if (iuiae.CurrentClassName == "CustomListClass")
            {
                var outerArayOfStuff = iuiae.FindAllBuildCache(interop.UIAutomationCore.TreeScope.TreeScope_Children, trueCondition, cacheRequest.Clone());
                var outerArayOfStuff2 = iuiae.FindAll(interop.UIAutomationCore.TreeScope.TreeScope_Children, trueCondition);

                var countOuter = outerArayOfStuff.Length;
                var countOuter2 = outerArayOfStuff2.Length;

                var uiAutomationElement = outerArayOfStuff.GetElement(0); // error
                var uiAutomationElement2 = outerArayOfStuff2.GetElement(0); // error
    //...
    //I've erased what's followed next because the code isn't working even now..
              }
        }

由于这个问题,代码得以实现:

使用 C# 从另一个应用程序的 SysListView32 中的数据网格中读取单元格项

作为结果:

  • countOuter 和 countOuter2 长度 = 0
  • 无法选择元素(列表中的行)
  • 不可能获得任何价值
  • 没有任何工作
4

1 回答 1

2

您可能想尝试使用核心 UI 自动化类。它要求您导入 dll 以在 C# 中使用它。将此添加到您的预构建事件中(或只执行一次等):

"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\tlbimp.exe" %windir%\system32\UIAutomationCore.dll /out:..\interop.UIAutomationCore.dll"

然后,您可以使用 IUIAutomationLegacyIAccessiblePattern。

从以下位置获取调用所需的常量:

C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\UIAutomationClient.h

我可以通过这种方式阅读 Infragistics Ultragrids。

如果那太痛苦,请尝试使用 MSAA。在转换为所有 UIA 核心之前,我将此项目用作 MSAA 的起点: MSSA 示例代码

----- 2012 年 6 月 25 日编辑 ------

我肯定会说找到正确的“标识符”是使用 MS UIAutomation 东西最痛苦的部分。对我帮助很大的是创建一个简单的表单应用程序,我可以将其用作“位置记录器”。本质上,您只需要两件事:

  • 一种即使您离开表单窗口也能保持焦点的方法

  • 使用鼠标所在位置的 x,y 坐标调用 ElementFromPoint()。在 CUIAutomation 类中有一个实现。

我使用 CTRL 按钮告诉我的应用程序抓取鼠标坐标 (System.Windows.Forms.Cursor.Position)。然后我从该点获取元素并递归获取元素的父元素,直到我到达桌面。

        var desktop = auto.GetRootElement();
        var walker = GetRawTreeWalker();
        while (true)
        {
            element = walker.GetParentElement(element);
            if (auto.CompareElements(desktop, element) == 1){ break;}
        }

----- 2012 年 6 月 26 日编辑 -----

一旦您可以递归地找到自动化标识符和/或名称,您就可以在此处轻松修改代码:http: //blog.functionalfun.net/2009/06/introduction-to-ui-automation-with.html用于核心 UI 自动化类。这将允许您在递归时构建一个字符串,该字符串可用于识别嵌套在具有 XPath 样式语法的应用程序中的控件。

于 2012-06-22T22:46:40.397 回答