public TextPatternRange FindAttribute(AutomationTextAttribute attribute, object value, bool backward) { Utility.ValidateArgumentNonNull(attribute, "attribute"); Utility.ValidateArgumentNonNull(value, "value"); if ((attribute == TextPattern.CultureAttribute) && (value is CultureInfo)) { value = ((CultureInfo)value).LCID; } try { return(TextPatternRange.Wrap( this._range.FindAttribute(attribute.Id, value, Utility.ConvertToInt(backward)), this._pattern)); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
/// <summary> /// Compares the endpoint of this range with the endpoint of another range. /// </summary> /// <param name="endpoint">The endpoint of this range to compare.</param> /// <param name="targetRange">The range with the other endpoint to compare. /// The range must have come from the same text provider or an InvalidArgumentException will be thrown.</param> /// <param name="targetEndpoint">The endpoint on the other range to compare.</param> /// <returns>Returns <0 if this endpoint occurs earlier in the text than the target endpoint. /// Returns 0 if this endpoint is at the same location as the target endpoint. /// Returns >0 if this endpoint occurs later in the text than the target endpoint.</returns> public int CompareEndpoints(TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { ValidateEndpointArgument(endpoint, "endpoint"); ValidateRangeArgument(targetRange, "targetRange"); ValidateEndpointArgument(targetEndpoint, "targetEndpoint"); return(UiaCoreApi.TextRange_CompareEndpoints(_hTextRange, endpoint, targetRange._hTextRange, targetEndpoint)); }
/// <summary> /// Moves an endpoint of this range to coincide with the endpoint of another range. /// </summary> /// <param name="endpoint">The endpoint to move.</param> /// <param name="targetRange">Another range from the same text provider.</param> /// <param name="targetEndpoint">An endpoint on the other range.</param> public void MoveEndpointByRange(TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { ValidateEndpointArgument(endpoint, "endpoint"); ValidateRangeArgument(targetRange, "targetRange"); ValidateEndpointArgument(targetEndpoint, "targetEndpoint"); UiaCoreApi.TextRange_MoveEndpointByRange(_hTextRange, endpoint, targetRange._hTextRange, targetEndpoint); }
public int CompareEndpoints( TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { Validate.ArgumentNotNull(parameter: targetRange, parameterName: nameof(targetRange)); return(IUIAutomationTextRange.CompareEndpoints(srcEndPoint: UiaConvert.Convert(textPatternRangeEndpoint: endpoint), range: targetRange.IUIAutomationTextRange, targetEndPoint: UiaConvert.Convert(textPatternRangeEndpoint: targetEndpoint))); }
public void MoveEndpointByRange( TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { Validate.ArgumentNotNull(parameter: targetRange, parameterName: nameof(targetRange)); IUIAutomationTextRange.MoveEndpointByRange(srcEndPoint: UiaConvert.Convert(textPatternRangeEndpoint: endpoint), range: targetRange.IUIAutomationTextRange, targetEndPoint: UiaConvert.Convert(textPatternRangeEndpoint: targetEndpoint)); }
public bool Compare(TextPatternRange range) { try { return 0 != this._range.Compare(range.NativeRange); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
public TextPatternRange FindAttribute( AutomationTextAttribute attribute, object value, bool backward) { Validate.ArgumentNotNull(parameter: attribute, parameterName: nameof(attribute)); var variant = value.ToVariant(); var textPatternRange = new TextPatternRange(textPatternRange: IUIAutomationTextRange.FindAttribute(attr: attribute.Id, val: variant, backward: Convert.ToInt32(value: backward))); variant.Free(); return(textPatternRange); }
internal static TextPatternRange[] Wrap(IUIAutomationTextRangeArray ranges, TextPattern pattern) { if (ranges == null) { return(null); } TextPatternRange[] rangeArray = new TextPatternRange[ranges.Length]; for (int i = 0; i < ranges.Length; i++) { rangeArray[i] = new TextPatternRange(ranges.GetElement(i), pattern); } return(rangeArray); }
public int CompareEndpoints(TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { try { return this._range.CompareEndpoints( (UIAutomationClient.TextPatternRangeEndpoint)endpoint, targetRange.NativeRange, (UIAutomationClient.TextPatternRangeEndpoint)targetEndpoint); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
// check a range argument to see if it is valid. void ValidateRangeArgument(TextPatternRange range, string name) { // check if the argument is null if (range == null) { throw new ArgumentNullException(name); } // check if the range comes from a different text pattern. if (!TextPattern.Compare(_pattern, range._pattern)) { Misc.ThrowInvalidArgument(name); } }
internal static TextPatternRange [] Wrap(SafeTextRangeHandle [] hTextRanges, TextPattern pattern) { if (hTextRanges == null) { return(null); } TextPatternRange[] ranges = new TextPatternRange[hTextRanges.Length]; for (int i = 0; i < hTextRanges.Length; i++) { // if invalid, leave as null if (!hTextRanges[i].IsInvalid) { ranges[i] = new TextPatternRange(hTextRanges[i], pattern); } } return(ranges); }
public bool Compare(TextPatternRange range) { try { return(0 != this._range.Compare(range.NativeRange)); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
public TextPatternRange Clone() { try { return(TextPatternRange.Wrap(_range.Clone(), this._pattern)); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
public TextPatternRange FindText(string text, bool backward, bool ignoreCase) { try { return(TextPatternRange.Wrap( this._range.FindText(text, Utility.ConvertToInt(backward), Utility.ConvertToInt(ignoreCase)), this._pattern)); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
public void MoveEndpointByRange(TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { try { this._range.MoveEndpointByRange( (TextPatternRangeEndpoint)endpoint, targetRange.NativeRange, (TextPatternRangeEndpoint)targetEndpoint); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
public int CompareEndpoints(TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { try { return(this._range.CompareEndpoints( (UIAutomationClient.TextPatternRangeEndpoint)endpoint, targetRange.NativeRange, (UIAutomationClient.TextPatternRangeEndpoint)targetEndpoint)); } catch (System.Runtime.InteropServices.COMException e) { Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; } } }
public TextPatternRange FindText(string text, bool backward, bool ignoreCase) { Validate.StringNeitherNullNorEmpty(parameter: text, parameterName: nameof(text)); TextPatternRange textPatternRange = null; try { textPatternRange = new TextPatternRange(textPatternRange: IUIAutomationTextRange.FindText(text: text, backward: Convert.ToInt32(value: backward), ignoreCase: Convert.ToInt32(value: ignoreCase))); } catch (NotSupportedException ex) { var str = GetText(maxLength: -1).Replace(oldValue: "\n", newValue: ""); var comparisonType = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; var count = backward ? str.LastIndexOf(value: text, comparisonType: comparisonType) : str.IndexOf(value: text, comparisonType: comparisonType); if (count != -1) { var num = count + text.Length; textPatternRange = Clone(); textPatternRange.MoveEndpointByUnit(endpoint: TextPatternRangeEndpoint.Start, unit: TextUnit.Character, count: count); textPatternRange.MoveEndpointByUnit(endpoint: TextPatternRangeEndpoint.End, unit: TextUnit.Character, count: num - str.Length); } } return(textPatternRange); }
/// -------------------------------------------------------------------- /// <summary> /// The delegate for the target text selection changed event. /// </summary> /// <param name="arg">null argument</param> /// <returns>A null object.</returns> /// -------------------------------------------------------------------- private void NotifySelectionChanged() { // Get the array of disjoint selections. var selectionRanges = _targetTextPattern.GetSelection(); // Update the current search range. // For the purposes of this sample only the first selection // range will be echoed in the client. _searchRange = selectionRanges[0]; // For performance and security reasons we'll limit // the length of the string retrieved to 100 characters. // Alternatively, GetText(-1) will retrieve all selected text. var selectedText = _searchRange.GetText(100); _targetSelectionLabel.Content = "Currently selected (100 character maximum): " + selectedText.Length + " characters."; // Report target selection details. DisplaySelectedTextWithAttributes(selectedText); }
//--------------------------------------------------------------------------- // Iterate through child automation elements //--------------------------------------------------------------------------- internal void TS_RecurseChildAutomationElements(TextPatternRange callingRange, CheckType checkType) { int recurseLevel = 1; Comment("Performing recursion through child elements (if any)"); RecurseChildAutomationElements(recurseLevel, callingRange, checkType); m_TestStep++; }
//--------------------------------------------------------------------------- // Create range of specific type (random ranges) //--------------------------------------------------------------------------- internal void CreateRamdomRange(TextPatternRange sourceRange, out TextPatternRange targetRange, TargetRangeType targetRangeType, CheckType checkType) { int startOffset = 0; int endOffset = 0; int length = _actualText.Length; targetRange = null; // Determine offsets of existing range TextPatternRange documentRange = Pattern_DocumentRange(checkType); Range_CompareEndpoints( sourceRange, TextPatternRangeEndpoint.Start, documentRange, TextPatternRangeEndpoint.Start, ref startOffset, null, checkType ); Range_CompareEndpoints( sourceRange, TextPatternRangeEndpoint.End, documentRange, TextPatternRangeEndpoint.End, ref endOffset, null, checkType ); Comment("Calling range is from " + startOffset + " to " + (length + endOffset) + " (characters)" ); // Adjust offsets switch (targetRangeType) { case TargetRangeType.RandomEndsStart: //range that ENDs at START of calling range endOffset = startOffset - length; startOffset = 0; break; case TargetRangeType.RandomStartStart: //range that STARTs at START of calling range endOffset = 0; //start endPoint remains unchanged break; case TargetRangeType.RandomEndsEnd: //range that ENDs at END of calling range startOffset = 0; //end endPoint remains unchanges break; case TargetRangeType.RandomStartsEnd: //range that STARTs at END of calling range startOffset = endOffset + length; endOffset = 0; break; default: throw new ArgumentException("CreateRandomRange() has no support for " + ParseType(targetRangeType)); } // Set offsets of target range Range_Clone( documentRange, ref targetRange, null, checkType ); Range_MoveEndpointByUnit( targetRange, TextPatternRangeEndpoint.Start, TextUnit.Character, startOffset, ref startOffset, null, checkType ); Range_MoveEndpointByUnit( targetRange, TextPatternRangeEndpoint.End, TextUnit.Character, endOffset, ref endOffset, null, checkType ); Comment("Target range is from " + startOffset + " to " + (length + endOffset) + " (characters)"); }
//--------------------------------------------------------------------------- // Add attribute to dictionary //--------------------------------------------------------------------------- internal void AddAttributeToDictionary(TextPatternRange callingRange, ref IDictionary dict, AutomationTextAttribute attrib, CheckType checkType) { object attribValue = null; Range_GetAttributeValue(callingRange, attrib, ref attribValue, null, checkType); if (attribValue == null) ThrowMe(checkType, "Null incorrectly returned for value of text attribute " + Helpers.GetProgrammaticName(attrib)); dict.Add(attrib, attribValue); }
//--------------------------------------------------------------------------- // Create range of specific text unit size //--------------------------------------------------------------------------- internal void CreateTextUnitRange(out TextPatternRange range, TextUnit unit, int expectedCount, TargetRangeType targetRangeType, RangeLocation rangeLocation, CheckType checkType) { int actualCount = 0; TextPatternRange documentRange = Pattern_DocumentRange(CheckType.Verification); if (IsEmptyRange(documentRange, checkType)) ThrowMe(checkType, ParseType(targetRangeType) + " requires non-empty range"); // Create empty range CreateEmptyRange(out range, rangeLocation, checkType); // Expand range to match Range_MoveEndpointByUnit(range, TextPatternRangeEndpoint.End, unit, expectedCount, ref actualCount, null, checkType); // If we did a move endPoint, did expected count = actual count? if (expectedCount != actualCount) { ThrowMe(checkType, "MoveEndpointByUnit(" + ParseType(unit) + "," + expectedCount + ") returned " + actualCount + ", unable to create range of type " + Parse(targetRangeType)); } else { Comment("Created range size " + expectedCount + " " + Parse(unit) + " units"); } }
/// -------------------------------------------------------------------- /// <summary> /// Handles the Search button click. /// </summary> /// <param name="sender">The object that raised the event.</param> /// <param name="e">Event arguments.</param> /// <remarks>Find the text specified in the text box.</remarks> /// -------------------------------------------------------------------- private void SearchDirection_Click(object sender, RoutedEventArgs e) { var searchDirection = (Button) sender; // Are we searching backward through the text control? _searchBackward = ((TraversalDirection) searchDirection.Tag == TraversalDirection.Backward); // Check if search text entered if (_searchString.Text.Trim() == "") { _targetResult.Content = "No search criteria."; _targetResult.Background = Brushes.Salmon; return; } // Does target range support text selection? if (_targetTextPattern.SupportedTextSelection == SupportedTextSelection.None) { _targetResult.Content = "Unable to select text."; _targetResult.Background = Brushes.Salmon; return; } // Does target range support multiple selections? if (_targetTextPattern.SupportedTextSelection == SupportedTextSelection.Multiple) { _targetResult.Content = "Multiple selections present."; _targetResult.Background = Brushes.Salmon; return; } // Clone the document range since we modify the endpoints // as we search. var documentRangeClone = _documentRange.Clone(); // Move the cloned document range endpoints to enable the // selection of the next matching text range. var selectionRange = _targetTextPattern.GetSelection(); if (selectionRange[0] != null) { if (_searchBackward) { documentRangeClone.MoveEndpointByRange( TextPatternRangeEndpoint.End, selectionRange[0], TextPatternRangeEndpoint.Start); } else { documentRangeClone.MoveEndpointByRange( TextPatternRangeEndpoint.Start, selectionRange[0], TextPatternRangeEndpoint.End); } } // Find the text specified in the Search textbox. // Clone the search range since we need to modify it. var searchRangeClone = _searchRange.Clone(); // backward = false? -- search forward, otherwise backward. // ignoreCase = false? -- search is case sensitive. _searchRange = documentRangeClone.FindText( _searchString.Text, _searchBackward, false); // Search unsuccessful. if (_searchRange == null) { // Search string not found at all. if (documentRangeClone.CompareEndpoints( TextPatternRangeEndpoint.Start, searchRangeClone, TextPatternRangeEndpoint.Start) == 0) { _targetResult.Content = "Text not found."; _targetResult.Background = Brushes.Wheat; _searchBackwardButton.IsEnabled = false; _searchForwardButton.IsEnabled = false; } // End of document (either the start or end of the document // range depending on search direction) was reached before // finding another occurence of the search string. else { _targetResult.Content = "End of document reached."; _targetResult.Background = Brushes.Wheat; if (!_searchBackward) { searchRangeClone.MoveEndpointByRange( TextPatternRangeEndpoint.Start, _documentRange, TextPatternRangeEndpoint.End); _searchBackwardButton.IsEnabled = true; _searchForwardButton.IsEnabled = false; } else { searchRangeClone.MoveEndpointByRange( TextPatternRangeEndpoint.End, _documentRange, TextPatternRangeEndpoint.Start); _searchBackwardButton.IsEnabled = false; _searchForwardButton.IsEnabled = true; } } _searchRange = searchRangeClone; } // The search string was found. else { _targetResult.Content = "Text found."; _targetResult.Background = Brushes.LightGreen; } _searchRange.Select(); // Scroll the selection into view and align with top of viewport _searchRange.ScrollIntoView(true); // The WPF target doesn't show selected text as highlighted unless // the window has focus. _targetWindow.SetFocus(); }
//--------------------------------------------------------------------------- // Overload for CreateSubRange //--------------------------------------------------------------------------- internal void CreateSubRange(out TextPatternRange subRange, RangeLocation rangeLocation, CheckType checkType) { int startOffset = 0; int endOffset = 0; CreateSubRange(out subRange, rangeLocation, out startOffset, out endOffset, checkType); }
//--------------------------------------------------------------------------- // Create a TextPatternRange that is a subset of the existing TextPattern.DocumentRange //--------------------------------------------------------------------------- internal void CreateSubRange(out TextPatternRange subRange, RangeLocation rangeLocation, out int startOffset, out int endOffset, CheckType checkType) { TextPatternRange documentRange = Pattern_DocumentRange(CheckType.Verification); int trailingCount = TextLibrary.CountTrailingCRLF(m_le, Pattern_DocumentRange(checkType)); int stringLength = Range_GetText(documentRange).Length - trailingCount; int subRangeLength = (stringLength / 3) - (stringLength/12) + 1; // should 1 less than 1/4. Note that +1 is very important, -1 causes overlaping sub-ranges!!! Comment("Creating sub-range at " + Parse(rangeLocation)); // sanity check: we must have a string length >= 8 if (stringLength < 8) ThrowMe(checkType, "CreateSubRange(" + ParseType(rangeLocation) + ") expected TextPattern.DocumentRange of length 8 or greater, actual length = " + stringLength); // Is it impossible to create sub-range??? while( (subRangeLength > 0) && ((subRangeLength*4)>stringLength) ) subRangeLength--; // this is very small string lengths. // sanity check: If our sub range is too small, we're hosed. Technically, we shouldn't have gotten this far because of earlier checks if( subRangeLength == 0) ThrowMe( checkType, "Unable to create subRange, length of document is likely too small. Should be >= 6, actual length = " + stringLength ); Comment("String length = " + stringLength); Comment("Maximum sub-range size = " + subRangeLength); // initialize vars startOffset = 0; endOffset = 0; // Find upper / lower bounds switch (rangeLocation) { case RangeLocation.Start: // Range 0...{1/8 to 1/4} of document // range from 0 to {7/12...9/12} startOffset = 0; endOffset -= (subRangeLength * 3 ) + (int)Helpers.RandomValue(0, subRangeLength/2); // e.g. -1 * (3/4 + Random(0...1/8)) break; case RangeLocation.Middle: // Range = ~1/4...~3/4 startOffset = subRangeLength + (int) Helpers.RandomValue(0, (subRangeLength)); // e.g. 1/4 + Random(0..1/4) endOffset -= subRangeLength + (int) Helpers.RandomValue(0, (subRangeLength)); // e.g. -1 * (1/4 + Random(0..1/4)) break; case RangeLocation.End: // Range = ~3/4...7/8 of document // Range from {7/12...9/12} to stringLength startOffset = (subRangeLength * 3) + (int) Helpers.RandomValue(0, (subRangeLength/2)); // e.g. 3/4 + Random(0..1/8) endOffset = 0; break; default: break; } // Sanity check... can't be greater than length. // Can't be equal to length (we'd have an empty range then--not what we wanted) if ((startOffset + (-1 * endOffset)) >= stringLength) { Comment("StartOffset = " + startOffset); Comment("EndOffset = " + endOffset); ThrowMe(checkType, "startOffset + (-1*endOffset) cannot be greater than length of document"); } // Another sanity check, end can't be equal to greater than start (must before start if( startOffset >= (stringLength + endOffset)) { Comment("StartOffset = " + startOffset); Comment("EndOffset = " + endOffset); ThrowMe(checkType, "Test case problem: startoffset (" + startOffset + ") cannot be <= [stringLength + endOffset(" + (stringLength + endOffset) + ")], must have at non-zero length range(!)"); } // create sub-range subRange = null; Range_Clone(documentRange, ref subRange, null, checkType); if( startOffset != 0 ) Range_MoveEndpointByUnit(subRange, TextPatternRangeEndpoint.Start, TextUnit.Character, startOffset, ref startOffset, null, checkType); if( endOffset != 0 ) Range_MoveEndpointByUnit(subRange, TextPatternRangeEndpoint.End, TextUnit.Character, endOffset, ref endOffset, null, checkType); // Give results string s = Range_GetText(subRange); Comment("Created sub-range from " + startOffset + " to " + (_actualText.Length + endOffset) + " (characters)" ); Comment("Sub-range length = " + s.Length); Comment("Sub-range = '" + TrimText(s, 512) + "'"); }
internal void CreateRange(out TextPatternRange targetRange, TargetRangeType targetRangeType, out int startOffset, out int endOffset, TextPatternRange sourceRange, CheckType checkType) { TextPattern differentTextPattern = null; // Initialize ref params targetRange = null; startOffset = 0; endOffset = 0; Comment("ENTERING CreateRange(" + Parse(targetRangeType) + "," + startOffset + "," + endOffset + "," + (sourceRange == null ? null : "<sourceRange>") + ",...)"); switch (targetRangeType) { case TargetRangeType.DocumentRange: // entire document targetRange = Pattern_DocumentRange(checkType); Comment("Created range of type " + Parse(targetRangeType)); break; case TargetRangeType.Clone: Range_Clone(sourceRange, ref targetRange, null, checkType); Comment("Created range of type " + Parse(targetRangeType)); break; case TargetRangeType.SameAsCaller: //same as calling range if (sourceRange == null) ThrowMe(checkType, "CreateRange(" + ParseType(targetRangeType) + ") cannot succeed, calling range was not passed into method"); targetRange = sourceRange; Comment("Created range of type " + Parse(targetRangeType)); break; case TargetRangeType.Null: //null value targetRange = null; Comment("Created range of type " + Parse(targetRangeType)); break; case TargetRangeType.EmptyStart: // EMPTY range at START of document CreateEmptyRange(out targetRange, RangeLocation.Start, checkType); break; case TargetRangeType.EmptyMiddle: // EMPTY range in MIDDLE of document CreateEmptyRange(out targetRange, RangeLocation.Middle, checkType); break; case TargetRangeType.EmptyEnd: // EMPTY range at END of document CreateEmptyRange(out targetRange, RangeLocation.End, checkType); break; case TargetRangeType.RandomStart: //RANDOM range at START of document CreateSubRange(out targetRange, RangeLocation.Start, out startOffset, out endOffset, checkType); break; case TargetRangeType.RandomMiddle: //RANDOM range in MIDDLE of document CreateSubRange(out targetRange, RangeLocation.Middle, out startOffset, out endOffset, checkType); break; case TargetRangeType.RandomEnd: //RANDOM range at END of document CreateSubRange(out targetRange, RangeLocation.End, out startOffset, out endOffset, checkType); break; case TargetRangeType.RandomEmptyStart: //EMPTY range at random location near START of document CreateEmptyRandomRange(out targetRange, RangeLocation.Start, targetRangeType, checkType); break; case TargetRangeType.RandomEmptyEnd: //EMPTY range at random location near END of document CreateEmptyRandomRange(out targetRange, RangeLocation.End, targetRangeType, checkType); break; case TargetRangeType.FirstCharacter: //first character in document CreateTextUnitRange(out targetRange, TextUnit.Character, 1, targetRangeType, RangeLocation.Start, checkType); break; case TargetRangeType.MiddleCharacter: //MIDDLE chracter in document CreateTextUnitRange(out targetRange, TextUnit.Character, 1, targetRangeType, RangeLocation.Middle, checkType); break; case TargetRangeType.LastCharacter: //last character in document CreateTextUnitRange(out targetRange, TextUnit.Character, -1, targetRangeType, RangeLocation.End, checkType); break; case TargetRangeType.FirstFormat: //First format range in document CreateTextUnitRange(out targetRange, TextUnit.Format, 1, targetRangeType, RangeLocation.Start, checkType); break; case TargetRangeType.FirstWord: //First word range in document CreateTextUnitRange(out targetRange, TextUnit.Word, 1, targetRangeType, RangeLocation.Start, checkType); break; case TargetRangeType.FirstLine: //First line range in document CreateTextUnitRange(out targetRange, TextUnit.Line, 1, targetRangeType, RangeLocation.Start, checkType); break; case TargetRangeType.FirstParagraph: //First paragraph range in document CreateTextUnitRange(out targetRange, TextUnit.Paragraph, 1, targetRangeType, RangeLocation.Start, checkType); break; case TargetRangeType.FirstPage: //First page range in document CreateTextUnitRange(out targetRange, TextUnit.Page, 1, targetRangeType, RangeLocation.Start, checkType); break; case TargetRangeType.DifferentTextPattern: //range from a different TextPattern differentTextPattern = GetDifferentTextPattern(m_le, checkType); targetRange = differentTextPattern.DocumentRange; break; case TargetRangeType.TwoCharsAdjacent: //two adjacent characters case TargetRangeType.TwoCharsSplitAcrossLine: //two chracters split across a line break CreateMiscRange(targetRangeType, out targetRange, checkType); break; case TargetRangeType.VisibleRange: // Equal to visible range of control CreateVisibleRange(ref targetRange, checkType ); break; case TargetRangeType.RandomEndsStart: //range that ENDs at START of calling range case TargetRangeType.RandomStartStart: //range that STARTs at START of calling range case TargetRangeType.RandomEndsEnd: //range that ENDs at END of calling range case TargetRangeType.RandomStartsEnd: //range that STARTs at END of calling range CreateRamdomRange(sourceRange, out targetRange, targetRangeType, checkType); break; case TargetRangeType.MiddleSpaces: //In middle of spaces between 1st and 2nd word case TargetRangeType.MiddlePunctuation: //In middle of punctuation between 1st and 2nd word case TargetRangeType.HiddenLast: //Last instance of hidden text within document case TargetRangeType.HiddenFirst: //1st instance of hidden text within document default: throw new ArgumentException("CreateRange() has no support for " + ParseType(targetRangeType)); } Comment(" EXITING CreateRange(" + ParseType(targetRangeType) + "," + startOffset + "," + endOffset + "," + (sourceRange == null ? null : "<sourceRange>") + ",...)"); }
internal void CreateRange(out TextPatternRange targetRange, TargetRangeType targetRangeType, TextPatternRange sourceRange, CheckType checkType) { int startOffset = 0; int endOffset = 0; CreateRange( out targetRange, targetRangeType, out startOffset, out endOffset, sourceRange, checkType ); }
internal void CreateMiscRange(TargetRangeType targetRangeType, out TextPatternRange targetRange, CheckType checkType) { int startOffset = 0; int endOffset = 0; int actualStartOffset = 0; int actualEndOffset = 0; string text = ""; TextPatternRange documentRange = Pattern_DocumentRange(CheckType.Verification); Range_GetText(documentRange, ref text, -1, null, checkType); // Sanity check TrimTrailingCRLF(m_le, ref text); if (text.Length == 0) ThrowMe(checkType, "Require non-empty document to create range " + Parse(targetRangeType)); // calculate where range begins/ends switch (targetRangeType) { case TargetRangeType.TwoCharsAdjacent: //two adjacent characters // Bug 1134054: TextPatternRange.ScrollIntoView fails to scroll horizontally on edit control // So... we'll pick something that will always be in view startOffset = 1; endOffset = 3; break; case TargetRangeType.TwoCharsSplitAcrossLine: //two chracters split across a line break // Bug 1059601: TextPatternRange.GetText(-1) retrieves a string that eliminates \n's in RichEdit 2.0 // So... we search for \r instead of \n startOffset = text.IndexOf("\r") - 1; endOffset = startOffset + 3; break; default: throw new ArgumentException("CreateMiscRange() has no support for " + ParseType(targetRangeType)); } // sanity check if ((startOffset < 0) || (endOffset > text.Length)) ThrowMe(checkType, "CreateMiscRange is unable to calculate correct start/end (" + startOffset + "," + endOffset + ") for range"); // Create range CreateEmptyRange(out targetRange, RangeLocation.Start, checkType); Range_MoveEndpointByUnit(targetRange, TextPatternRangeEndpoint.End, TextUnit.Character, endOffset, ref actualEndOffset, null, checkType); Range_MoveEndpointByUnit(targetRange, TextPatternRangeEndpoint.Start, TextUnit.Character, startOffset, ref actualStartOffset, null, checkType); // sanity check if ((startOffset != actualStartOffset) || (endOffset != actualEndOffset)) { ThrowMe(checkType, "CreateMisMatchRange could not move end points as expected. Expected offsets = " + startOffset + ", " + endOffset + ", actual offsets = " + actualStartOffset + ", " + actualEndOffset); } else Comment("Created range of type " + Parse(targetRangeType)); }
/// -------------------------------------------------------------------- /// <summary> /// Finds the text control in our target. /// </summary> /// <param name="src">The object that raised the event.</param> /// <param name="e">Event arguments.</param> /// <remarks> /// Initializes the TextPattern object and event handlers. /// </remarks> /// -------------------------------------------------------------------- private void FindTextProvider_Click(object src, RoutedEventArgs e) { // Set up the conditions for finding the text control. var documentControl = new PropertyCondition( AutomationElement.ControlTypeProperty, ControlType.Document); var textPatternAvailable = new PropertyCondition( AutomationElement.IsTextPatternAvailableProperty, true); var findControl = new AndCondition(documentControl, textPatternAvailable); // Get the Automation Element for the first text control found. // For the purposes of this sample it is sufficient to find the // first text control. In other cases there may be multiple text // controls to sort through. _targetDocument = _targetWindow.FindFirst(TreeScope.Descendants, findControl); // Didn't find a text control. if (_targetDocument == null) { _targetResult.Content = _wpfTarget + " does not contain a Document control type."; _targetResult.Background = Brushes.Salmon; _startWpfTargetButton.IsEnabled = false; return; } // Get required control patterns _targetTextPattern = _targetDocument.GetCurrentPattern( TextPattern.Pattern) as TextPattern; // Didn't find a text control that supports TextPattern. if (_targetTextPattern == null) { _targetResult.Content = _wpfTarget + " does not contain an element that supports TextPattern."; _targetResult.Background = Brushes.Salmon; _startWpfTargetButton.IsEnabled = false; return; } // Text control is available so display the client controls. _infoGrid.Visibility = Visibility.Visible; _targetResult.Content = "Text provider found."; _targetResult.Background = Brushes.LightGreen; // Initialize the document range for the text of the document. _documentRange = _targetTextPattern.DocumentRange; // Initialize the client's search buttons. if (_targetTextPattern.DocumentRange.GetText(1).Length > 0) { _searchForwardButton.IsEnabled = true; } // Initialize the client's search TextBox. _searchString.IsEnabled = true; // Check if the text control supports text selection if (_targetTextPattern.SupportedTextSelection == SupportedTextSelection.None) { _targetResult.Content = "Unable to select text."; _targetResult.Background = Brushes.Salmon; return; } // Edit control found so remove the find button from the client. _findEditButton.Visibility = Visibility.Collapsed; // Initialize the client with the current target selection, if any. NotifySelectionChanged(); // Search starts at beginning of doc and goes forward _searchBackward = false; // Initialize a text changed listener. // An instance of TextPatternRange will become invalid if // one of the following occurs: // 1) The text in the provider changes via some user activity. // 2) ValuePattern.SetValue is used to programatically change // the value of the text in the provider. // The only way the client application can detect if the text // has changed (to ensure that the ranges are still valid), // is by setting a listener for the TextChanged event of // the TextPattern. If this event is raised, the client needs // to update the targetDocumentRange member data to ensure the // user is working with the updated text. // Clients must always anticipate the possibility that the text // can change underneath them. Automation.AddAutomationEventHandler( TextPattern.TextChangedEvent, _targetDocument, TreeScope.Element, TextChanged); // Initialize a selection changed listener. // The target selection is reflected in the client. Automation.AddAutomationEventHandler( TextPattern.TextSelectionChangedEvent, _targetDocument, TreeScope.Element, OnTextSelectionChange); }
public static int CountTextUnit(TextUnit tu, TextPatternRange rangeToCount) { return TextLibraryCount.CountTextUnit(tu, rangeToCount); }
/// -------------------------------------------------------------------- /// <summary> /// Gets the enclosing element of the target selection. /// </summary> /// <param name="sender">The object that raised the event.</param> /// <param name="e">Event arguments.</param> /// -------------------------------------------------------------------- private void GetEnclosingElement_Click(object sender, RoutedEventArgs e) { // Obtain the enclosing element. AutomationElement enclosingElement; try { enclosingElement = _searchRange.GetEnclosingElement(); } catch (ElementNotAvailableException) { // TODO: error handling. return; } // Assemble the information about the enclosing element. var enclosingElementInformation = new StringBuilder(); enclosingElementInformation.Append( "Enclosing element:\t").AppendLine( enclosingElement.Current.ControlType.ProgrammaticName); // The WPF target doesn't show selected text as highlighted unless // the window has focus. _targetWindow.SetFocus(); // Display the enclosing element information in the client. _targetSelectionDetails.Text = enclosingElementInformation.ToString(); // Is the enclosing element the entire document? // If so, select the document. if (enclosingElement == _targetDocument) { _documentRange = _targetTextPattern.DocumentRange; _documentRange.Select(); return; } // Otherwise, select the range from the child element. var childRange = _documentRange.TextPattern.RangeFromChild(enclosingElement); childRange.Select(); }
public int CompareEndpoints(TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { return(source.CompareEndpoints(endpoint, targetRange.Source, targetEndpoint)); }
internal static TextPatternRange[] Wrap(UIAutomationClient.IUIAutomationTextRangeArray ranges, TextPattern pattern) { if (ranges == null) { return null; } TextPatternRange[] rangeArray = new TextPatternRange[ranges.Length]; for (int i = 0; i < ranges.Length; i++) { rangeArray[i] = new TextPatternRange(ranges.GetElement(i), pattern); } return rangeArray; }
internal void CreateEmptyRange(out TextPatternRange range, RangeLocation rangeLoc, CheckType checkType) { string text = ""; int expectedCount = 0; int actualCount = 0; // Get range and text in the range range = null; range = Pattern_DocumentRange(checkType); if (IsEmptyRange(range, checkType)) { Comment("Document already has an empty range, proceeding with next test step"); return; } else { Range_GetText(range, ref text, -1, null, checkType); } // Now, create the degenerate range switch (rangeLoc) { case RangeLocation.Start: // Move end point to start of document expectedCount = -1; actualCount = expectedCount; ExpandRange(range, TextPatternRangeEndpoint.End, TextUnit.Document, expectedCount, out actualCount, true, checkType); break; case RangeLocation.Middle: // Move start point to middle of doc expectedCount = text.Length / 2; actualCount = expectedCount; ExpandRange(range, TextPatternRangeEndpoint.Start, TextUnit.Character, expectedCount, out actualCount, true, checkType); // Move End point to middle of doc expectedCount = -1 * (text.Length - expectedCount); actualCount = expectedCount; ExpandRange(range, TextPatternRangeEndpoint.End, TextUnit.Character, expectedCount, out actualCount, true, checkType); break; case RangeLocation.End: // Move end point to start of document expectedCount = 1; actualCount = expectedCount; ExpandRange(range, TextPatternRangeEndpoint.Start, TextUnit.Document, expectedCount, out actualCount, true, checkType); //Bug1134056: Resolve RichEdit control inconsistencies / unexpected behavior TextLibrary.TrimRangeCRLF(m_le, range); break; default: throw new ArgumentException("TS_CreateEmptyRange() has no support for " + ParseType(rangeLoc)); } // Final check if (IsEmptyRange(range, checkType)) Comment("Created degenerate (empty) range at " + rangeLoc + " of the document"); else { ThrowMe(checkType, "TS_CreateEmptyRange() failed to create empty range, text = '" + TrimText(Range_GetText(range), 512) + "'"); } }
//--------------------------------------------------------------------------- // Calls MOveEndPointByUnit2(range,TextUnit,count) and validates expected / actual return value //--------------------------------------------------------------------------- internal void TS_MoveEndpointByUnitAndValidate2(TextPatternRange callingRange, TextPatternRangeEndpoint endPoint, Count requestedCountEnum, Count expectedCountEnum, int[] countOfTextUnits, int richEditOffset, CheckType checkType) { int requestedCount = 0; int expectedCount = 0; int actualCount = 0; int errorCount = 0; TextPatternRange rangeToMove = null; for( TextUnit unit = TextUnit.Character; unit <= TextUnit.Document; unit ++ ) { requestedCount = CountConvert(requestedCountEnum, countOfTextUnits[(int) unit]); expectedCount = CountConvert(expectedCountEnum, countOfTextUnits[(int) unit]); // Clone range Range_Clone(callingRange, ref rangeToMove, null, checkType); Range_MoveEndpointByUnit(rangeToMove, endPoint, unit, requestedCount, ref actualCount, null, checkType); if (actualCount == expectedCount) Comment("MoveEndpointByUnit(" + endPoint + "," + unit + "," + requestedCount + ") moved the range by " + actualCount + ", as expected"); else if ((richEditOffset != 0) && ((actualCount + richEditOffset) == expectedCount)) { Comment("MoveEndpointByUnit(" + endPoint + "," + unit + "," + requestedCount + ") moved the range by " + actualCount + ", as expected taking into account extra characters added by RichEdit"); } else { Comment(KNOWNISSUE + " MoveEndpointByUnit(" + endPoint + "," + unit + "," + requestedCount + ") moved the range by " + actualCount + ", expected " + expectedCount); errorCount++; } } if (errorCount > 0) ThrowMe(checkType, errorCount + " errors while calling MoveEndpointByUnit() method"); m_TestStep++; }
public bool Compare(TextPatternRange range) { return(source.Compare(range.Source)); }
public static int CountTrailingCRLF(AutomationElement autoElement, TextPatternRange callingRange) { // Bug: 1134056: Resolve RichEdit control inconsistencies / unexpected behavior int offset = 0; Library.ValidateArgumentNonNull(autoElement, "AutomationElement cannot be null"); Library.ValidateArgumentNonNull(callingRange, "callingRange cannot be null"); if (IsRichEdit(autoElement) == true) { string text = callingRange.GetText(-1); offset = GetTrailingCRLFOffset(text); } return offset; }
internal void CreateEmptyRandomRange(out TextPatternRange range, RangeLocation rangeLoc, TargetRangeType targetRangeType, CheckType checkType) { int actualCount = 0; TextPatternRange documentRange = Pattern_DocumentRange(CheckType.Verification); // Requires non-empty range if (IsEmptyRange(documentRange, checkType)) ThrowMe(checkType, ParseType(targetRangeType) + " requires non-empty range"); // Get range and text in the range range = null; range = Pattern_DocumentRange(checkType); // calculate position of random range int length = Range_GetText(range).Length; int offset = 1 + Helpers.RandomValue(1, length / 4); // Create empty range by collapsing endpoint to start CreateEmptyRange(out range, RangeLocation.Start, checkType); // Now, create the degenerate range switch (rangeLoc) { case RangeLocation.Start: // Move start (and end) endPoint to location in document // This works because Start EndPoint can never roll past end endPoint (it just rolls with start) Range_MoveEndpointByUnit(range, TextPatternRangeEndpoint.Start, TextUnit.Character, offset, ref actualCount, null, checkType); break; case RangeLocation.End: offset = 0 - offset; // was length - offset. This seems to be correct // Move start (and end) endPoint to location in document // This works because Start EndPoint can never roll past end endPoint (it just rolls with start) Range_MoveEndpointByUnit(range, TextPatternRangeEndpoint.Start, TextUnit.Character, offset, ref actualCount, null, checkType); break; default: throw new ArgumentException("TS_CreateEmptyRandomRange() has no support for " + ParseType(rangeLoc)); } // Final check if (IsEmptyRange(range, checkType)) Comment("Created degenerate (empty) range near " + rangeLoc + " of the document"); else { ThrowMe(checkType, "TS_CreateEmptyRange() failed to create empty range, text = '" + TrimText(Range_GetText(range), 512) + "'"); } }
public bool Compare(TextPatternRange range) { Validate.ArgumentNotNull(parameter: range, parameterName: nameof(range)); return(Convert.ToBoolean(value: IUIAutomationTextRange.Compare(range: range.IUIAutomationTextRange))); }
//--------------------------------------------------------------------------- // Tests if start and end points of a range are identical //--------------------------------------------------------------------------- internal bool IsEmptyRange(TextPatternRange range, CheckType checkType) { int results = 0; // We compare if start and end points are the same... Range_CompareEndpoints(range, TextPatternRangeEndpoint.Start, range, TextPatternRangeEndpoint.End, ref results, null, checkType); return (results == 0); }
/// <summary> /// Compares this range with another range. /// </summary> /// <param name="range">A range to compare. /// The range must have come from the same text provider or an InvalidArgumentException will be thrown.</param> /// <returns>true if both ranges span the same text.</returns> public bool Compare(TextPatternRange range) { ValidateRangeArgument(range, "range"); return(UiaCoreApi.TextRange_Compare(_hTextRange, range._hTextRange)); }
internal void RecurseChildAutomationElements(int recurseLevel, TextPatternRange callingRange, CheckType checkType) { AutomationElement parent = null; AutomationElement[] children = null; if (recurseLevel > recurseLevelMax) throw new ArgumentException("Arbitrary sanity check: RecurseChildAutomationElement likely should not have exceeded " + recurseLevelMax + " generations of children for a given document"); if (callingRange == null) throw new ArgumentException("RecurseChildAutomationElement requires non-null callingRange"); // Get child and parent automation elements Range_GetEnclosingElement(callingRange, ref parent, null, checkType); Range_GetChildren(callingRange, ref children, checkType); Comment("Level " + recurseLevel + " has " + children.Length + " child Automation Elements"); for (int i = 0; i < children.Length; i++) { int childrenCount; TextPatternRange childRange = null; // Get child range Pattern_RangeFromChild(_pattern, ref childRange, children[i], null, checkType); // Validate child range if (childRange == null) ThrowMe(checkType, "Level " + recurseLevel + ", Child[" + i + "] incorrectly returned null range."); childrenCount = childRange.GetChildren().Length; Comment("Level " + recurseLevel + ", Child[" + i + "] range has " + childRange.GetChildren().Length + " child elements."); if (childrenCount > 0) RecurseChildAutomationElements(recurseLevel + 1, childRange, checkType); // Perform value equality to validate instances have same identity VerifyAutomationElement(parent, children[i], checkType); } }
public void MoveEndpointByRange(TextPatternRangeEndpoint endpoint, TextPatternRange targetRange, TextPatternRangeEndpoint targetEndpoint) { source.MoveEndpointByRange(endpoint, targetRange.Source, targetEndpoint); }
/// -------------------------------------------------------------------- /// <summary> /// The delegate for the target text changed event. /// </summary> /// <param name="arg">null argument</param> /// <returns>A null object.</returns> /// -------------------------------------------------------------------- private void NotifyTextChanged(string message) { // Notify the user of the text changed event. _targetSelectionLabel.Content = message; // Re-initialize the document range for the text of the document // since we don't know the extent of the changes. For example, a // change in the font color attribute, such as on a hyperlink // mouseover, raises this event but doesn't change the content of // the text control. _documentRange = _targetTextPattern.DocumentRange; }
//--------------------------------------------------------------------------- // Create a TextPatternRange that contains all visible ranges //--------------------------------------------------------------------------- internal void CreateVisibleRange( ref TextPatternRange targetRange, CheckType checkType ) { int startMin = Int32.MaxValue, startTemp = 0; int endMax = Int32.MinValue, endTemp = 0;; TextPatternRange[] visibleRanges = null; Pattern_GetVisibleRanges( _pattern, ref visibleRanges, null, checkType ); targetRange = Pattern_DocumentRange(checkType); // Find smallest start endPoint, highest end endPoint for( int i=0; i < visibleRanges.Length; i++ ) { Range_CompareEndpoints(visibleRanges[i], TextPatternRangeEndpoint.Start, targetRange, TextPatternRangeEndpoint.Start, ref startTemp, null, checkType); Range_CompareEndpoints(visibleRanges[i], TextPatternRangeEndpoint.End, targetRange, TextPatternRangeEndpoint.End, ref endTemp, null, checkType); startMin = Math.Min( startMin, startTemp ); endMax = Math.Max( endMax, endTemp ); } // Build new range Range_MoveEndpointByUnit(targetRange, TextPatternRangeEndpoint.Start, TextUnit.Character, startMin, ref startTemp, null, checkType); Range_MoveEndpointByUnit(targetRange, TextPatternRangeEndpoint.End, TextUnit.Character, endMax, ref endMax, null, checkType); Comment("Created composite range of " + visibleRanges.Length + " visible ranges"); Comment(" Start = " + startMin.ToString().PadLeft(5) + " (actual = " + startTemp.ToString().PadLeft(5) + ")"); Comment(" End = " + endMax.ToString().PadLeft(5) + " (actual = " + endTemp.ToString().PadLeft(5) + ")"); Comment(" Text = " + TrimText( Range_GetText(targetRange), 512 ) ); }
//--------------------------------------------------------------------------- // Calls move N+1 times and validates results // First N times should equal expected result // N+1'th time should return 0 // Unit is the actual unit we're going to call move with. //--------------------------------------------------------------------------- internal void TS_MoveNTimes(TextUnit unit, int[] numberOfTextUnits, TextPatternRange range, int moveCount, int expectedResult, CheckType checkType) { int count = 0; int countOffset = 0; int actualResult = 0; bool isRichEdit = TextLibrary.IsRichEdit(m_le); string msg = "Move(" + unit.ToString() + ", " + moveCount + ")"; TextPatternRange callingRange = null; // Get document range and clone calling range Range_Clone(range, ref callingRange, null, checkType); // Get count of type count = numberOfTextUnits[(int)unit]; if (isRichEdit == true) // Bug 1059357 or 1134056 (take your pick) { if (unit == TextUnit.Character) { countOffset = _trailingCRLFCount; count += countOffset; Comment("Depricating expected count of chracters by " + countOffset + " for textunit " + ParseType(TextUnit.Character)); } else if (unit == TextUnit.Word) { count--; Comment("Depricating expected count of words by -1 for textunit " + ParseType(TextUnit.Word)); } } // First N times, the return value of Move should equal result for (int i = 0; i < count; i++) { Range_Move(callingRange, unit, moveCount, ref actualResult, null, checkType); if (actualResult != expectedResult) { ThrowMe(checkType, msg + " returned " + actualResult + ", expected = " + expectedResult); } } Comment(msg + " called " + count + " times successfully"); // Now move N+1'th time, should always return 0 moveCount = 0; Range_Move(callingRange, unit, moveCount, ref actualResult, null, checkType); if (actualResult != 0) ThrowMe(checkType, msg + " returned " + actualResult + ", expected = 0"); else Comment(msg + " returned 0 as expected"); m_TestStep++; }
/// ------------------------------------------------------------------- /// <summary> /// Count a single TextUnit /// </summary> /// ------------------------------------------------------------------- internal static int Win32CountTextUnit(TextUnit textUnit, TextPatternRange rangeToCount) { return Win32CountTextUnit(textUnit, rangeToCount); }
//--------------------------------------------------------------------------- // Expands range by a given # of units, and optionally then // validates if # of units moved actual == expected //--------------------------------------------------------------------------- internal void ExpandRange(TextPatternRange range, TextPatternRangeEndpoint endPoint, TextUnit unit, int expectedCount, out int actualCount, bool mustMatchExpected, CheckType checkType) { actualCount = 0; Range_MoveEndpointByUnit(range, endPoint, unit, expectedCount, ref actualCount, null, checkType); if (mustMatchExpected == true) { if (actualCount != expectedCount) { ThrowMe( checkType, "Unable to modify range " + endPoint + " endPoint by expected " + expectedCount + " " + unit + " units. Actual = " + actualCount); } } }
public static void TrimRangeCRLF(AutomationElement autoElement, TextPatternRange callingRange) { Library.ValidateArgumentNonNull(autoElement, "AutomationElement cannot be null"); Library.ValidateArgumentNonNull(autoElement, "callingRange cannot be null"); if (IsRichEdit(autoElement) == true) { int actualOffset = 0; // Actual offset of \r, \n or \r\n int expectedOffset = 0; // Expected offset of \r, \n or \r\n string text = callingRange.GetText(-1); expectedOffset = GetTrailingCRLFOffset(text); // Now... move the endpoint actualOffset = callingRange.MoveEndpointByUnit(TextPatternRangeEndpoint.End, TextUnit.Character, expectedOffset); if (actualOffset != expectedOffset) throw new InvalidOperationException("Unable to move endpoint back by " + expectedOffset + " characters. Actual = " + actualOffset); else /* changing to new flexible logging */ //Logger.LogComment("Adjusted size of range for RichEdit control by omitting last " + expectedOffset + " characters"); UIVerifyLogger.LogComment("Adjusted size of range for RichEdit control by omitting last " + expectedOffset + " characters"); } }
internal void GetAttributeValues(TextPatternRange callingRange, out IDictionary dict, AttributeType attribType, CheckType checkType) { bool isRichEdit = TextLibrary.IsRichEdit(m_le); int supportedAttribs = 0; // How many attributes for this control??? int expectedCount = 0; // How many attributes do we expect to have? IDictionaryEnumerator enum1 = null; AutomationTextAttribute key = null; AttributeMadness attrib = null; dict = new Hashtable(attributesCount); enum1 = attributeMadness.GetEnumerator(); // count attributes for (int i = 0; i < attributeMadness.Count; i++) { enum1.MoveNext(); key = (AutomationTextAttribute)enum1.Key; attrib = (AttributeMadness)enum1.Value; switch (attribType) { case AttributeType.SupportedAttributes: // Supported attributes on the edit/richedit control if (((isRichEdit == true) && (attrib.isRichEditControl == true)) || ((isRichEdit == false) && (attrib.isEditControl == true))) AddAttributeToDictionary(callingRange, ref dict, key, checkType); break; case AttributeType.UnsupportedAttributes: // Attributes not supported by the edit/richedit control if (((isRichEdit == true) && (attrib.isRichEditControl == false)) || ((isRichEdit == false) && (attrib.isEditControl == false))) AddAttributeToDictionary(callingRange, ref dict, key, checkType); break; case AttributeType.EnumAttributes: // Those attributes whose data type is an enum if (attrib.isEnum == true) AddAttributeToDictionary(callingRange, ref dict, key, checkType); break; //case AttributeType.Null: // Delibratly skipped, this is for sending NULL as arg to GetAttributeValue // Building a dictionary here doesn't makes sense. default: throw new ArgumentException("GetAttributeValues() has no support for " + ParseType(attribType)); } } // Determine what correct count should be if (isRichEdit == true) supportedAttribs = richEditControlAttribCount; else supportedAttribs = editControlAttribCount; switch (attribType) { case AttributeType.SupportedAttributes: // Supported attributes on the edit/richedit control expectedCount = supportedAttribs; break; case AttributeType.UnsupportedAttributes: // Attributes not supported by the edit/richedit control expectedCount = attributesCount - supportedAttribs; break; case AttributeType.EnumAttributes: // Those attributes whose data type is an enum expectedCount = enumAttributesCount; break; case AttributeType.Null: // Null value for attribute(s) expectedCount = supportedAttribs; break; default: throw new ArgumentException("GetAttributeValues() has no support for " + ParseType(attribType)); } // Now, does count equal expectations??? if (dict.Count != expectedCount) { ThrowMe(checkType, "Expected " + expectedCount + " attributes for Win32 " + (isRichEdit == true ? "RichEdit" : "Edit") + " control, got " + dict.Count); } else Comment("Correctly retrived values for " + dict.Count + " attributes for Win32 " + (isRichEdit == true ? "RichEdit" : "Edit") + " control"); }