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

[WPF] 如何实现文字描边的更多相关文章

  1. WPF文字描边的解决方法(二)——支持文字竖排和字符间距调整

    原文:WPF文字描边的解决方法(二)--支持文字竖排和字符间距调整 自前天格式化文本效果出来后,今天又添加文本竖排和调整字符间距的功能.另外,由于上次仓促,没来得及做有些功能的设计时支持,这次也调整好 ...

  2. WPF文字描边的解决方法

    原文:WPF文字描边的解决方法  由于项目原因,今天研究了一下午WPF的文字描边,网上这方面的资料奇少,搞了半天才发现强大的WPF原来不直接支持文字描边啊.最后求助于MSDN,找到了方案,和大家分 ...

  3. 用CSS3实现文字描边

    CSS3作为新兴的前端技术可以实现很多复杂变化的效果,比如文字描边. 这里主要用到text-shadow属性,顾名思义就是为文字加上阴影效果.例: text-shadow:10px 5px 2px # ...

  4. cocos2d-x 利用CCLabelTTF制作文字描边与阴影效果的实现方法

    // // myttf.h// // Created by 王天宇 on 14-6-12. // // #ifndef ____SLG__myttf__ #define ____SLG__myttf_ ...

  5. CSS3文字描边 CSS3字体外部描边

    给需要实现文字描边的元素添加如下CSS3的属性 text-shadow:#000 1px 0 0,#000 0 1px 0,#000 -1px 0 0,#000 0 -1px 0; -webkit-t ...

  6. 常用CSS3效果:用text-shadow做CSS3 文字描边

    思路: 利用CSS3的text-shadow属性,对文字的四个边均用阴影. 最终效果: 单纯的为了实现效果.未作任何美化. 实现代码: HTML: <div>文字描边效果</div& ...

  7. ps怎么给文字描边

    在设计的时候,单一的文字,往往对人没有多少的吸引力,这就需要我们在文字上加一些文字特效,比如说外发光,描边,投影,等等.在这里我们详细的介绍一下文字的输入,和文字描边的怎么增加,删除的经验.(这些方法 ...

  8. Android TextView文字描边的实现!!

    Android开发:文字描边 转自:http://www.oschina.net/code/snippet_586849_37287 1. [代码][Java]代码 1 2 3 4 5 6 7 8 9 ...

  9. TextView文字描边实现

    TextView文字描边实现 需求描述 文字显示在图片的上面,图片的内容是不确定了,为了防止文字与图片的颜色相近导致用户看不到或者看不清文字的问题,所以显示文字描边,避免问题. 实现 实现思想 使用T ...

随机推荐

  1. Xcode 插件推荐

    1. Alcatraz(建议安装,以下插件都可以在Alcatraz下载安装) 使用Alcatraz来下载管理Xcode插件, 2.下载安装注释插件VVDocumenter-Xcode. 3.使用代码对 ...

  2. PHP面试常考内容之面向对象(1)

    PHP中面向对象常考的知识点有以下几点,我将会从以下几点进行详细介绍说明,帮助你更好的应对PHP面试常考的面向对象相关的知识点和考题. 整个面向对象文章的结构涉及的内容模块有: 一.面向对象与面向过程 ...

  3. Solution -「多校联训」光影交错

    \(\mathcal{Description}\)   Link.   一个游戏包含若干次卡牌抽取,每次以 \(p_l\) 的概率得到 \(+1\),\(p_d\) 的概率得到 \(-1\),否则得到 ...

  4. Idea个人配置

    Intellij IDEA配置 1. 优化导包配置 2. 取消tab页单行显示 多行显示更多的文件,方便查看. 3. 双斜杠注释改成紧跟代码头 4. 选中复制整行 原本只会复制你选中的代码,改完配置后 ...

  5. [入门到吐槽系列] Webix 10分钟入门 一 管理后台制作

    前言 本人是服务端程序员,同时需要兼职前端开发.常用的就是原生态的HTML.Javascript,也用过ExtJS.Layui.可是ExtJS变公司后非常难用.Layui上手还行,用过一段时间,会觉得 ...

  6. 我们一起来学Shell - shell的数组

    文章目录 什么是数组 数组中常用变量 数组的定义 小括号定义数组变量 小括号加键值对定义数组变量 分别定义数组变量 动态地定义数组变量 数组赋值的切片 遍历数组 关联数组 我们一起来学Shell - ...

  7. 上架打包错误:error itms-90086

    这是一个很纠结的错误 大家第一反应肯定是 赶紧去看看 位数是否设置  然后发现没有问题  就开始懵逼了 (比如我) 然而无意看到了一个人写的简书 这个人在 Overflow 找到了一个答案 比如你选择 ...

  8. kali linux 静态地址和动态地址的设置

    在文件系统里找到/etc/network下的interfaces文件,打开后可以看到eth0为dhcp,将其修改为# This file describes the network interface ...

  9. 在 CentOS 或 RHEL 系统上检查可用的安全更新的方法

    当你更新系统时,根据你所在公司的安全策略,有时候可能只需要打上与安全相关的补丁.大多数情况下,这应该是出于程序兼容性方面的考量.那该怎样实践呢?有没有办法让 yum 只安装安全补丁呢? 答案是肯定的, ...

  10. 【windows 操作系统】线程句柄HANDLE与线程ID的关系

    什么是句柄 句柄是一种指向指针的指针.我们知道,所谓指针是一种内存地址.应用程序启动后,组成这个程序的各对象是住留在内存的.如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访 ...