1. 程式人生 > 其它 >[WPF] 如何實現文字描邊

[WPF] 如何實現文字描邊

1. 前言

WPF 的 TextBlock 提供了大部分常用的文字修飾方法,在日常使用中基本夠用。如果需要更豐富的表現方式,WPF 也提供了其它用起來複雜一些的工具去實現這些需求。例如這篇文章介紹的文字描邊,就有幾種方法可以在 WPF 中呈現。這篇文章將簡單介紹這實現文字描邊的方法。

2. 將文字轉換位 Geometry

實現文字描邊的關鍵是使用 FormattedText 將文字轉換為 Geometry,然後通過其它技術將 Geometry 加上邊框再畫出來。

在 WPF 中,Geometry 及它的派生類(EllipseGeometry、LineGeometry、PathGeometry、RectangleGeometry 等)用於描述 2D 形狀的集合圖形。而 FormattedText 的 BuildGeometry

函式可以將文字轉換為 GeometryGroup(表示由其他 Geometry 物件組成的複合幾何圖形),程式碼如下:

private Geometry CreateTextGeometry()
{
    // Create the formatted text based on the properties set.
    FormattedText formattedText = new FormattedText(
        Text,
        CultureInfo.CurrentCulture,
        FlowDirection.LeftToRight,
        new Typeface(
            FontFamily,
            FontStyle,
            FontWeight,
            FontStretch),
        FontSize,
        System.Windows.Media.Brushes.Black,// This brush does not matter since we use the geometry of the text.
        100);
    // Build the geometry object that represents the text.

    return formattedText.BuildGeometry(new Point(0, 0));
}

得到 Geometry 後,有兩種方式將它畫出來。

3. 使用 DrawingContext

WPF 中的 DrawingContext 是一個基礎的繪圖物件,用於繪製各種圖形,它的一個最簡單的使用方式是過載 UIElement 的 OnRender 方法,在這個方法中繪製 UIElement 的UI:

// Override the OnRender call to add a Background and Border to the OffSetPanel
protected override void OnRender(DrawingContext dc)
{
    SolidColorBrush mySolidColorBrush  = new SolidColorBrush();
    mySolidColorBrush.Color = Colors.LimeGreen;
    Pen myPen = new Pen(Brushes.Blue, 10);
    Rect myRect = new Rect(0, 0, 500, 500);
    dc.DrawRectangle(mySolidColorBrush, myPen, myRect);
}

上面的示例程式碼用 DrawingContext 畫了一個500 * 500 的正方形。除了正方形,DrawingContext 還提供了 DrawEllipse、DrawImage、DrawLine 等函式,用於畫圓形、影象、線條等,也可以用 DrawText 函式畫出文字。不過比起直接用 DrawText,DrawGeometry 會是一個更好的選擇,因為它可以畫出文字的邊框。在上面的程式碼中我們已經將文字轉為一個 Geometry,接下來直接呼叫 DrawGeometry 並加上邊框:

protected override void OnRender(DrawingContext drawingContext)
{
    base.OnRender(drawingContext);
    var geometry = CreateTextGeometry();
    // Draw the outline based on the properties that are set.
    drawingContext.DrawGeometry(Foreground, new Pen(Stroke, StrokeThickness), geometry);
}

通過 Stroke, StrokeThickness 控制可以控制文字邊框的顏色和粗細。

4. 自定義 Shape

前面介紹的方法來自微軟的 示例文件,不過既然都拿到文字的 Geometry 了,直接做成自定義的 Shape 不更好嗎,Shape 還可以很簡單地玩更多花樣更多動畫。用自定義 Shape 做空心文字的程式碼大致如下(省略了一些文字的自定義依賴屬性):

public class TextShape : Shape
{
    private double _height;

    private double _width;

    private Geometry _textGeometry;

    [Localizability(LocalizationCategory.Text)]
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    protected sealed override Geometry DefiningGeometry
    {
        get
        {
            return _textGeometry ?? Geometry.Empty;
        }
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        this.RealizeGeometry();
        return new Size(Math.Min(availableSize.Width, _width), Math.Min(availableSize.Height, _height));
    }

    private void RealizeGeometry()
    {
        var formattedText = new FormattedText(
                                   Text,
                                   CultureInfo.CurrentCulture,
                                   FlowDirection.LeftToRight,
                                   new Typeface(FontFamily, FontStyle, FontWeight, FontStretch), FontSize, Brushes.Black, 100);

        _height = formattedText.Height;
        _width = formattedText.Width;
        _textGeometry = formattedText.BuildGeometry(new Point());
    }
}

得到一個由文字轉換成的 Shape 後除了可以實現文字描邊,還可以玩很多動畫,例如下面這種:

5. 最後

這篇文章介紹瞭如何實現文字描邊。除了文字描邊,文章裡介紹的文字轉換成 Shape 還有很多中玩法,下一篇文章將簡單試試其中一些。

另外,文字描邊的方案還可以參考部落格園的這篇部落格,將文字字串用GDI+生成Bitmap,然後轉成BitmapImage:

WPF 文字描邊+外發光效果實現

6. 參考

Geometry 概述 - WPF .NET Framework

GeometryGroup 類 (System.Windows.Media)

FormattedText 類 (System.Windows.Media)

DrawingContext 類 (System.Windows.Media)

UIElement.OnRender(DrawingContext) 方法 (System.Windows)

7. 原始碼

https://github.com/DinoChan/wpf_design_and_animation_lab