[WPF] 如何實現文字描邊
1. 前言
WPF 的 TextBlock 提供了大部分常用的文字修飾方法,在日常使用中基本夠用。如果需要更豐富的表現方式,WPF 也提供了其它用起來複雜一些的工具去實現這些需求。例如這篇文章介紹的文字描邊,就有幾種方法可以在 WPF 中呈現。這篇文章將簡單介紹這實現文字描邊的方法。
2. 將文字轉換位 Geometry
實現文字描邊的關鍵是使用 FormattedText 將文字轉換為 Geometry,然後通過其它技術將 Geometry 加上邊框再畫出來。
在 WPF 中,Geometry 及它的派生類(EllipseGeometry、LineGeometry、PathGeometry、RectangleGeometry 等)用於描述 2D 形狀的集合圖形。而 FormattedText 的 BuildGeometry
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:
6. 參考
Geometry 概述 - WPF .NET Framework
GeometryGroup 類 (System.Windows.Media)
FormattedText 類 (System.Windows.Media)
DrawingContext 類 (System.Windows.Media)
UIElement.OnRender(DrawingContext) 方法 (System.Windows)