//判断是否是中文
public bool IsChina(char c) {bool BoolValue = false;
if (Convert.ToInt32(c) < Convert.ToInt32(Convert.ToChar(128))) { BoolValue = false; } else { return BoolValue = true; } return BoolValue; } //获取字符串中文数量 public int GetLineIsChinese(Line list) { int isChinese = 0; for (int num = 0; num < list.Count;num++ ) { if (IsChina(list[num].c)) { isChinese++; } } return isChinese; } //获取中文和英文差异宽度 public int GetCharDiffWidth() { SizeF sizef = GetCharSize(this.Font, '中');//new Font("宋体", 10) int len = (int)sizef.Width - CharWidth; return len; }
//draw selection
if (!Selection.IsEmpty && lastChar >= firstChar) { e.Graphics.SmoothingMode = SmoothingMode.None; var textRange = new Range(this, from + firstChar, iLine, from + lastChar + 1, iLine); textRange = Selection.GetIntersectionWith(textRange); if (textRange != null && SelectionStyle != null) { int chineseCount= GetLineIsChinese(line); int diffWidths = GetCharDiffWidth()*chineseCount; diffWidth = diffWidths; SelectionStyle.Draw(e.Graphics, new Point(startX + (textRange.Start.iChar - from) * CharWidth, y), textRange); diffWidth = 0; } }
public override void Draw(Graphics gr, Point position, Range range)
{ //draw background if (BackgroundBrush != null) { Rectangle rect = new Rectangle(position.X, position.Y, (range.End.iChar - range.Start.iChar) * range.tb.CharWidth+FastColoredTextBox.diffWidth, range.tb.CharHeight); if (rect.Width == 0) return; gr.FillRectangle(BackgroundBrush, rect); } }diffWidth 这是公共变量,放在FastColoredTextBox类的公共变量声明里面
public static int diffWidth = 0;
/*****************************/
/* 该代码用于准确定位字,主要是因为中文不能准确定位 */
/*****************************/
/// <summary>
/// Gets nearest line and char position from coordinates /// </summary> /// <param name="point">Point</param> /// <returns>Line and char position</returns> public Place PointToPlace(Point point) { #if debug var sw = Stopwatch.StartNew();#endif point.Offset(HorizontalScroll.Value, VerticalScroll.Value); point.Offset(-LeftIndent - Paddings.Left, 0); int iLine = YtoLineIndex(point.Y); int y = 0;
for (; iLine < lines.Count; iLine++)
{ y = LineInfos[iLine].startY + LineInfos[iLine].WordWrapStringsCount * CharHeight; if (y > point.Y && LineInfos[iLine].VisibleState == VisibleState.Visible) break; } if (iLine >= lines.Count) iLine = lines.Count - 1; if (LineInfos[iLine].VisibleState != VisibleState.Visible) iLine = FindPrevVisibleLine(iLine); // int iWordWrapLine = LineInfos[iLine].WordWrapStringsCount; do { iWordWrapLine--; y -= CharHeight; } while (y > point.Y); if (iWordWrapLine < 0) iWordWrapLine = 0; // int start = LineInfos[iLine].GetWordWrapStringStartPosition(iWordWrapLine); int finish = LineInfos[iLine].GetWordWrapStringFinishPosition(iWordWrapLine, lines[iLine]); var x = (int)Math.Round((float)point.X / CharWidth); x = x < 0 ? start : start + x; if (x > finish) x = finish + 1; if (x > lines[iLine].Count) x = lines[iLine].Count;
if (lines[iLine].Count > 0)
{ x = GetXWidth(lines[iLine], point.X); }
#if debug
Console.WriteLine("PointToPlace: " + sw.ElapsedMilliseconds);#endif
return new Place(x, iLine);
}
private Place PointToPlaceSimple(Point point)
{ point.Offset(HorizontalScroll.Value, VerticalScroll.Value); point.Offset(-LeftIndent - Paddings.Left, 0); int iLine = YtoLineIndex(point.Y); var x = (int)Math.Round((float)point.X / CharWidth); Line line = lines[iLine]; if (x < 0) x = 0;
if (line.Count > 0)
{ x = GetXWidth(lines[iLine], point.X); } return new Place(x, iLine); } //计算x轴应该显示第几个字的宽度 public int GetXWidth(Line line,int x) { int iChar = 0; int len = 0; for (int num = 0; num < line.Count; num++) { if (len >= x) { break; } if (IsChina(line[num].c)) { iChar += 2; len += (GetCharDiffWidth() + CharWidth); } else { iChar++; len += CharWidth; } } return iChar; }