首先创建一个自定义控件,继承自FrameworkElement,“Generic.xaml”中可以不添加样式。

  要自定义空心文字,要用到绘制格式化文本FormattedText类。FormattedText对象提供的文本格式设置功能比WPF提供的已有文本控件提供的相应功能更为强大。调用FormattedText构造函数,可以传入相应的参数,得到我们想要的文本样式。使用 MaxTextWidth 属性可以将文本约束为特定宽度。 文本将自动换行,以避免超过指定宽度。 使用 MaxTextHeight 属性可以将文本约束为特定高度。 超过指定高度的文本将显示一个省略号“…”。

  接下来重写OnRender方法,在方法体中调用DrawingContext对象的DrawGeometry方法即可完成文本的绘制工作。

     public class OutlinedText : FrameworkElement, IAddChild
{
/// <summary>
/// 静态构造函数
/// </summary>
static OutlinedText()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(OutlinedText), new FrameworkPropertyMetadata(typeof(OutlinedText)));
} #region Private Fields /// <summary>
/// 文字几何形状
/// </summary>
private Geometry m_TextGeometry; #endregion #region Private Methods /// <summary>
/// 当依赖项属性改变文字无效时,创建新的空心文字对象来显示。
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
private static void OnOutlineTextInvalidated(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (Convert.ToString(e.NewValue) != Convert.ToString(e.OldValue))
{
((OutlinedText)d).CreateText();
}
} #endregion #region FrameworkElement Overrides /// <summary>
/// 重写绘制文字的方法。
/// </summary>
/// <param name="drawingContext">空心文字控件的绘制上下文。</param>
protected override void OnRender(DrawingContext drawingContext)
{
//CreateText();
// 基于设置的属性绘制空心文字控件。
drawingContext.DrawGeometry(Fill, new Pen(Stroke, StrokeThickness), m_TextGeometry);
} /// <summary>
/// 基于格式化文字创建文字的几何轮廓。
/// </summary>
public void CreateText()
{
FontStyle fontStyle = FontStyles.Normal;
FontWeight fontWeight = FontWeights.Medium;
if (Bold == true)
fontWeight = FontWeights.Bold;
if (Italic == true)
fontStyle = FontStyles.Italic;
// 基于设置的属性集创建格式化的文字。
FormattedText formattedText = new FormattedText(
Text, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight,
new Typeface(Font, fontStyle, fontWeight, FontStretches.Normal),
FontSize, Brushes.Black);
formattedText.MaxTextWidth = this.MaxTextWidth;
formattedText.MaxTextHeight = this.MaxTextHeight;
// 创建表示文字的几何对象。
m_TextGeometry = formattedText.BuildGeometry(new Point(, ));
// 基于格式化文字的大小设置空心文字的大小。
this.MinWidth = formattedText.Width;
this.MinHeight = formattedText.Height;
} #endregion #region DependencyProperties /// <summary>
/// 指定将文本约束为特定宽度
/// </summary>
public double MaxTextWidth
{
get { return (double)GetValue(MaxTextWidthProperty); }
set { SetValue(MaxTextWidthProperty, value); }
}
/// <summary>
/// 指定将文本约束为特定宽度依赖属性
/// </summary>
public static readonly DependencyProperty MaxTextWidthProperty =
DependencyProperty.Register("MaxTextWidth", typeof(double), typeof(OutlinedText),
new FrameworkPropertyMetadata(1000.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定将文本约束为特定高度
/// </summary>
public double MaxTextHeight
{
get { return (double)GetValue(MaxTextHeightProperty); }
set { SetValue(MaxTextHeightProperty, value); }
}
/// <summary>
/// 指定将文本约束为特定高度依赖属性
/// </summary>
public static readonly DependencyProperty MaxTextHeightProperty =
DependencyProperty.Register("MaxTextHeight", typeof(double), typeof(OutlinedText),
new FrameworkPropertyMetadata(1000.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定字体是否加粗。
/// </summary>
public bool Bold
{
get { return (bool)GetValue(BoldProperty); }
set { SetValue(BoldProperty, value); }
}
/// <summary>
/// 指定字体是否加粗依赖属性。
/// </summary>
public static readonly DependencyProperty BoldProperty = DependencyProperty.Register(
"Bold", typeof(bool), typeof(OutlinedText),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定填充字体的画刷颜色。
/// </summary>
///
public Brush Fill
{
get { return (Brush)GetValue(FillProperty); }
set { SetValue(FillProperty, value); }
}
/// <summary>
/// 指定填充字体的画刷颜色依赖属性。
/// </summary>
public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
"Fill", typeof(Brush), typeof(OutlinedText),
new FrameworkPropertyMetadata(new SolidColorBrush(Colors.LightSteelBlue), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定文字显示的字体。
/// </summary>
public FontFamily Font
{
get { return (FontFamily)GetValue(FontProperty); }
set { SetValue(FontProperty, value); }
}
/// <summary>
/// 指定文字显示的字体依赖属性。
/// </summary>
public static readonly DependencyProperty FontProperty = DependencyProperty.Register(
"Font", typeof(FontFamily), typeof(OutlinedText),
new FrameworkPropertyMetadata(new FontFamily("Arial"), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定字体大小。
/// </summary>
public double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
/// <summary>
/// 指定字体大小依赖属性。
/// </summary>
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
"FontSize", typeof(double), typeof(OutlinedText),
new FrameworkPropertyMetadata((double)48.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定字体是否显示斜体字体样式。
/// </summary>
public bool Italic
{
get { return (bool)GetValue(ItalicProperty); }
set { SetValue(ItalicProperty, value); }
}
/// <summary>
/// 指定字体是否显示斜体字体样式依赖属性。
/// </summary>
public static readonly DependencyProperty ItalicProperty = DependencyProperty.Register(
"Italic", typeof(bool), typeof(OutlinedText),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定绘制空心字体边框画刷的颜色。
/// </summary>
public Brush Stroke
{
get { return (Brush)GetValue(StrokeProperty); }
set { SetValue(StrokeProperty, value); }
}
/// <summary>
/// 指定绘制空心字体边框画刷的颜色依赖属性。
/// </summary>
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
"Stroke", typeof(Brush), typeof(OutlinedText),
new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Teal), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定空心字体边框大小。
/// </summary>
public ushort StrokeThickness
{
get { return (ushort)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
/// <summary>
/// 指定空心字体边框大小依赖属性。
/// </summary>
public static readonly DependencyProperty StrokeThicknessProperty =
DependencyProperty.Register("StrokeThickness",
typeof(ushort), typeof(OutlinedText),
new FrameworkPropertyMetadata((ushort), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnOutlineTextInvalidated), null)); /// <summary>
/// 指定要显示的文字字符串。
/// </summary>
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <summary>
/// 指定要显示的文字字符串依赖属性。
/// </summary>
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(OutlinedText),
new FrameworkPropertyMetadata("",
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnOutlineTextInvalidated),
null)); #endregion #region Public Methods /// <summary>
/// 添加子对象。
/// </summary>
/// <param name="value">要添加的子对象。</param>
public void AddChild(Object value)
{ } /// <summary>
/// 将节点的文字内容添加到对象。
/// </summary>
/// <param name="value">要添加到对象的文字。</param>
public void AddText(string value)
{
Text = value;
} #endregion
}

源码下载

WPF自定义空心文字的更多相关文章

  1. [WPF] 如何实现文字描边

    1. 前言 WPF 的 TextBlock 提供了大部分常用的文字修饰方法,在日常使用中基本够用.如果需要更丰富的表现方式,WPF 也提供了其它用起来复杂一些的工具去实现这些需求.例如这篇文章介绍的文 ...

  2. WPF 自定义 MessageBox (相对完善版)

    WPF 自定义 MessageBox (相对完善版)     基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当 ...

  3. WPF 自定义 MessageBox (相对完善版 v1.0.0.6)

    基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当你不得不弹出一个消息框通知用户消息时(虽然很不建议在程序中频繁 ...

  4. WPF自定义TextBox及ScrollViewer

    原文:WPF自定义TextBox及ScrollViewer 寒假过完,在家真心什么都做不了,可能年龄大了,再想以前那样能专心坐下来已经不行了.回来第一件事就是改了项目的一个bug,最近又新增了一个新的 ...

  5. WPF自定义LED风格数字显示控件

    原文:WPF自定义LED风格数字显示控件 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199988899/article/de ...

  6. WPF 自定义柱状图 BarChart

    WPF 自定义柱状图 当前的Telerik控件.DevExpress控件在图表控件方面做得不错,但是有时项目中需要特定的样式,不是只通过修改图表的模板和样式就能实现的. 或者说,通过修改当前的第三方控 ...

  7. Android实现自定义带文字和图片的Button

    Android实现自定义带文字和图片的Button 在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就 ...

  8. wpf 自定义圆形按钮

    wpf 自定义圆形按钮 效果图 默认样式 获取焦点样式 点击样式 下面是实现代码: 一个是自定义控件类,一个是控件类皮肤 using System; using System.Collections. ...

  9. WPF自定义窗口基类

    WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...

随机推荐

  1. js自调用匿名函数的三种写法

    第一种: (function(){ console.log(‘hello world”) })() 第二种: (function(){ console.log(‘hello world’) }()) ...

  2. Quartz.NET开源作业调度框架系列(二):CronTrigger

    CronTriggers比SimpleTrigger更加的灵活和有用,对于比较复杂的任务触发规则,例如"每个星期天的晚上12:00"进行备份任务,SimpleTrigger就不能胜 ...

  3. Droidicon – 1600+ 漂亮的 Android 图标

    Droidicon 提供超过1600款定制图标,让你可以超级容易的把图标和徽章添加到您的应用程序中.你可以自定义你想要的各种形式的图标,给图标添加描边,透明度和颜色过滤器.包括这些 Google Ma ...

  4. Headroom.js – 快速响应用户的页面滚动操作

    Headroom.js 是一个轻量级,高性能的JS插件(无依赖性!),允许你响应用户的滚动行为.Headroom.js 使您能够在适当的时候把元素融入视图,而其它时候让内容成为焦点.Headroom. ...

  5. 【特别推荐】10款唯美浪漫的婚礼 & 结婚纪念网站模板

    互联网的重要性不言而喻,如今我们的生活已经完全离不开网络.这里给大家分享一组唯美浪漫的结婚邀请网站以及婚礼请柬网站模板,如果你也正想制作这样的网站,相信这些漂亮的网站模板能够带给你很大的帮助,让你快速 ...

  6. DevExpress 13.1.8全面支持VS2013

    界面套包DevExpress 13.1.8重磅来袭.从这个版本开始所有.NET控件均正式支持VS2013,当然还有很多其他更新,下面是部分更新内容: DevExpress所有.NET控件: 正式支持V ...

  7. 传说中的AutoCAD公司 - 欧特克(Autodesk)招聘开发顾问-上海或北京

    如果您热衷新技术,垂涎科技前沿,对编程有狂热的热情,乐于帮助别人打造解决方案,喜爱分享和交流,英文沟通无障碍,来吧,把简历丢过来! 如果您刚毕业不久,那也不要因为工作经历尚浅而怯步,我们也非常欢迎您! ...

  8. Android提交数据到JavaWeb服务器实现登录

    之前学习Android提交数据到php服务器没有成功,在看了两三个星期的视频之后,现在终于实现了与服务器的交互.虽然完成的不是PHP端的,但是在这个过程还是学到了不少东西的.现在我先来展示一下我的成果 ...

  9. Swift开发第二篇——extension及fatalError

    本篇分两部分: 一.extension在 Swift 中的使用 二.Swift 中的 fatalError 一.extension在 Swift 中的使用 在 swift 中我们可以通过 extens ...

  10. View的onSaveInstanceState和onRestoreInstanceState过程分析

    为什么要介绍这2个方法呢?这是因为在我们的开发中最近遇到了一个很诡异的bug.大体是这样的:在我们的ViewPager中 有2页的root view都是ScrollView,我们在xml里面都用了an ...