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

2023-11-30

我正在尝试使用 C# .net ui-automation 和 winapi 读取另一个进程的 SysListView32 中的数据网格项

使用 ui-automation 的 C# 代码
http://pastebin.com/6x7rXMiW

使用 winapi 的 C# 代码http://pastebin.com/61RjXZuK

使用此代码,您只需将鼠标指针放在屏幕上的 SysListView32 上,然后按 Enter 键。

现在,两个代码在具有以下属性的单元格项目上返回空

pastebin.com/Rw9FGkYC

但这两个代码都适用于以下属性

pastebin.com/L51T4PLu

我注意到的唯一区别是名称属性包含与单元格中相同的数据,但当名称属性为空时会出现问题。

还有其他方法可以读取单元格吗?或者我可以做出任何更改,请详细说明。


我还建议使用检查工具。如果你看到这个:

IsLegacyIAccessiblePatternAvailable:    true

您可以使用 LegacyIAccessiblePattern。其他帖子似乎表明它尚未出现在客户端 UI 自动化 Api 中,但它位于核心中。您可以通过包装它来使用 .NET 中的核心。我将其添加到我的构建中以开始使用它:

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

如果确实支持此模式,我可以添加更多详细信息。


嗯,那么你可能很好。

这是一些示例代码:

    // C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\UIAutomationClient.h
    public const int UIA_LegacyIAccessibleNamePropertyId = 30092;
    public const int UIA_LegacyIAccessibleValuePropertyId = 30093;
    public const int UIA_IsTextPatternAvailablePropertyId = 30040;
    public const int UIA_IsItemContainerPatternAvailablePropertyId = 30108;
    public const int UIA_AutomationIdPropertyId = 30011;
    public const int UIA_NamePropertyId = 30005;
    public const int UIA_IsInvokePatternAvailablePropertyId = 30031;

    public const int UIA_ItemContainerPatternId = 10019;
    public const int UIA_TextPatternId = 10014;
    public const int UIA_LegacyIAccessiblePatternId = 10018;
    public const int UIA_ValuePatternId = 10002;
    public const int UIA_InvokePatternId = 10000;

    public const int UIA_ButtonControlTypeId = 50000;

        uiAutomationCore = new UiAutomationCore();
        cacheRequest = UiAuto.CreateCacheRequest();
        cacheRequest.AddPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);
        cacheRequest.AddProperty(WindowsConstants.UIA_LegacyIAccessibleNamePropertyId);

       cacheRequest.AddProperty(WindowsConstants.UIA_LegacyIAccessibleValuePropertyId);
        cacheRequest.TreeFilter = UiAuto.ContentViewCondition;
        trueCondition = UiAuto.CreateTrueCondition();

// A Pinvoke GetChildWindows call because it is 
// the fastest way to traverse down to a handle
foreach (var child in GetChildWindows(someIUIAutomationElement.GetMainWindowHandle()))
        {
            var sb = new StringBuilder(100);
            // get the name of each window & see if it is an ultragrid
            // (get the name because the getchildwindows call only gets the handles
            User32.GetClassName(child, sb, sb.Capacity);
            var foundProperGrid = false;
            if (Win32Utils.GetText(child) != "UltraGrid1")
                continue;
            // if this is an ultragrid, create a core automation object
            var iuiae = UiCore.AutoElementFromHandle(child);

            // get the children of the grid
            var outerArayOfStuff =
                iuiae.FindAllBuildCache(interop.UIAutomationCore.TreeScope.TreeScope_Children,
                                        trueCondition,
                                        cacheRequest.Clone());

            var countOuter = outerArayOfStuff.Length;
            // loop through the grid children 
            for (var counterOuter = 0; counterOuter < countOuter; counterOuter++)
            {
                // make a core automation object from each
                var uiAutomationElement = outerArayOfStuff.GetElement(counterOuter);

                // hacky - see if this grid has a GroupBy Box as first 'row'
                //       - if so, this is the proper grid
                //       - ignore other grids
                if (!foundProperGrid && uiAutomationElement.CurrentName.Equals("GroupBy Box"))
                {
                    foundProperGrid = true;
                }
                else if (foundProperGrid)
                {
                    // 'cast' the object to a core 'legacy msaa' object
                    IUIAutomationLegacyIAccessiblePattern outerLegacyPattern =
                        uiAutomationElement.GetCachedPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);
                    Log.Info("OUTER, CachedName = " + outerLegacyPattern.CachedName);

                    try
                    {
                        // select the 'row' to give visual feedback
                        outerLegacyPattern.Select(3);
                    }
                    catch (Exception exc)
                    {
                        Log.Info(exc.Message);
                    }

                    // get the cells in a row
                    var arrayOfStuff =
                        uiAutomationElement.FindAllBuildCache(TreeScope.TreeScope_Children,
                                                                trueCondition,
                                                                cacheRequest.Clone());
                    // loop over the cells in a row
                    var count = arrayOfStuff.Length;
                    for (var counter = 0; counter < count; counter++)
                    {
                        // get a cell
                        var currIUIA = arrayOfStuff.GetElement(counter);

                        // 'cast' cell to a core 'legacy msaa' object
                        IUIAutomationLegacyIAccessiblePattern legacyPattern =
                            currIUIA.GetCachedPattern(WindowsConstants.UIA_LegacyIAccessiblePatternId);

                        // dump cell name & value for reference
                        var name = legacyPattern.CachedName;
                        Log.Info(counter + ") CachedName = " + name);
                        var value = legacyPattern.CachedValue;
                        Log.Info("CachedValue = " + value);
                        // check if cell name corresponds to what is being checked
                        if (name.Equals("Date"))
                        {
                            //if (!value.StartsWith("5/23/2012"))
                            if (!value.StartsWith("5/25/2012"))
                                errorList.AppendLine("Bad Date = " + value);
                        }
                        if (name.Equals("XXX"))
                        {
                            if (!(value.Equals("1") || value.Equals("2")))
                                errorList.AppendLine("Bad XXX= " + value);
                        }
                        if (name.Equals("YYY"))
                        {
                            if (!value.Equals("ZZZ"))
                                errorList.AppendLine("Bad YYY = " + value);
                        }
                    }
                }
            }
            foundProperGrid = false;
        }
        var stopTime = DateTime.Now;
        var duration = stopTime - startTime;
        Log.Info("duration = " + duration);

        if (!"".Equals(errorList.ToString()))
        {
            Log.Info("errorList = " + errorList);
            Assert.Fail("Test errors");
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐