WPF C# get the size and position of inline element of a TextBlock

依然范特西╮ 提交于 2019-12-24 11:23:28

问题


I use this example ( https://siderite.dev/blog/how-to-draw-outlined-text-in-wpf-and.html ) for add outline to a text in a TextBlock. However this example don't support Inlines.

I try to add this ability modifying the OnRender and I iterate the Inlines collection to build a Geometry for each Inline block. The problem is that I need to get the position and size of the inline block in the TextBlock instead of those of the whole text in the TextBlock.

This is the source code that I have modified.

protected override void OnRender(DrawingContext drawingContext)
{
    ensureTextBlock();
    base.OnRender(drawingContext);

    foreach (Inline inline in _textBlock.Inlines)
    {
        var textRange = new TextRange(inline.ContentStart, inline.ContentEnd);
        var formattedText = new FormattedText(
            textRange.Text,
            CultureInfo.CurrentUICulture,
            inline.FlowDirection,
            new Typeface(inline.FontFamily, inline.FontStyle, inline.FontWeight, inline.FontStretch),
            inline.FontSize, System.Windows.Media.Brushes.Black // This brush does not matter since we use the geometry of the text.
        );
        formattedText.SetTextDecorations(inline.TextDecorations);


        //*****************************************************************
        //This part get the size and position of the TextBlock
        // Instead I need to find a way to get the size and position of the Inline block

        //formattedText.TextAlignment = _textBlock.TextAlignment;
        //formattedText.Trimming = _textBlock.TextTrimming;

        formattedText.LineHeight = _textBlock.LineHeight;
        formattedText.MaxTextWidth = _textBlock.ActualWidth - _textBlock.Padding.Left - _textBlock.Padding.Right;
        formattedText.MaxTextHeight = _textBlock.ActualHeight - _textBlock.Padding.Top;// - _textBlock.Padding.Bottom;
        while (formattedText.Extent == double.NegativeInfinity)
        {
            formattedText.MaxTextHeight++;
        }

        // Build the geometry object that represents the text.
        var _textGeometry = formattedText.BuildGeometry(new System.Windows.Point(_textBlock.Padding.Left, _textBlock.Padding.Top));

        //*****************************************************************


        var textPen = new System.Windows.Media.Pen(Stroke, StrokeThickness * 2)
        {
            DashCap = PenLineCap.Round,
            EndLineCap = PenLineCap.Round,
            LineJoin = PenLineJoin.Round,
            StartLineCap = PenLineCap.Round
        };

        var boundsGeo = new RectangleGeometry(new Rect(0, 0, ActualWidth, ActualHeight));

        _clipGeometry = Geometry.Combine(boundsGeo, _textGeometry, GeometryCombineMode.Exclude, null);
        drawingContext.PushClip(_clipGeometry);
        drawingContext.DrawGeometry(System.Windows.Media.Brushes.Transparent, textPen, _textGeometry);
        drawingContext.Pop();
    }
}

I need to change the part that get the size and position from the TextBlock in order to get the size and position of the Inline block, but I don't see any property of Inline that can get that information. Any idea?


回答1:


I have found a way to get the position with:

inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Left
inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Top

Then I changed the line that build the geometry in this way:

double posLeft = inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Left;
double posTop = inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Top;

var _textGeometry = formattedText.BuildGeometry(new System.Windows.Point(posLeft, posTop));

I still have some problem with wrap because when the text is wrapped the Geometry is built only in the first line.




回答2:


Use the LineHeight property of the TextBlock:

formattedText.LineHeight = _textBlock.LineHeight;

So you can modify the LineHeight value programmatically.



来源:https://stackoverflow.com/questions/53522632/wpf-c-sharp-get-the-size-and-position-of-inline-element-of-a-textblock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!