代码分享,WinForm中LinkLabel实现关键字高亮
使用说明:
IgnoreCase 是否匹配大小写,默认false,严格匹配大小写
Keyword 关键字
KeywordColor 关键字的颜色,默认红色
BUG列表:
部分颜色属性不工作,比如访问后颜色,自定义背景色等等
不支持多行文本
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApplication1
{
class SuperLinkLabel : LinkLabel
{
public bool IgnoreCase { get; set; }
private string keyWord = "";
public string Keyword
{
get { return keyWord; }
set { keyWord = value; this.Invalidate(); }
}
public Color KeywordColor { get; set; }
public SuperLinkLabel()
{
Keyword = "";
KeywordColor = Color.Red;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(SystemColors.Control), e.ClipRectangle);
StringFormat stringFormat = new StringFormat();
stringFormat.SetMeasurableCharacterRanges(GetRanges());
stringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
Region[] regions = e.Graphics.MeasureCharacterRanges(Text, Font, new RectangleF(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width + 200, e.ClipRectangle.Height), stringFormat);
int i = 0;
foreach (var item in GetStringRgn().ToList())
{
bool isKeyword = GetStringRgn().Single(x => x.Item1 == item.Item1).Item3;
e.Graphics.DrawString(Text.Substring(item.Item1, item.Item2 - item.Item1 + 1), Font, isKeyword ? new SolidBrush(KeywordColor) : new SolidBrush(LinkColor), new PointF(regions[i].GetBounds(e.Graphics).X, regions[i].GetBounds(e.Graphics).Y), stringFormat);
i++;
}
}
private CharacterRange[] GetRanges()
{
return GetStringRgn().ToArray().Select(x => new CharacterRange(x.Item1, x.Item2 - x.Item1 + 1)).ToArray();
}
private IEnumerable<Tuple<int, int, bool>> GetStringRgn()
{
if (Keyword == "" || Text == "")
{
if (Text == "") yield break;
yield return new Tuple<int, int, bool>(0, Text.Length - 1, false);
yield break;
}
int pre = 0;
int i = 0;
while (i <= Text.Length - Keyword.Length)
{
if (Text.Substring(i, Keyword.Length).ToUpper() == Keyword.ToUpper())
{
if (IgnoreCase || Text.Substring(i, Keyword.Length) == Keyword)
{
if (pre != i) yield return new Tuple<int, int, bool>(pre, i - 1, false);
yield return new Tuple<int, int, bool>(i, i + Keyword.Length - 1, true);
i += Keyword.Length;
pre = i;
}
else
{
i++;
}
}
else
{
i++;
}
}
if (pre <= Text.Length - 1) yield return new Tuple<int, int, bool>(pre, Text.Length - 1, false);
}
}
}