在WPF中渲染文本,使其完全适合给定的矩形

时间:2011-01-21 17:20:27

标签: c# wpf .net-3.5

我需要在WPF Canvas上显示单词,使其完全适合预定义的框。

一个框通常包含一行文字,从一个字母到几个单词。

盒子内的文字必须尽可能大,即:触摸盒子的所有边框(除非由于异常盒子/高度比而导致文本失真太多)。

我找不到根据文字内容计算合适的字体高度,缩放比例和偏移量的好方法。

无法更改原始文本宽高比的第一个解决方案已经非常好了!

我想使用TextBlock元素,但其他任何有效的东西都应该没问题。

3 个答案:

答案 0 :(得分:5)

正如Robery Levy所说,你可以使用Viewbox来达到这个目的。然而,文本本身不会延伸,因此根据您的文本(正如您所注意到的那样),您仍然会在零个或多个边上有一些“边距”。要解决此问题,您可以创建一个自定义控件,从Geometry构建FormattedText,然后在OnRender中使用DrawGeometry绘制它。您会注意到文本的质量如何通过更大的FontSize得到改善。一个非常小的文本(例如FontSize="10")在大Viewbox中看起来不会非常清晰,因此您需要进行一些实验

enter image description here

一些示例Xaml

<Canvas Background="Black">
    <Viewbox Canvas.Left="10" Canvas.Top="10"
             Stretch="Fill" Width="200" Height="50">
        <Border Background="Red">
            <local:StretchText Text="Text" Foreground="Green" FontSize="100"/>
        </Border>
    </Viewbox>
    <Viewbox Canvas.Left="230" Canvas.Top="10"
             Stretch="Fill" Width="200" Height="50">
        <Border Background="Red">
            <local:StretchText Text="B" Foreground="Green" FontSize="500"/>
        </Border>
    </Viewbox>
</Canvas>

StretchText.cs

public class StretchText : Control
{
    protected override void OnRender(DrawingContext drawingContext)
    {
        FormattedText formattedText = new FormattedText(
            Text,
            CultureInfo.GetCultureInfo("en-us"),
            FlowDirection.LeftToRight,
            new Typeface(FontFamily, FontStyle, FontWeight, FontStretches.Normal),
            FontSize,
            Foreground);

        Geometry textGeometry = formattedText.BuildGeometry(new Point(0, 0));
        this.MinWidth = textGeometry.Bounds.Width;
        this.MinHeight = textGeometry.Bounds.Height;

        TranslateTransform translateTransform = new TranslateTransform();
        translateTransform.X = -textGeometry.Bounds.Left;
        translateTransform.Y = -textGeometry.Bounds.Top;
        drawingContext.PushTransform(translateTransform);
        drawingContext.DrawGeometry(Foreground, new Pen(Foreground, 1.0), textGeometry);
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text",
        typeof(string),
        typeof(StretchText),
        new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender));
}

答案 1 :(得分:4)

答案 2 :(得分:0)

你可以查看Charles Petzold的文章“Render Text on a Path with WPF”。不幸的是,由于MSDN网站出现问题,我无法刷新目前关于主题的知识,但他描述了如何在路径中缩放文本。