下载文件里的代码比较老了 在下也懒得去更新,其实文章已经说的很清楚了,关键代码也贴出来了,
认真看文章的同学应该很容易就能自己实现,下载文件那5个分各位看情谊吧。。。(代码以文章为准)
更新:
之前那个文本横向不支持下划线删除线等
1.添加依赖属性
public TextDecorationCollection TextDecorations
{
get { return (TextDecorationCollection)GetValue(TextDecorationsProperty); }
set { SetValue(TextDecorationsProperty, value); }
}
public static readonly DependencyProperty TextDecorationsProperty =
DependencyProperty.Register("TextDecorations", typeof(TextDecorationCollection), typeof(ReportButton), new PropertyMetadata());
2.修改文字绘制方式
#region DrawText
//textOrientation
if (VM.Direction == ReportContentDirection.Horizontal)
{
var fmttxt = MeasureFont(Text.ToString());
fmttxt.SetTextDecorations(TextDecorations);
drawingContext.DrawText(fmttxt, new Point(0, BorderThickness.Top));
}
————————————————————————————————————————————————————————
LabelEx实现说明
LabelEx是对WPF原生的Label控件的功能扩展
扩展的功能有
在摒弃了原有的文本属性基础上,通过自定义的依赖属性和Onrender的drawingContext的一系列绘制方法重绘Label的文字。
先看最终需要达到的效果
上对齐、左对齐
文字超出边界后
效果主要体现在竖排文字的变换上,从上图分析:
分别用于控制文字排布、文本内容、文字字符间距及背景色
Label本身的Content和Backgreound属性必须设置为空文本和透明,是因为我们绘制的操作实在本身的控件下显示的。
自定义了3个方法,分别用来:
ASCII码常用对照表
在ASCII上不存在的,基本就是非数字英文标点及空格
第二个方法就不说了
直接进行第三个方法的说明:
红色区域一的作用:
调用自定义方法二,为每个字符生成一个FormattedText对象,累计计算它们变换操作后的区域大小。
红色区域二的作用:
要看懂代码得先看链接一下的Method系列了解各个方法函数的作用
要看懂代码得先看链接一下的Method系列了解各个方法函数的作用
要看懂代码得先看链接一下的Method系列了解各个方法函数的作用
原理:在原有Label的基础上,添加依赖属性,通过依赖属性来触发Onrender重绘文本内容
Content 和 Background这两个属性必须设置为string.Empty 和 透明
难点:旋转等变换操作后文本的位置控制(需要考虑边距 单个字符的宽高差 整体变换的原点...)
关键代码
#region override method
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
//background
drawingContext.DrawRectangle(BackColor, null, new Rect(new Point(0, 0), new Size(ActualWidth, ActualHeight)));
//获取整个文本区域的大小
Size size = getTextRange();
double offsetx = BorderThickness.Left, offsety = BorderThickness.Top;
//控制文本超出控件范围则剪去
drawingContext.PushClip(new RectangleGeometry(new Rect(new Point(BorderThickness.Left, BorderThickness.Top), new Point(Width - BorderThickness.Right, Height - BorderThickness.Bottom))));
//根据文字排布位置计算需要移动的位置
if (HorizontalContentAlignment == HorizontalAlignment.Center)
offsetx = (Width - size.Width - BorderThickness.Left - BorderThickness.Right) / 2;
if (HorizontalContentAlignment == HorizontalAlignment.Right)
offsetx = Width - size.Width - BorderThickness.Right;
if (VerticalContentAlignment == VerticalAlignment.Center)
offsety = (Height - size.Height - BorderThickness.Top - BorderThickness.Bottom) / 2;
if (VerticalContentAlignment == VerticalAlignment.Bottom)
offsety = Height - size.Height - BorderThickness.Bottom;
drawingContext.PushTransform(new TranslateTransform(offsetx, offsety));
#region DrawText
//textOrientation
if (TextOrientation == Direction.Horizontal)
{
double w = BorderThickness.Left;
foreach (char str in Text)
{
var fmttxt = MeasureFont(str.ToString());
drawingContext.DrawText(fmttxt, new Point(w, BorderThickness.Top));
w += fmttxt.WidthIncludingTrailingWhitespace + FontSpace;
}
}
else if (TextOrientation == Direction.Vertical)
{
drawingContext.PushTransform(new TranslateTransform(-Math.Abs(size.Width - size.Height) / 2, Math.Abs(size.Width - size.Height) / 2));
double w = BorderThickness.Top;
drawingContext.PushTransform(new RotateTransform(90, size.Height / 2, size.Width / 2 + BorderThickness.Top / 2));
foreach (char str in Text)
{
var fmttxt = MeasureFont(str.ToString());
if (IsASCIIChar(str))
{
drawingContext.DrawText(fmttxt, new Point(w, BorderThickness.Top));
w += fmttxt.WidthIncludingTrailingWhitespace + FontSpace;
}
else
{
drawingContext.PushTransform(new TranslateTransform(0, 0));
drawingContext.PushTransform(new RotateTransform(-90, w + fmttxt.WidthIncludingTrailingWhitespace / 2, fmttxt.Height / 2));
if (FontStyle == FontStyles.Italic || FontStyle == FontStyles.Oblique)
{
fmttxt.SetFontStyle(FontStyles.Normal);
drawingContext.PushTransform(new TranslateTransform(0, 5));
drawingContext.PushTransform(new SkewTransform(0, 15, w + fmttxt.Height / 2, fmttxt.WidthIncludingTrailingWhitespace / 2));
drawingContext.DrawText(fmttxt, new Point(w, BorderThickness.Top));
drawingContext.Pop();
drawingContext.Pop();
}
else
{
drawingContext.DrawText(fmttxt, new Point(w, BorderThickness.Top));
}
drawingContext.Pop();
drawingContext.Pop();
w += fmttxt.WidthIncludingTrailingWhitespace / 2 + fmttxt.Height / 2 + FontSpace;
}
}
drawingContext.Pop();
drawingContext.Pop();
}
else if (TextOrientation == Direction.ClockwiseVertical)
{
drawingContext.PushTransform(new TranslateTransform(-Math.Abs(size.Width - size.Height) / 2, Math.Abs(size.Width - size.Height) / 2));
double w = BorderThickness.Top;
drawingContext.PushTransform(new RotateTransform(90, size.Height / 2, size.Width / 2 ));
foreach (char str in Text)
{
var fmttxt = MeasureFont(str.ToString());
drawingContext.DrawText(fmttxt, new Point(w, BorderThickness.Top));
w += fmttxt.WidthIncludingTrailingWhitespace + FontSpace;
}
drawingContext.Pop();
drawingContext.Pop();
}
else
{
drawingContext.PushTransform(new TranslateTransform(-Math.Abs(size.Width - size.Height) / 2, Math.Abs(size.Width - size.Height) / 2));
double w = BorderThickness.Top;
drawingContext.PushTransform(new RotateTransform(270, size.Height / 2, size.Width / 2 ));
foreach (char str in Text)
{
var fmttxt = MeasureFont(str.ToString());
drawingContext.DrawText(fmttxt, new Point(w, BorderThickness.Top));
w += fmttxt.WidthIncludingTrailingWhitespace + FontSpace;
}
drawingContext.Pop();
drawingContext.Pop();
}
drawingContext.Pop();
drawingContext.Pop();
//若Height和Width没设置 则为它加上值
if (double.IsNaN(Height))
Height = size.Height + BorderThickness.Top + BorderThickness.Bottom;
if (double.IsNaN(Width))
Width = size.Width + BorderThickness.Left + BorderThickness.Right;
}
#endregion
#region other method
private bool IsASCIIChar(char c)
{
// 判断字符串中第一位字符是否是ASCII字符( 0–127),ASCII字符占一个字节
return c / 0x80 == 0 ? true : false;
}
private FormattedText MeasureFont(string str)
{
var ftxt = new FormattedText(
str,
CultureInfo.CurrentUICulture,
FlowDirection.LeftToRight,
new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
FontSize,
Foreground
);
ftxt.TextAlignment = TextAlignment.Justify;
return ftxt;
}
///
/// get all Text area size
///
///
private Size getTextRange()
{
Size size = new Size();
if (TextOrientation == Direction.Horizontal)
foreach (var v in Text)
{
var ft = MeasureFont(v.ToString());
size.Width += ft.WidthIncludingTrailingWhitespace + FontSpace;
size.Height = size.Height > ft.Height ? size.Height : ft.Height;
}
else if (TextOrientation == Direction.Vertical)
{
foreach (var v in Text)
{
var ft = MeasureFont(v.ToString());
if (IsASCIIChar(v))
size.Height += ft.Width + FontSpace;
else
size.Height += ft.Height / 2 + ft.WidthIncludingTrailingWhitespace / 2 + FontSpace + 2.5;
size.Width = size.Width > ft.Height ? size.Width : ft.Height;
}
}
else
{
foreach (var v in Text)
{
var ft = MeasureFont(v.ToString());
size.Height += ft.WidthIncludingTrailingWhitespace + FontSpace;
size.Width = size.Width > ft.Height ? size.Width : ft.Height;
}
}
//tan15/180=2-Math.Sqrt(3.0)
if (FontStyle == FontStyles.Italic || FontStyle == FontStyles.Oblique)
{
if (TextOrientation == Direction.Horizontal)
{
size.Width += size.Height * (2 - Math.Sqrt(3.0));
}
else
{
size.Height += size.Width * (2 - Math.Sqrt(3.0));
}
}
return size;
}
#endregion
不想思考或者想支持一下的同学:下载链接 链接里的代码是旧版的懒得改了 方法以这里的为准
参照这个 你还可以自己玩一下其他的button textbox什么的 还有文字描边的原理其实比这个更简单 就懒得写了。。。