C# Richtextbox 创建、设置字体颜色、添加删除读取行、每行显示指定字数、修改选中文字颜色、用红色标出行
Richtextbox 是 C# 中的富文本编辑框,用于编辑内容比较多的文本,当然也可以用它显示文本,只要把它的背景颜色设置为与它所在控件的背景一致。Richtextbox 创建有两种方法,一种为用控件创建,另一种为用代码创建。它有很多属性,设置或修改它们既可在“属性”窗口又可用代码,本文主要探讨后者。
设置或修改 Richtextbox 字体颜色,既可用具体的颜色名称又可用RGB。Richtextbox 显示的行数与换行符分隔的行数不是一个概念,它的属性 lines 是指后者,而添加删除读取行和每行显示指定字数都是指前者。若要突出显示选中文字,可以用高亮的颜色或大的字体显示,也可以同时用两者;除可标出一行或几行外,还可标出某个指定词组。
一、C# Winform Richtextbox 的创建
1、从“工具箱”创建。把“工具箱”中的 Richtextbox 拖到窗体就创建了一个 Richtextbox 控件。
2、用代码创建。
创建一个 Richtextbox 控件,同时定义几个属性,然后把它添加到现有窗体,代码如下:
using System.Drawing;
using System.Windows.Forms;
private void CreateRichTextBox()
{
RichTextBox richTextBox1 = new RichTextBox
{
Dock = DockStyle.None,// 不填充,若要填整个窗体,用 Dock = DockStyle.Fill
Font = new Font("Cambria", 10),
ForeColor = Color.Gray,
Size = new Size(600, 400)
};
richTextBox1.Text = "创建一个 richTextBox 控件";
richTextBox1.Location = new Point(10, 10);
this.Controls.Add(richTextBox1);
}
如果要把创建的 Richtextbox 控件添加到一个新建的窗体,只需把 this.Controls.Add(richTextBox1); 改为如下代码:
Form frm = new Form { Controls = { richTextBox1 } };
frm.Width = 670;
frm.Height = 520;
frm.ShowDialog();
在窗体构造函数中调用:
public richtext()
{
InitializeComponent();
CreateRichTextBox();
}
二、C# Winform Richtextbox 的属性设置
1、Richtextbox 字体颜色
创建 Richtextbox 时可以定义字体颜色,如以上的 ForeColor = Color.Gray;也可以创建 Richtextbox 后定义,代码如下:
richTextBox1.ForeColor = Color.DimGray;
或
richTextBox1.ForeColor = Color.FromArgb(255, 108, 105, 105);
FromArgb 的第一个参数为 alpha(透明度),后三个参数为 R、G、B(红、绿、蓝)。
2、Richtextbox 字体大小
Font f = new Font("宋体", 10F, FontStyle.Regular, GraphicsUnit.Point);
richTextBox1.Font = f;
如果要设置为粗体,只需把 FontStyle.Regular 改为 FontStyle.Bold,即:
Font f = new Font("宋体", 10F, FontStyle.Bold, GraphicsUnit.Point);
3、Richtextbox 的比例因子 ZoomFactor
修改 ZoomFactor,文字和行高会自动增大,例如把它的值改为 1.2,见如下代码:
richTextBox1.ZoomFactor = (float)1.2;
效果如图1所示:
图1
三、C# Winform Richtextbox 行
(一)Richtextbox 添加和插入新行
1、添加新行到最后
(1)只添加空行
richTextBox1.AppendText( Environment.NewLine); 或 richTextBox1.AppendText("\r\n");
(2)添加一行文字
richTextBox1.AppendText("Richtextbox 添加新行\r\n");
\r\n 为换行符,放在后表示在文字后换行;如果要在文字前换行,把它放到文字前即可。
2、插入新行
插入新行到第一行:
richTextBox1.Text = richTextBox1.Text.Insert(0, "插入新行到第一行\r\n");
0 表示插入到第一行,如果要插入到其它行,把 0 改为相应行号,例如插入到第 6 行,把 0 改为 6 即可。
3、如果 RichTextBox 的内容为空,添加到第一行,否则添加末尾,代码如下:
private void AddTextIntoRichTextBox(string text)
{
if (String.IsNullOrEmpty(richTextBox1.Text))
richTextBox1.AppendText(text);
else
richTextBox1.AppendText( Environment.NewLine + text);
richTextBox1.ScrollToCaret();//把控件内容滚动到当前插入符号位置
}
(二)C# Winform Richtextbox 添加新行且文字为彩色
假如要把一行文字显示为三种颜色。添加文本仍用 AppendText 方法,但默认方法没有此功能,需要重载扩展,代码如下:
using System;
using System.Windows.Forms;
using System.Drawing;
namespace PublicClass
{
public static class RichTextBoxColorExtensions
{
public static void AppendText(this RichTextBox rtb, string text, Color color, Font font, bool isNewLine = false)
{
rtb.SuspendLayout();
rtb.SelectionStart = rtb.TextLength;
rtb.SelectionLength = 0;
rtb.SelectionColor = color;
rtb.SelectionFont = font;
rtb.AppendText(isNewLine ? $"{text}{ Environment.NewLine}" : text);
rtb.SelectionColor = rtb.ForeColor;
rtb.ScrollToCaret();
rtb.ResumeLayout();
}
}
}
// 添加新行且文字为彩色
private void DifferentColorRichTextBox()
{
string text = "沙糖桔|6元/斤|2050千克||龙眼|5元/斤|685千克||香蕉|4.5元/斤|1258千克";
string[] arr = text.Split(new string[] { "||" }, StringSplitOptions.RemoveEmptyEntries);
Font font = new Font("宋体", 12);
string[] subArr;
for (int i = 0; i < arr.Length; i++)
{
subArr = arr[i].Split('|');
richTextBox1.AppendText(subArr[0], Color.Fuchsia, font);
richTextBox1.AppendText(":");
richTextBox1.AppendText(subArr[1], Color.Green, font);
richTextBox1.AppendText(" ");
richTextBox1.AppendText(subArr[2], Color.Blue, font, true);
}
}
在窗体构造函数中调用:
public richtext()
{
InitializeComponent();
DifferentColorRichTextBox();
}
效果如图2所示:
图2
(三)C# Winform Richtextbox 滚动到最后一行
richTextBox1.SelectionStart = richTextBox1.TextLength;//或 richTextBox1.Select(richTextBox1.TextLength, 0);
richTextBox1.ScrollToCaret();
richTextBox1.AppendText(richTextBox1.Text);
(四)C# Winform Richtextbox 行数
1、RichTextBox.Lines 含义
RichTextBox.Lines 是指“属性”窗口中 Text 右边的文字行数,不是指窗体中的文字行数。假如在 RichTextBox1 中有两行文字,如图3所示:
图3
用代码:
int n = richTextBox1.Lines.Length;
AddTextIntoRichTextBox(n.ToString());//调用上面的方法
显示它的行数,结果显示 2,如图4所示:
图4
2、逐行读取 RichTextBox.Lines 文本
private void ReadTextInRichTextBox()
{
foreach(string l in richTextBox1.Lines)
{
MessageBox.Show(l);
}
}
3、读取指定行
假如要读取包含 Winform 的行,代码如下:
private string ReadSpecificLineInRichTextBox(string specificText)
{
// 查找指定文字所在的位置
int pos = richTextBox1.Find(specificText, RichTextBoxFinds.MatchCase);
if (pos != -1)
{
// 根据指定文字所在的位置返回行号
int lineNum = richTextBox1.GetLineFromCharIndex(pos);
string text = richTextBox1.Lines.ElementAt(lineNum);
return text;
}
return null;
}
调用:
ReadSpecificLineInRichTextBox("Winform");
也可以用兰姆达表达式(Lambda)实现,代码如下:
private string ReadSpecificLineInRichTextBox(string specificText)
{
return richTextBox1.Lines.FirstOrDefault(l => l.Contains(specificText));
}
4、RichTextBox 仅显示前 n 行
(1)显示前 n 行,不能指定每行字数
private void RichTextBoxDisplayNLines(int lineNum)
{
richTextBox1.Lines = richTextBox1.Lines.Take(lineNum).ToArray();
}
调用(仅显示前 5 行):
RichTextBoxDisplayNLines(5);
(2)显示前 n 行,能指定每行字数
using System.Text.RegularExpressions;
/// <summary>
/// 仅显示前 n 行且能指定每行字数
/// </summary>
/// <param name="text">文本</param>
/// <param name="lineNum">显示行数</param>
/// <param name="numEachLine">每行字数</param>
/// <param name="replaceLineBreak">是否取代文本中的换行符;如果取代,所有行变一行,然后再分行;如果不取代,把原来的每行分为多行</param>
/// <returns>每行指定字数的指定行数的文本</returns>
private string RichTextBoxDisplayNLines(string text, int lineNum, int numEachLine, bool replaceLineBreak = false)
{
if (string.IsNullOrEmpty(text) || lineNum <= 0 || numEachLine <= 0)
return null;
if (text.Length <= numEachLine)
return text;//当文本字数小于每行要求的字数时,返回原文本
string lineBreak = Environment.NewLine;
int realLen = 0;//文本以汉字为单位的长度
int lastLen = 0;//每行实际长度
if (replaceLineBreak)
{
text = Regex.Replace(text, "["[\\s]]{2,}", " ");//去掉空格
text = Regex.Replace(text, "("[\\s]*&[n|N][b|B][s|S][p|P];"[\\s]*)+", " ");//去掉
text = text.Trim().Replace("\n", "").Replace("\r", "");
realLen = GetTextRealLenght(ref text);
int n = realLen / numEachLine;
if (realLen % numEachLine > 0)
n++;
if (n > lineNum)
n = lineNum;
//把换行符插到每行指定字数后
for (int i = 0; i < n; i++)
{
lastLen += GetTextRealLenght(ref text, numEachLine * 2, lastLen);
if (i == 0)
{
if (i == n - 1)//只显示一行
text = text.Substring(0, lastLen);
else
text = text.Insert(lastLen, lineBreak);
lastLen += lineBreak.Length;
}
else
{
if (i != n - 1)//最后一行不插换行符
{
text = text.Insert(lastLen, lineBreak);
lastLen += lineBreak.Length;
}
else
{
//如果原文本长度大于指定行数,只显示指定行数
if (text.Length >= lastLen)
text = text.Substring(0, lastLen);
}
}
}
}
else
{
string[] arr = text.Split( Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
int currLineNum = 0;
text = string.Empty;
bool flag = false;//最后一次是否插入过换行符
for (int i = 0; i < arr.Length && currLineNum < lineNum; i++)
{
if (!string.IsNullOrEmpty(arr[i]))
{
realLen = GetTextRealLenght(ref arr[i]);
int n = realLen / numEachLine;
if (realLen % numEachLine > 0)
n++;
if (n == 0)
n = 1;
for (int j = 0; j < n && currLineNum < lineNum; j++)
{
lastLen += GetTextRealLenght(ref arr[i], numEachLine * 2, lastLen);
//只有原文本的每行字数大于指定的每行字数时才重新拆分为多行
if (realLen > numEachLine)
{
if (j == 0)
{
if (currLineNum == lineNum - 1)
{
arr[i] = arr[i].Substring(0, lastLen);//只显示一行
flag = true;
}
else
arr[i] = arr[i].Insert(lastLen, lineBreak);
lastLen += lineBreak.Length;
}
else
{
//每隔每行指定个字插入一个换行符
if (j != n - 1 && currLineNum != lineNum - 1)
{
arr[i] = arr[i].Insert(lastLen, lineBreak);
}
else
{
if (currLineNum == lineNum - 1 && lastLen < realLen + (j + 1) * lineBreak.Length)
{
arr[i] = arr[i].Insert(lastLen, lineBreak);
flag = true;
}
}
// 从原文本当前行截取到最后一行
if (currLineNum == lineNum - 1 && flag)
arr[i] = arr[i].Substring(0, arr[i].LastIndexOf(lineBreak));
lastLen += lineBreak.Length;
}
}
currLineNum++;
}
lastLen = 0;
text += arr[i];
if (currLineNum != lineNum)//不是最后一行,每段后加一个换行符
stext += lineBreak;
}
}
}
return text;
}
//统计以汉字为单位字符个数
private int GetTextRealLenght(ref string text)
{
int len = text.Length, cnNum = 0, enNum = 0;
GetTextRealLenght(ref text, text.Length * 2, 0, ref cnNum, ref enNum);
int enLen = enNum / 2;
if (enNum % 2 > 0)
enLen++;
return cnNum + enLen;
}
/// <summary>
/// 统计汉字和字母个数,一个汉字或字母都算一个
/// </summary>
/// <param name="text">文本</param>
/// <param name="num">指定字数</param>
/// <param name="i">开始统计位置</param>
/// <returns>满足条件的汉字和字母个数</returns>
private int GetTextRealLenght(ref string text, int num, int i)
{
int len = text.Length, cnNum = 0, enNum = 0;
return GetTextRealLenght(ref text, num, i, ref cnNum, ref enNum);
}
/// <summary>
/// 统计汉字和字母个数,一个汉字或字母都算一个
/// </summary>
/// <param name="text">文本</param>
/// <param name="num">指定字数</param>
/// <param name="i">开始统计位置</param>
/// <param name="cnNum">汉字个数</param>
/// <param name="enNum">字母个数</param>
/// <returns>满足条件的汉字和字母个数</returns>
private int GetTextRealLenght(ref string text, int num, int i, ref int cnNum, ref int enNum)
{
int len = text.Length;
for (; i < len && 2 * cnNum + enNum < num; i++)
{
if ((int)text[i] > 128)
cnNum++;
else
enNum++;
}
return cnNum + enNum;
}
调用:
//取代原文本中的换行符:
richTextBox1.Text = RichTextBoxDisplayNLines(richTextBox1.Text, 12, 42, true);
//不取代原文本中的换行符:
richTextBox1.Text = RichTextBoxDisplayNLines(richTextBox1.Text, 12, 42);
效果如图5所示:
图5
(五)C# Winform Richtextbox 删除行
1、清空 RichTextBox
richTextBox1.Clear();
2、删除任意指定行
/// <summary>
/// 删除任意指定行
/// </summary>
/// <param name="startLineNum">开始行号</param>
/// <param name="endLineNum">结束行号</param>
private void DelSpecialLines(int startLineNum, int endLineNum)
{
//获取指定行的第一行的第一个字符的索引
int start = richTextBox1.GetFirstCharIndexFromLine(startLineNum - 1);
//获取指定行的最后一行的第一个字符的索引
int end = richTextBox1.GetFirstCharIndexFromLine(endLineNum);
richTextBox1.Select(start, end - start);//选中指定行
richTextBox1.SelectedText = "";//设置选择行的内容为空
}
调用:
DelSpecialLines(1, 1);//删除第 1 行
DelSpecialLines(6, 6);//删除第 6 行
DelSpecialLines(2, 4);//删除第 2 至 4 行
3、删除最后一行
richTextBox1.Text = richTextBox1.Text.Remove(richTextBox1.Text.Length - 1);
四、C# Winform richtextbox 修改选择文字的字体或颜色
1、右键 richtextbox,在弹出的菜单中选择“属性”,打开“属性”窗口,选择“事件”选项卡,在 SelectionChanged 右边添加 richTextBox1_SelectionChanged,然后按回车,则 richtextbox 添加选择事件,如图6所示:
图6
2、然后添加如下代码:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
if (richTextBox1.SelectedText.Length > 0)
{
richTextBox1.SelectionFont = new Font("楷体", 14);
richTextBox1.SelectionColor = Color.Red;
}
}
五、C# Winform richtextbox 修改文字的颜色
1、把包含指定文字的行修改为指定颜色
假如要把包含 Label 的行修改为指定颜色(如“红色”),代码如下:
private void ChangeColorForSpecialText(string specialText, Color color)
{
if (string.IsNullOrEmpty(specialText))
return;
int pos = 0;
int lineNum;
List<int> lst = new List<int>();
do
{
if (pos != 0 && pos + specialText.Length < richTextBox1.Text.Length)
pos += specialText.Length;//跳过要查找文字继续找
//查找指定文本的位置
pos = richTextBox1.Find(specialText, pos, RichTextBoxFinds.None);
if (pos > 0)
{
//根据文本位置返回它所在的行号
lineNum = richTextBox1.GetLineFromCharIndex(pos);
lst.Add(lineNum);
}
if (pos + specialText.Length > richTextBox1.Text.Length - 1)
break;
}while (pos >= 0 && pos < richTextBox1.Text.Length);
for (int i = 0; i < lst.Count; i++)
{
SelectLine(lst[i]);
richTextBox1.SelectionColor = color;
}
}
//选中一行,lineNum 为行号
private void SelectLine(int lineNum)
{
if (lineNum < 0)
return;
//根据行号返回该行第一个字符的索引
int start = this.richTextBox1.GetFirstCharIndexFromLine(lineNum);
int end = this.richTextBox1.GetFirstCharIndexFromLine(++lineNum);
if (start == -1)
return;
else if (end == -1)//如果 end 超出文本长度,则用文本长度 - start
end = this.richTextBox1.TextLength - start;
else
end = end - start;
this.richTextBox1.Select(start, end);
}
调用:
ChangeColorForSpecialText("Label", Color.Red);
效果如图7所示:
图7
2、把指定文字修改为指定颜色
private void ChangeColorForSpecialWord(string specialWord, Color color)
{
if (string.IsNullOrEmpty(specialWord))
return;
int pos = 0;
do
{
if (pos != 0 && pos + specialWord.Length < richTextBox1.Text.Length)
pos += specialWord.Length;//跳过要查找词继续找
//查找指定词的位置
pos = richTextBox1.Find(specialWord, pos, RichTextBoxFinds.None);
if (pos > 0)
{
richTextBox1.Select(pos, specialWord.Length);
richTextBox1.SelectionColor = color;
}
if (pos + specialWord.Length > richTextBox1.Text.Length - 1)
break;
} while (pos >= 0 && pos < richTextBox1.Text.Length);
}
调用:
ChangeColorForSpecialWord("Panel", Color.Red);// Panel 用红色标示
效果如图8所示:
图8
ChangeColorForSpecialWord("所示:\r4", Color.Red);// 用红色标示跨行的词(跨行查找)
效果如图9所示:
图9