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

时间:2012-05-29 13:03:02

标签: c# winapi pinvoke unmanaged ui-automation

我正在尝试使用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

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

还有其他方法可以阅读细胞吗?或者我可以做出任何改变,请详细说明。

1 个答案:

答案 0 :(得分:3)

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

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");
        }
    }