I'm using UIAutomation to get all the words from an AutomationElement that are currently visible on the screen, including its text and its bounding rectangles.
I already receive all visible lines using the TextPattern.GetVisibleRanges() method which returns an array of TextPatternRanges.
In the next step, I try to split each line into words using the TextPatternRange.Move() method with TextUnit.Word. The problem is that I could not find an indicator that tells me when I reach the last word of the line.
I already tried comparing the endpoints of the TextPatternRanges of the line and the current word, their bounding rectangles or the length of the string containing the lines and the extracted words. But I still could not figure out when I reach the end of the
line. That leads to an infinit loop in some lines because there is no indication when to end the line processing.
// Traverse all (at least partially) visible lines var visibleLines = textPattern.GetVisibleRanges(); List<string> testresults = new List<string>(); string expectedText = ""; foreach (var lineRange in visibleLines) { // Select first word var currentRange = lineRange.Clone(); currentRange.Move(TextUnit.Word, 1); currentRange.Move(TextUnit.Word, -1); expectedText += lineRange.GetText(-1); int lineLength = lineRange.GetText(-1).Length; int currentLength = 0; // Traverse through all words of the line int distance = -1; System.Windows.Rect currentWordBounds = System.Windows.Rect.Empty; System.Windows.Rect lastWordBounds = System.Windows.Rect.Empty; while ((currentLength < lineLength) && (currentWordBounds.IsEmpty || !lastWordBounds.Equals(currentWordBounds))) { string wordText = currentRange.GetText(-1); currentLength += wordText.Length; var currentWordBoundList = currentRange.GetBoundingRectangles(); lastWordBounds = currentWordBounds; currentWordBounds = currentWordBoundList.Length != 0 ? currentWordBoundList[0] : System.Windows.Rect.Empty; if (!currentWordBounds.IsEmpty) testresults.Add(wordText); currentRange.Move(TextUnit.Word, 1); distance = currentRange.CompareEndpoints(TextPatternRangeEndpoint.End, lineRange, TextPatternRangeEndpoint.End); } }
Using this code, the inner while-loop does not break at the end of the line in some cases although I compare the length of the extracted words and the length of the line as well as the their bounding rectangles. I also tried to compare the endpoints of the
TextPatternRanges of the current word and the line using the TextPatternRange.CompareEndpoints() method, but it always returns -1 even for the last word of the line. This is probably caused by invisible characters such as \r\n, but I don't know how to get
around this issue. Unfortunately, I could not find an example that shows how to achieve this.
So my question is: How can I detect if I reached the end of a line TextPattern by using the Move method? Or which break condition should I use for the inner while loop, respectively? Or is there another, better way to split a line TextPatternRange into multiple
word TextPatternRanges?