Created
March 16, 2026 13:57
-
-
Save cnbluefire/d444e62b8f8723a7a7d573c2530dcf96 to your computer and use it in GitHub Desktop.
WinUI3 get TextBlock character bounding box.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public static class TextBlockExtensions | |
| { | |
| // https://github.com/microsoft/microsoft-ui-xaml/blob/main/src/dxaml/xcp/core/text/TextBlock/TextBlockView.cpp#L606 | |
| public static TextPointer GetAdjustedPosition(this TextBlock textBlock, int charIndex) | |
| { | |
| const int PlaceHolderPositionsForInlines = 2; | |
| var contentLength = textBlock.Text.Length + 2 * PlaceHolderPositionsForInlines; | |
| int charCount = charIndex; | |
| int adjustedPosition = 0; | |
| // Correct out of bound indexes to valid ones | |
| if (charIndex < 0) | |
| { | |
| adjustedPosition = PlaceHolderPositionsForInlines; | |
| } | |
| else if (charIndex >= (contentLength - (int)PlaceHolderPositionsForInlines)) | |
| { | |
| adjustedPosition = contentLength - (int)PlaceHolderPositionsForInlines; | |
| } | |
| else | |
| { | |
| adjustedPosition = charIndex + PlaceHolderPositionsForInlines; | |
| System.Diagnostics.Debug.Assert(adjustedPosition <= (int)contentLength - (int)PlaceHolderPositionsForInlines); | |
| } | |
| return textBlock.ContentStart.GetPositionAtOffset(adjustedPosition, LogicalDirection.Forward); | |
| } | |
| public static TextBlockCharacterBoundingBox GetElementBoundingBox(this TextBlock textBlock, int charIndex) | |
| { | |
| var text = textBlock.Text; | |
| ArgumentOutOfRangeException.ThrowIfLessThan(charIndex, 0); | |
| ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(charIndex, text.Length); | |
| var pointer = GetAdjustedPosition(textBlock, charIndex); | |
| var nextPointer = pointer.GetPositionAtOffset(1, LogicalDirection.Forward); | |
| var rect1 = pointer.GetCharacterRect(LogicalDirection.Forward); | |
| var rect2 = nextPointer.GetCharacterRect(LogicalDirection.Backward); | |
| var ch = text[charIndex]; | |
| var p1x = Math.Min(rect1.X, rect2.X); | |
| var p1y = Math.Min(rect1.Y, rect2.Y); | |
| var p2x = Math.Max(rect1.X, rect2.X); | |
| var p2y = Math.Max(rect1.Y + rect1.Height, rect2.Y + rect2.Height); | |
| var rect = new Rect(new Point(p1x, p1y), new Point(p2x, p2y)); | |
| return new TextBlockCharacterBoundingBox(charIndex, ch, rect); | |
| } | |
| public record struct TextBlockCharacterBoundingBox(int CharacterIndex, char Character, Rect BoundingBox); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment