C# 自定义Label实现 指定字符串(关键词)高亮显示(字体、颜色)
原来是搞android的,本来自己就菜,现在由于项目需要开始着手弄C#、WPF,虽然了解一些,毕竟只是皮毛,唉,苦不堪言啊,还是得倚靠万能的互联网啊!
需求:提示用户的文字,但是该文字中需要高亮显示指定字符串,颜色字体等要不一样,比如提示"请使用 支付宝 扫码支付" ,其中要对“支付宝”三个字高亮显示。就像这样
第一反应就是使用 自带的Label控件,但是普通的Label是无法实现的,然后想了个笨办法,使用多个Label拼接,这个。。。如果需要高亮显示的字符串多了,那得要多少个Label啊,行不通。然后网上有说使用RichTextBox,试了一下,效果确实可以达到,但是有些差强人意,比如RichTextBox用户可以选中提示文字,试了设置enable=false后,确实是不可以选中文字了,但是系统默认的控件不可用的背景色是灰色,属性无法更改,也可能是自己对这些控件不够了解,或许可以通过重写Paint方法来更改,既然要重写Paint方法,何必使用RichTextBox这个控件呢?所以自定义Label就登场了:
###效果图:
#####两个重点
- 需要显示的字符串如何知道哪个是关键词
- 设置不同的字体后如何让文本居中显示
####1、拆分字符串
List<string> data = new List<string>();
//将所给字符串根据关键词 拆分成数组
private void splitText(string txt)
{
if (txt == null || txt.Length < 1)
return;
if (txt.Equals(keyword))//当前字符串就是关键词
{
data.Add(txt);
return;
}
//拆分文字 拿到关键词
int startIndex = txt.IndexOf(keyword);//关键词索引
if (startIndex == -1)//该字符串不包含关键词 直接添加到集合
{
data.Add(txt);
return;
}
//包含关键词 还有其他字符窜
int endIndex = startIndex + keyword.Length;
if (startIndex == 0)//关键词在首(第一次出现 可能后面还包含有关键词)
{
string k = txt.Substring(startIndex, endIndex);//拿到关键词
data.Add(k);
splitText(txt.Substring(endIndex));
}
else if (endIndex == txt.Length - 1)//关键词在末(当前字符串只要一个关键词)
{
splitText(txt.Substring(0, startIndex));
string k = txt.Substring(startIndex, keyword.Length);//拿到关键词
data.Add(k);//添加到集合
}
else//关键词在中
{
splitText(txt.Substring(0, startIndex));
string k = txt.Substring(startIndex, keyword.Length);//拿到关键词
data.Add(k);
splitText(txt.Substring(endIndex));
}
}
- 代码注释很详细了,就是递归拆分获取字符串数组,以便后面遍历画到控件上
####2、 重写Paint方法
private void l_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;//获取画笔
//设置背景色
if (mBackColor != null)
g.FillRectangle(mBackColor, 0, 0, this.Width, this.Height);//填充控件大小
if (mText == null || mText.Length < 1)
{
return;
}
data.Clear();
splitText(mText);//拆分字符串
//文字居中显示 dx水平偏移 dy垂直偏移
//使用Graphics 的 MeasureString()方法测量指定字体的字符串宽高
float dx = (this.Width - (g.MeasureString(mText, font)).Width) / 2.0f;
float dy = (this.Height - (g.MeasureString(mText, font)).Height) / 2.0f;
if (keyword == null || keyword.Length < 1)//没有关键词 关键词为空
{
g.DrawString(mText, font, mNormalColor, dx, dy);
return;
}
//拆分文字 拿到关键词
int startIndex = mText.IndexOf(keyword);//关键词索引
int endIndex = startIndex + keyword.Length;
string[] chunks = data.ToArray();//
if (keyfont != null)//当设置了关键词字体时 需要根据该字体测量 偏移量
{
float ddx = 0;
float ddy = 0;
ddx = this.Width;
//遍历
for (int i = 0; i < chunks.Length; i++)
{
if (chunks[i].Equals(keyword))//关键词
{
ddx -= g.MeasureString(keyword, keyfont).Width;
}
else
{
ddx -= g.MeasureString(chunks[i], font).Width;
}
}
ddx = ddx / 2.0f;
if (ddx < 0)
ddx = 0;
//遍历着色
for (int i = 0; i < chunks.Length; i++)
{
if (chunks[i].Equals(keyword))//关键词
{
ddy = (this.Height - (g.MeasureString(keyword, keyfont)).Height) / 2.0f;
g.DrawString(chunks[i], keyfont, mKeyColor, ddx, ddy);
//水平偏移自增
ddx += (g.MeasureString(chunks[i], keyfont)).Width;
}
else
{
ddy = (this.Height - (g.MeasureString(chunks[i], font)).Height) / 2.0f;
g.DrawString(chunks[i], font, mNormalColor, ddx, ddy);
//水平偏移自增
ddx += (g.MeasureString(chunks[i], font)).Width;
}
}
}
else
{
//遍历着色
for (int i = 0; i < chunks.Length; i++)
{
if (chunks[i].Equals(keyword))//关键词
{
g.DrawString(chunks[i], font, mKeyColor, dx, dy);
}
else
{
g.DrawString(chunks[i], font, mNormalColor, dx, dy);
}
//水平偏移自增
dx += (g.MeasureString(chunks[i], font)).Width;
}
}
}
- 代码注释得也很详细了,首先根据关键词拆分字符串,然后遍历数组,需要根据设置的关键词的字体来计算偏移量,以便最后文字居中显示
完整代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace lColorfulLabel
{
public partial class lColorfulLabel : UserControl
{
private string txt;
public string mText//显示文本
{
get { return txt; }
set
{
txt = value;
l.Invalidate();
}
}
private string keyword;
public string mKeyword//关键词
{
get { return keyword; }
set
{
keyword = value;
l.Invalidate();
}
}
private Font font;
public Font mFont//字体样式
{
get { return font; }
set
{
font = value;
l.Invalidate();
}
}
private Font keyfont;
public Font mKeyFont//关键词字体样式
{
get { return keyfont; }
set
{
keyfont = value;
l.Invalidate();
}
}
private SolidBrush normalColor;
public SolidBrush mNormalColor//普通字颜色
{
get { return normalColor; }
set
{
normalColor = value;
l.Invalidate();
}
}
private SolidBrush keyColor;//关键词颜色
public SolidBrush mKeyColor//关键词颜色
{
get { return keyColor; }
set
{
keyColor = value;
l.Invalidate();
}
}
private SolidBrush backColor;//背景色
public SolidBrush mBackColor//背景色
{
get { return backColor; }
set
{
backColor = value;
l.Invalidate();
}
}
public lColorfulLabel()
{
InitializeComponent();
mText = "请使用支付宝扫码支付";
keyword = "支付宝";
normalColor = new SolidBrush(Color.Black);//默认文字黑色
backColor = new SolidBrush(Color.White);//默认背景白色
keyColor = new SolidBrush(Color.DeepSkyBlue);//默认关键词红色
font = new System.Drawing.Font("微软雅黑", 12f);
keyfont = new System.Drawing.Font("微软雅黑", 20f);
l.Paint += l_Paint;
}
List<string> data = new List<string>();
//将所给字符串根据关键词 拆分成数组
private void splitText(string txt)
{
if (txt == null || txt.Length < 1)
return;
if (txt.Equals(keyword))//当前字符串就是关键词
{
data.Add(txt);
return;
}
//拆分文字 拿到关键词
int startIndex = txt.IndexOf(keyword);//关键词索引
if (startIndex == -1)//该字符串不包含关键词 直接添加到集合
{
data.Add(txt);
return;
}
//包含关键词 还有其他字符窜
int endIndex = startIndex + keyword.Length;
if (startIndex == 0)//关键词在首(第一次出现 可能后面还包含有关键词)
{
string k = txt.Substring(startIndex, endIndex);//拿到关键词
data.Add(k);
splitText(txt.Substring(endIndex));
}
else if (endIndex == txt.Length - 1)//关键词在末(当前字符串只要一个关键词)
{
splitText(txt.Substring(0, startIndex));
string k = txt.Substring(startIndex, keyword.Length);//拿到关键词
data.Add(k);//添加到集合
}
else//关键词在中
{
splitText(txt.Substring(0, startIndex));
string k = txt.Substring(startIndex, keyword.Length);//拿到关键词
data.Add(k);
splitText(txt.Substring(endIndex));
}
}
private void l_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;//获取画笔
//设置背景色
if (mBackColor != null)
g.FillRectangle(mBackColor, 0, 0, this.Width, this.Height);//填充控件大小
if (mText == null || mText.Length < 1)
{
return;
}
data.Clear();
splitText(mText);
//文字居中显示 dx水平偏移 dy垂直偏移
//使用Graphics 的 MeasureString()方法测量指定字体的字符串宽高
float dx = (this.Width - (g.MeasureString(mText, font)).Width) / 2.0f;
float dy = (this.Height - (g.MeasureString(mText, font)).Height) / 2.0f;
if (keyword == null || keyword.Length < 1)//没有关键词 关键词为空
{
g.DrawString(mText, font, mNormalColor, dx, dy);
return;
}
//拆分文字 拿到关键词
int startIndex = mText.IndexOf(keyword);//关键词索引
int endIndex = startIndex + keyword.Length;
string[] chunks = data.ToArray();//
if (keyfont != null)//当设置了关键词字体时 需要根据该字体测量 偏移量
{
float ddx = 0;
float ddy = 0;
ddx = this.Width;
//遍历
for (int i = 0; i < chunks.Length; i++)
{
if (chunks[i].Equals(keyword))//关键词
{
ddx -= g.MeasureString(keyword, keyfont).Width;
}
else
{
ddx -= g.MeasureString(chunks[i], font).Width;
}
}
ddx = ddx / 2.0f;
if (ddx < 0)
ddx = 0;
//遍历着色
for (int i = 0; i < chunks.Length; i++)
{
if (chunks[i].Equals(keyword))//关键词
{
ddy = (this.Height - (g.MeasureString(keyword, keyfont)).Height) / 2.0f;
g.DrawString(chunks[i], keyfont, mKeyColor, ddx, ddy);
//水平偏移自增
ddx += (g.MeasureString(chunks[i], keyfont)).Width;
}
else
{
ddy = (this.Height - (g.MeasureString(chunks[i], font)).Height) / 2.0f;
g.DrawString(chunks[i], font, mNormalColor, ddx, ddy);
//水平偏移自增
ddx += (g.MeasureString(chunks[i], font)).Width;
}
}
}
else
{
//遍历着色
for (int i = 0; i < chunks.Length; i++)
{
if (chunks[i].Equals(keyword))//关键词
{
g.DrawString(chunks[i], font, mKeyColor, dx, dy);
}
else
{
g.DrawString(chunks[i], font, mNormalColor, dx, dy);
}
//水平偏移自增
dx += (g.MeasureString(chunks[i], font)).Width;
}
}
}
}
}
这是自定义控件,若有需要的朋友,需要将编译后的dll文件添加到你的解决方案里,不会的朋友请百度“C#使用自定义控件”。