65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中的高级文本格式设置

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.61/5 (15投票s)

2012年7月22日

CPOL

2分钟阅读

viewsIcon

58118

本文档描述了 WPF 中的高级文本格式化。

引言

WPF 提供了几个控件来处理文本,例如 LabelTextBlockTextBoxRichTextBox 等。但所有这些控件提供的文本格式化功能都有限。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);

使用 MaxTextWidthMaxTextHeight 方法分别指定最大宽度和最大高度。

使用 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);
}

以下是上述代码的输出:

关注点

我希望读者觉得上述讨论有趣且有用。

© . All rights reserved.