【发布时间】:2011-01-21 17:20:27
【问题描述】:
我需要在 WPF 画布上以完全适合预定义框的方式显示单词。
一个框通常包含一行文本,从一个字母到几个单词。
框内的文字必须尽可能大,即:触及框的所有边框(除非可能由于框宽/高比异常而导致文本失真过多)。
我找不到根据文本内容计算适当字体高度、缩放和偏移的好方法。
原始文本宽高比不能改变的第一个解决方案已经很不错了!
我想使用 TextBlock 元素,但其他任何可行的都应该没问题。
【问题讨论】:
我需要在 WPF 画布上以完全适合预定义框的方式显示单词。
一个框通常包含一行文本,从一个字母到几个单词。
框内的文字必须尽可能大,即:触及框的所有边框(除非可能由于框宽/高比异常而导致文本失真过多)。
我找不到根据文本内容计算适当字体高度、缩放和偏移的好方法。
原始文本宽高比不能改变的第一个解决方案已经很不错了!
我想使用 TextBlock 元素,但其他任何可行的都应该没问题。
【问题讨论】:
正如 Robery Levy 的回答所说,您可以使用 Viewbox 来实现此目的。但是,文本本身不会拉伸,因此根据您的文本(如您所见),您仍然会在零个或多个边上保留一些“边距”。要解决此问题,您可以创建一个自定义控件,该控件从 FormattedText 构建一个 Geometry,然后在 OnRender 中使用 DrawGeometry 绘制它。您会注意到文本质量如何随着FontSize 的增大而提高。一个非常小的文本(例如FontSize="10")在大的Viewbox 中看起来不会很清晰,所以你必须尝试一下
一些示例 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));
}
【讨论】:
Grid 中同时尝试了 10 个左右的StretchText,然后快速调整了Window 的大小。我似乎工作得很好,但 DrawGeometry 以非常慢而闻名
将 TextBlock 放入 Viewbox:http://msdn.microsoft.com/en-us/library/system.windows.controls.viewbox.aspx
【讨论】:
您可以查看 Charles Petzold 的文章“Render Text on a Path with WPF”。不幸的是,由于 MSDN 网站出现问题,我目前无法刷新有关主题的知识,但他描述了如何在路径内缩放文本。
【讨论】: