WPF 中的高级文本格式设置






4.61/5 (15投票s)
本文档描述了 WPF 中的高级文本格式化。
引言
WPF 提供了几个控件来处理文本,例如 Label
、TextBlock
、TextBox
、RichTextBox
等。但所有这些控件提供的文本格式化功能都有限。WPF 还提供了另一个控件,称为 FormattedText
。此控件提供了广泛的文本格式化功能。特别是,当您希望将大尺寸文本显示为横幅时,可以使用 FormattedText
控件。它还可以用于在文本上播放动画和视频。
背景
通过将以下参数传递给其构造函数来创建 FormattedText
对象:
字符串
CultureInfo
FlowDirection
-
TypeFace
Brush
FormattedText text = new FormattedText("HELLO",
System.Globalization.CultureInfo.GetCultureInfo("en-US"),
FlowDirection.LeftToRight, new Typeface("LilyUPC"), 256, Brushes.Black);
使用 MaxTextWidth
和 MaxTextHeight
方法分别指定最大宽度和最大高度。
使用 SetForegroundBrush
方法使用画笔格式化文本。
通常,我们重写 Window 的 OnRender
方法来执行格式化并显示格式化的文本。Window 类的 OnRender
方法接收一个 DrawingContext
对象作为参数。DrawingContext
对象的 DrawText
方法用于在 Window 上绘制文本。
注意:为了使 OnRender
方法起作用,Window
元素的 Background
属性必须为“Transparent
”。
使用代码
以下代码可用于显示使用 LinearGradientBrush
格式化的文本。
protected override void OnRender(DrawingContext drawingContext)
{
FormattedText text = new FormattedText("AZIM",
System.Globalization.CultureInfo.GetCultureInfo("en-US"),
FlowDirection.LeftToRight, new Typeface("LilyUPC"), 256, Brushes.Black);
text.MaxTextWidth = 700;
text.MaxTextHeight = 400;
LinearGradientBrush brush = new LinearGradientBrush(); // Create a LinearGradientBrush
// Set GradientStops
brush.GradientStops.Add(new GradientStop(Colors.Red, 0.2));
brush.GradientStops.Add(new GradientStop(Colors.Green, 0.3));
brush.GradientStops.Add(new GradientStop(Colors.Blue, 0.5));
brush.GradientStops.Add(new GradientStop(Colors.Magenta, 0.7));
brush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.8));
brush.GradientStops.Add(new GradientStop(Colors.Cyan, 0.9));
text.SetForegroundBrush(brush, 0, 4); // Apply formatting to 4 chars starting from first char
drawingContext.DrawText(text, new Point(10, 0)); // Draw text on the Window
base.OnRender(drawingContext);
}
上述代码创建了一个 FormattedText
对象。然后,它创建了一个 LinearGradientBrush
并使用 FormattedText
对象的 SetForegroundBrush
方法来格式化文本。SetForegroundBrush
方法接受三个参数。第一个参数是画笔,第二个参数是起始字符的索引,第三个参数是要格式化的字符数。最后,它使用 DrawingContext
对象的 DrawText
方法在 Window
上绘制文本。
以上代码的输出如下
可以将动画应用于 LinearGradientBrush
并将其用作文本的背景。其 XAML 代码如下:
<Window x:Class="TextEffects.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent"
Title="Animated Text" Height="350" Width="525">
<Canvas>
<Rectangle Name="myrect" Width="350" Height="250">
<Rectangle.Fill>
<LinearGradientBrush x:Name="brush" StartPoint="0,0" EndPoint="1,1">
<GradientStop x:Name="stop1" Offset="0" Color="Red"/>
<GradientStop x:Name="stop2" Offset="0.5" Color="Green"/>
<GradientStop x:Name="stop3" Offset="1" Color="Blue"/>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<ColorAnimation Storyboard.TargetName="stop1"
Storyboard.TargetProperty="Color" From="Red"
To="Green" Duration="0:0:1" BeginTime="0:0:0"/>
<ColorAnimation Storyboard.TargetName="stop1"
Storyboard.TargetProperty="Color" From="Green"
To="Blue" Duration="0:0:1" BeginTime="0:0:0.5"/>
<ColorAnimation Storyboard.TargetName="stop1"
Storyboard.TargetProperty="Color" From="Blue"
To="Red" Duration="0:0:1" BeginTime="0:0:1"/>
<ColorAnimation Storyboard.TargetName="stop2"
Storyboard.TargetProperty="Color" From="Green"
To="Blue" Duration="0:0:1" BeginTime="0:0:0"/>
<ColorAnimation Storyboard.TargetName="stop2"
Storyboard.TargetProperty="Color" From="Blue"
To="Red" Duration="0:0:1" BeginTime="0:0:0.5"/>
<ColorAnimation Storyboard.TargetName="stop2"
Storyboard.TargetProperty="Color" From="Red"
To="Green" Duration="0:0:1" BeginTime="0:0:1"/>
<ColorAnimation Storyboard.TargetName="stop3"
Storyboard.TargetProperty="Color" From="Blue"
To="Red" Duration="0:0:1" BeginTime="0:0:0"/>
<ColorAnimation Storyboard.TargetName="stop3"
Storyboard.TargetProperty="Color" From="Red"
To="Green" Duration="0:0:1" BeginTime="0:0:0.5"/>
<ColorAnimation Storyboard.TargetName="stop3"
Storyboard.TargetProperty="Color" From="Green"
To="Blue" Duration="0:0:1" BeginTime="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</Canvas>
</Window>
代码如下:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
protected override void OnRender(DrawingContext drawingContext)
{
FormattedText text = new FormattedText
("AZIM", System.Globalization.CultureInfo.GetCultureInfo("en-US"),
FlowDirection.LeftToRight, new Typeface("LilyUPC"), 256, Brushes.Black);
text.MaxTextWidth = 700;
text.MaxTextHeight = 400;
text.SetForegroundBrush(brush, 0, 4);
drawingContext.DrawText(text, new Point(10, 0));
myrect.Visibility = Visibility.Hidden; // Hide the Rectangle
base.OnRender(drawingContext);
}
}
这会产生以下输出:
可以使用图像作为文本的背景。以下代码可用于实现相同的功能:
protected override void OnRender(DrawingContext drawingContext)
{
FormattedText text = new FormattedText("AZIM",
System.Globalization.CultureInfo.GetCultureInfo("en-US"),
FlowDirection.LeftToRight, new Typeface("LilyUPC"), 256, Brushes.Black);
text.MaxTextWidth = 700;
text.MaxTextHeight = 400;
ImageBrush brush = new ImageBrush(); // Create an ImageBrush
brush.ImageSource = new BitmapImage(new Uri("flower.jpg", UriKind.Relative)); // Set the image source
text.SetForegroundBrush(brush, 0, 4);
drawingContext.DrawText(text, new Point(10, 200));
base.OnRender(drawingContext);
}
其输出如下:
如果您想在文本表面播放视频,可以使用 VideoDrawing
对象与 DrawingBrush
对象结合使用,如下所示:
protected override void OnRender(DrawingContext drawingContext)
{
FormattedText text =
new FormattedText("AZIM", System.Globalization.CultureInfo.GetCultureInfo("en-US"),
FlowDirection.LeftToRight, new Typeface("LilyUPC"), 256, Brushes.Black);
text.MaxTextWidth = 700;
text.MaxTextHeight = 400;
MediaTimeline timeline = new MediaTimeline(new Uri("airplane.mpg", UriKind.Relative)); // Create MediaTimeLine
timeline.RepeatBehavior = RepeatBehavior.Forever;
MediaClock clock = timeline.CreateClock();
MediaPlayer player = new MediaPlayer();
player.Clock = clock;
VideoDrawing drawing = new VideoDrawing(); // Create VideoDrawing
drawing.Rect = new Rect(0, 0, 300, 200);
drawing.Player = player; // Set player
DrawingBrush brush = new DrawingBrush(drawing); // Create DrawingBrush based on the VideoDrawing
text.SetForegroundBrush(brush, 0, 4);
drawingContext.DrawText(text, new Point(100, 0));
}
此代码的输出如下:
可以将 FormattedText
对象转换为 PathGeometry
对象。在以下示例中,创建了一个椭圆,该椭圆遵循文本的路径。
以下是 XAML 代码:
<Window x:Class="TextEffects.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent"
Title="PathGeometry Animation" Height="350" Width="525">
<Canvas>
<Ellipse Canvas.Top="0" Canvas.Left="0" Width="50" Height="50">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.5,0.5"
Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Color="Transparent" Offset="0.25" />
<GradientStop Color="Red" Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Ellipse.Fill>
<Ellipse.RenderTransform>
<MatrixTransform />
</Ellipse.RenderTransform>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard x:Name="storyboard">
<MatrixAnimationUsingPath x:Name="matrixAnimation"
Duration="0:00:40" RepeatBehavior="Forever"
Storyboard.TargetProperty="RenderTransform.Matrix" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
</Canvas>
</Window>
以下是代码:
protected override void OnRender(DrawingContext drawingContext)
{
FormattedText text =
new FormattedText("AZIM",
System.Globalization.CultureInfo.GetCultureInfo("en-US"),
FlowDirection.LeftToRight, new Typeface("LilyUPC"), 256, Brushes.Black);
text.MaxTextWidth = 700;
text.MaxTextHeight = 400;
ImageBrush brush = new ImageBrush();
brush.ImageSource = new BitmapImage(new Uri("flower.jpg", UriKind.Relative));
text.SetForegroundBrush(brush, 0, 4);
drawingContext.DrawText(text, new Point(10, 0));
Geometry geometry = text.BuildGeometry(new System.Windows.Point(-20, -20)); // Convert text to Geometry object
PathGeometry pathGeometry = geometry.GetFlattenedPathGeometry(); // Create a PathGeometry based on the Geometry object
matrixAnimation.PathGeometry = pathGeometry; // Set PathGeometry for the animation
base.OnRender(drawingContext);
}
以下是上述代码的输出:
关注点
我希望读者觉得上述讨论有趣且有用。