【问题标题】:WPF C# get the size and position of inline element of a TextBlockWPF C#获取TextBlock内联元素的大小和位置
【发布时间】:2018-11-28 15:15:44
【问题描述】:

我使用此示例 (https://siderite.dev/blog/how-to-draw-outlined-text-in-wpf-and.html) 为 TextBlock 中的文本添加轮廓。但是这个例子不支持内联。

我尝试添加此功能以修改 OnRender,并迭代 Inlines 集合以为每个 Inline 块构建一个 Geometry。问题是我需要获取 TextBlock 中内联块的位置和大小,而不是 TextBlock 中整个文本的位置和大小。

这是我修改的源代码。

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();
    }
}

我需要更改从 TextBlock 获取大小和位置的部分,以获取 Inline 块的大小和位置,但我没有看到任何可以获取该信息的 Inline 属性。有什么想法吗?

【问题讨论】:

    标签: c# wpf textblock inlines


    【解决方案1】:

    我找到了一种获得职位的方法:

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

    然后我以这种方式更改了构建几何的线:

    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));
    

    我仍然对换行有一些问题,因为当文本被换行时,几何图形只在第一行构建。

    【讨论】:

    • 这需要更新您的问题,而不是作为答案发布。它会被否决并可能被删除。
    • @MichaelPuckettII 这个回答我的问题:如何获得内联的位置? inline.ElementStart.GetCharacterRect(LogicalDirection.Forward) 我仍然有包装文本的问题,但这超出了这个问题的目标,我想我会为此提出一个新问题。
    • 复制那个;为防止混淆,我可能会删除最后一个提示您仍有问题的花絮。我相信我理解正确,因为您确实回答了这个问题,所以额外的问题可能会让它无人回答(这是我最初假设的)
    • 好吧,我已经添加了最后一条信息,因为如果有人只是在寻找我的原始问题,他们会得到答案,但如果有人试图用概述的文本做同样的事情,那么他会被警告说这段代码仍然有这个问题。但我明白你的意思,现在我不确定我是否必须离开它。可能我稍后会澄清它,但由于我仍在解决这个问题,如果我有更好的消息,我会在稍后更新我的答案。无论如何感谢您的建议。
    【解决方案2】:

    试试这个

    Rect rect = Rect.Union(inline.ElementStart.GetCharacterRect(LogicalDirection.Forward),                                                
                           inline.ElementEnd.GetCharacterRect(LogicalDirection.Backward));
    

    感谢

    【讨论】:

      【解决方案3】:

      使用 TextBlock 的 LineHeight 属性:

      formattedText.LineHeight = _textBlock.LineHeight;
      

      因此您可以通过编程方式修改 LineHeight 值。

      【讨论】:

      • 感谢您的回答,但问题是要获取内联块的大小和位置,而不仅仅是 LineHeight。每个 Inline 块在 TextBlock 内都有不同的大小和位置。
      • 尝试将它们分成不同的变量,可能会有所不同。
      猜你喜欢
      • 1970-01-01
      • 2013-01-08
      • 2019-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多