Hello!
I have a bug when paint string in a winforms custom control, and I cannot fix it.
the control is a custom linklabel control and highlight the keyword with a different color.
there are 3 add propertites:
IgnoreCase Keyword and KeywordColor
and rewrite the Paint methord.
here is full code:
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 = 0; Region[] regions = e.Graphics.MeasureCharacterRanges(Text, Font, new RectangleF(this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width, this.ClientRectangle.Height), stringFormat); int i = 0; foreach (var item in GetStringRgn().ToList()) { PointF ptf = new PointF(regions[i].GetBounds(e.Graphics).X, regions[i].GetBounds(e.Graphics).Y); 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), ptf, stringFormat); i++; } } private CharacterRange[] GetRanges() { return GetStringRgn().ToList() .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 (i - pre == 30) //{ // yield return new Tuple<int, int, bool>(pre, i - 1, false); // pre = i; //} 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; continue; } } i++; } if (pre <= Text.Length - 1) yield return new Tuple<int, int, bool>(pre, Text.Length - 1, false); } } }
to reproduce the bug, flow these steps:
(1) Create a Windows Forms Application (I'm using VS2012 UP3 + Windows 8, but I think VS2010/VS2013 is also ok)
(2) Create a Class(not a user control) named superlinklabel, and paste the code
(3) Put a superlinklabel Control to form, and set Text property to itself's sourcecode
(4) Set KeyWord property to Color
(5) Build and Run
Image may be NSFW.
Clik here to view.
the bug is shown on the image I attach here.
Thanks a lot.
Zhongyan