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

我试图使用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属性为空时会出现问题。

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

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

 IsLegacyIAccessiblePatternAvailable: true 

您可以使用LegacyIAccessiblePattern。 其他post似乎表明它尚未在Client UI Automation 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"); } }