void UnsafeNativeMethods.ITextStoreACP.GetTextExt(int viewCookie, int startIndex, int endIndex, out UnsafeNativeMethods.RECT rect, out bool clipped) { PresentationSource source; IWin32Window win32Window; CompositionTarget compositionTarget; ITextView view; ITextPointer startPointer; ITextPointer endPointer; GeneralTransform transform; Point milPointTopLeft; Point milPointBottomRight; // We need to update the layout before getting rect. It could be dirty by SetText call of TIP. _isInUpdateLayout = true; UiScope.UpdateLayout(); _isInUpdateLayout = false; // (Dev11 721274) if UpdateLayout caused a text change, startIndex // and endIndex are no longer valid. Handling this correctly is quite // difficult - Cicero assumes that the text can't change while it // owns the lock. Instead, we artificially reset the char count (to // keep VerifyTextStoreConsistency happy), and return TS_R_NOLAYOUT // to the caller; this seems to be good enough (i.e. avoids crashes) // in practice. if (_hasTextChangedInUpdateLayout) { _netCharCount = this.TextContainer.IMECharCount; throw new COMException(SR.Get(SRID.TextStore_TS_E_NOLAYOUT), UnsafeNativeMethods.TS_E_NOLAYOUT); } rect = new UnsafeNativeMethods.RECT(); clipped = false; GetVisualInfo(out source, out win32Window, out view); compositionTarget = source.CompositionTarget; // We use local coordinates. startPointer = CreatePointerAtCharOffset(startIndex, LogicalDirection.Forward); startPointer.MoveToInsertionPosition(LogicalDirection.Forward); if (!this.TextView.IsValid) { // We can not get the visual. Return TS_R_NOLAYOUT to the caller. throw new COMException(SR.Get(SRID.TextStore_TS_E_NOLAYOUT), UnsafeNativeMethods.TS_E_NOLAYOUT); } if (startIndex == endIndex) { Rect rectStart = startPointer.GetCharacterRect(LogicalDirection.Forward); milPointTopLeft = rectStart.TopLeft; milPointBottomRight = rectStart.BottomRight; } else { Rect rectBound = new Rect(Size.Empty); ITextPointer navigator = startPointer.CreatePointer(); endPointer = CreatePointerAtCharOffset(endIndex, LogicalDirection.Backward); endPointer.MoveToInsertionPosition(LogicalDirection.Backward); bool moved; do { // Compute the textSegment bounds line by line. TextSegment lineRange = this.TextView.GetLineRange(navigator); ITextPointer end; Rect lineRect; // Skip any BlockUIContainer or any other content that is not treated as a line by TextView. if (!lineRange.IsNull) { ITextPointer start = (lineRange.Start.CompareTo(startPointer) <= 0) ? startPointer : lineRange.Start; end = (lineRange.End.CompareTo(endPointer) >= 0) ? endPointer : lineRange.End; lineRect = GetLineBounds(start, end); moved = (navigator.MoveToLineBoundary(1) != 0) ? true : false; } else { lineRect = navigator.GetCharacterRect(LogicalDirection.Forward); moved = navigator.MoveToNextInsertionPosition(LogicalDirection.Forward); end = navigator; } if (lineRect.IsEmpty == false) { rectBound.Union(lineRect); } if (end.CompareTo(endPointer) == 0) { break; } } while (moved); // Invariant.Assert(rectBound.IsEmpty == false); milPointTopLeft = rectBound.TopLeft; milPointBottomRight = rectBound.BottomRight; } // Transform to root visual coordinates. transform = UiScope.TransformToAncestor(compositionTarget.RootVisual); // transform.TryTransform(milPointTopLeft, out milPointTopLeft); transform.TryTransform(milPointBottomRight, out milPointBottomRight); rect = TransformRootRectToScreenCoordinates(milPointTopLeft, milPointBottomRight, win32Window, source); }
private static UnsafeNativeMethods.RECT TransformRootRectToScreenCoordinates(Point milPointTopLeft, Point milPointBottomRight, IWin32Window win32Window, PresentationSource source) { UnsafeNativeMethods.RECT rect; NativeMethods.POINT clientPoint; CompositionTarget compositionTarget; rect = new UnsafeNativeMethods.RECT(); // Transform to device units. compositionTarget = source.CompositionTarget; milPointTopLeft = compositionTarget.TransformToDevice.Transform(milPointTopLeft); milPointBottomRight = compositionTarget.TransformToDevice.Transform(milPointBottomRight); IntPtr hwnd = IntPtr.Zero; new UIPermission(UIPermissionWindow.AllWindows).Assert(); // BlessedAssert try { hwnd = win32Window.Handle; } finally { CodeAccessPermission.RevertAssert(); } // Transform to screen coords. clientPoint = new NativeMethods.POINT(); UnsafeNativeMethods.ClientToScreen(new HandleRef(null, hwnd), /* ref by interop */ clientPoint); rect.left = (int)(clientPoint.x + milPointTopLeft.X); rect.right = (int)(clientPoint.x + milPointBottomRight.X); rect.top = (int)(clientPoint.y + milPointTopLeft.Y); rect.bottom = (int)(clientPoint.y + milPointBottomRight.Y); return rect; }
public void GetTextExt(int start, int end, out UnsafeNativeMethods.RECT rect, out bool clipped) { rect = new UnsafeNativeMethods.RECT(); clipped = false; }
public void GetScreenExt(out UnsafeNativeMethods.RECT rect) { rect = new UnsafeNativeMethods.RECT(); }
void UnsafeNativeMethods.ITextStoreACP.GetTextExt(int viewCookie, int startIndex, int endIndex, out UnsafeNativeMethods.RECT rect, out bool clipped) { PresentationSource source; IWin32Window win32Window; CompositionTarget compositionTarget; ITextView view; ITextPointer startPointer; ITextPointer endPointer; GeneralTransform transform; Point milPointTopLeft; Point milPointBottomRight; // We need to update the layout before getting rect. It could be dirty by SetText call of TIP. UiScope.UpdateLayout(); rect = new UnsafeNativeMethods.RECT(); clipped = false; GetVisualInfo(out source, out win32Window, out view); compositionTarget = source.CompositionTarget; // We use local coordinates. startPointer = CreatePointerAtCharOffset(startIndex, LogicalDirection.Forward); startPointer.MoveToInsertionPosition(LogicalDirection.Forward); if (!this.TextView.IsValid) { // We can not get the visual. Return TS_R_NOLAYOUT to the caller. throw new COMException(SR.Get(SRID.TextStore_TS_E_NOLAYOUT), UnsafeNativeMethods.TS_E_NOLAYOUT); } if (startIndex == endIndex) { Rect rectStart = startPointer.GetCharacterRect(LogicalDirection.Forward); milPointTopLeft = rectStart.TopLeft; milPointBottomRight = rectStart.BottomRight; } else { Rect rectBound = new Rect(Size.Empty); ITextPointer navigator = startPointer.CreatePointer(); endPointer = CreatePointerAtCharOffset(endIndex, LogicalDirection.Backward); endPointer.MoveToInsertionPosition(LogicalDirection.Backward); bool moved; do { // Compute the textSegment bounds line by line. TextSegment lineRange = this.TextView.GetLineRange(navigator); ITextPointer end; Rect lineRect; // Skip any BlockUIContainer or any other content that is not treated as a line by TextView. if (!lineRange.IsNull) { ITextPointer start = (lineRange.Start.CompareTo(startPointer) <= 0) ? startPointer : lineRange.Start; end = (lineRange.End.CompareTo(endPointer) >= 0) ? endPointer : lineRange.End; lineRect = GetLineBounds(start, end); moved = (navigator.MoveToLineBoundary(1) != 0) ? true : false; } else { lineRect = navigator.GetCharacterRect(LogicalDirection.Forward); moved = navigator.MoveToNextInsertionPosition(LogicalDirection.Forward); end = navigator; } if (lineRect.IsEmpty == false) { rectBound.Union(lineRect); } if (end.CompareTo(endPointer) == 0) { break; } } while (moved); // Invariant.Assert(rectBound.IsEmpty == false); milPointTopLeft = rectBound.TopLeft; milPointBottomRight = rectBound.BottomRight; } // Transform to root visual coordinates. transform = UiScope.TransformToAncestor(compositionTarget.RootVisual); // transform.TryTransform(milPointTopLeft, out milPointTopLeft); transform.TryTransform(milPointBottomRight, out milPointBottomRight); rect = TransformRootRectToScreenCoordinates(milPointTopLeft, milPointBottomRight, win32Window, source); }