📄 frmlinecount.cs
字号:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace PublicUIComponent
{
/// <summary>
/// frmLineCount 的摘要说明。
/// </summary>
public class frmLineCount : System.Windows.Forms.Form
{
#region Windows 窗体设计器生成的代码
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.NumericUpDown updBeginNum;
private System.Windows.Forms.NumericUpDown updSpace;
private System.Windows.Forms.Button btnInsert;
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.CheckBox chkIsAll;
private System.Windows.Forms.CheckBox chkHasStyle;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public frmLineCount()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.updBeginNum = new System.Windows.Forms.NumericUpDown();
this.updSpace = new System.Windows.Forms.NumericUpDown();
this.btnInsert = new System.Windows.Forms.Button();
this.btnClose = new System.Windows.Forms.Button();
this.chkIsAll = new System.Windows.Forms.CheckBox();
this.chkHasStyle = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.updBeginNum)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.updSpace)).BeginInit();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(16, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(66, 17);
this.label1.TabIndex = 0;
this.label1.Text = "起始行号:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(8, 48);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(103, 17);
this.label2.TabIndex = 1;
this.label2.Text = "与正文间隔空格:";
//
// updBeginNum
//
this.updBeginNum.Location = new System.Drawing.Point(112, 16);
this.updBeginNum.Name = "updBeginNum";
this.updBeginNum.Size = new System.Drawing.Size(88, 21);
this.updBeginNum.TabIndex = 2;
this.updBeginNum.Value = new System.Decimal(new int[] {
1,
0,
0,
0});
//
// updSpace
//
this.updSpace.Location = new System.Drawing.Point(112, 48);
this.updSpace.Name = "updSpace";
this.updSpace.Size = new System.Drawing.Size(88, 21);
this.updSpace.TabIndex = 3;
this.updSpace.Value = new System.Decimal(new int[] {
2,
0,
0,
0});
//
// btnInsert
//
this.btnInsert.Location = new System.Drawing.Point(224, 16);
this.btnInsert.Name = "btnInsert";
this.btnInsert.Size = new System.Drawing.Size(120, 24);
this.btnInsert.TabIndex = 4;
this.btnInsert.Text = "插入";
this.btnInsert.Click += new System.EventHandler(this.btnInsert_Click);
//
// btnClose
//
this.btnClose.Location = new System.Drawing.Point(224, 48);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(120, 24);
this.btnClose.TabIndex = 5;
this.btnClose.Text = "关闭";
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// chkIsAll
//
this.chkIsAll.Location = new System.Drawing.Point(16, 80);
this.chkIsAll.Name = "chkIsAll";
this.chkIsAll.TabIndex = 6;
this.chkIsAll.Text = "全文插入行号";
//
// chkHasStyle
//
this.chkHasStyle.Location = new System.Drawing.Point(152, 80);
this.chkHasStyle.Name = "chkHasStyle";
this.chkHasStyle.Size = new System.Drawing.Size(160, 24);
this.chkHasStyle.TabIndex = 7;
this.chkHasStyle.Text = "保留文本原有格式(慢)";
//
// frmLineCount
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(368, 117);
this.ControlBox = false;
this.Controls.Add(this.chkHasStyle);
this.Controls.Add(this.chkIsAll);
this.Controls.Add(this.btnClose);
this.Controls.Add(this.btnInsert);
this.Controls.Add(this.updSpace);
this.Controls.Add(this.updBeginNum);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "frmLineCount";
this.Text = "插入行号";
this.TopMost = true;
((System.ComponentModel.ISupportInitialize)(this.updBeginNum)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.updSpace)).EndInit();
this.ResumeLayout(false);
}
#endregion
//从外界传入的RichTextBox控件
public RichTextBox _rtf = null;
/// <summary>
/// 完成插入功能
/// </summary>
private void OnInsert()
{
//为正确插入行号,必须禁用WordWrap功能
bool OldWordWrapStatus = this._rtf.WordWrap;
if(OldWordWrapStatus)
this._rtf.WordWrap = false;
this.Cursor = Cursors.WaitCursor;
if(this.chkHasStyle.Checked)
this.InsertHasStyle();//有格式插入
else
this.InsertNoStyle();//无格式插入
this.Cursor = Cursors.Default;
//复原原先的WordWrap特性
if(OldWordWrapStatus)
this._rtf.WordWrap = true;
}
/// <summary>
/// 获取选中部分的起始行,结束行和总行号
/// </summary>
/// <param name="startLine"></param>
/// <param name="endLine"></param>
/// <param name="totalLines"></param>
private void GetSelectionLineInfo(ref int startLine, ref int endLine, ref int totalLines)
{
//获取开始和结束行数(相对全文档而言)
startLine = this._rtf.GetLineFromCharIndex(this._rtf.SelectionStart);
endLine = this._rtf.GetLineFromCharIndex(this._rtf.SelectionStart + this._rtf.SelectionLength - 1);
//获取选中的总行数
totalLines = endLine - startLine + 1;
}
/// <summary>
/// 无格式插入,速度快
/// </summary>
private void InsertNoStyle()
{
if(this._rtf == null)
return;
if(this.chkIsAll.Checked)
{
this._rtf.SelectAll();//全文插入行号,则全选文档
}
else if(this._rtf.SelectionLength == 0)//如果是个空文档,则退出
{
return;
}
//获取选中部分的起始行号,结束行号和选中的总行数
int startLine = 0, endLine = 0, totalLines = 0;
this.GetSelectionLineInfo(ref startLine, ref endLine, ref totalLines);
//获取最大行号的数字的位数
int bits = (totalLines + this.updBeginNum.Value - 1).ToString().Length;
//通过StringReader对象来修改字串
System.IO.StringReader strReader = new System.IO.StringReader(this._rtf.SelectedText);//strReader中现在存入了所有所选的文字
string str; //存放从选中文本中读出的行
string retStr = ""; //用于存放加了行号的字串
//读入第一行
str = strReader.ReadLine();
int i = 0;
while(!(str == null))
{
//给每行加上行号
str = this.GetLineNumber((int)(this.updBeginNum.Value + i), bits) + this.Space((int)this.updSpace.Value) + str;
i++;//行数加一
//将修改过的字串存入retStr中。
retStr += str + Environment.NewLine;
//继续读下一行
str = strReader.ReadLine();
}
//用加了行号的文字替换掉原先的内容
this._rtf.SelectedText = retStr;
}
/// <summary>
/// 保存原有文本的格式
/// </summary>
private void InsertHasStyle()
{
if(this._rtf == null)
return;
if(this.chkIsAll.Checked)
{
this._rtf.SelectAll();
this.WindowState = FormWindowState.Minimized;//时间可能较长,最小化窗体先
}
else if(this._rtf.SelectionLength == 0)//如果是个空文档
{
return;
}
//开始行,结束行
//获取开始和结束行数(相对全文档而言)
int startLine = this._rtf.GetLineFromCharIndex(this._rtf.SelectionStart);
int endLine = this._rtf.GetLineFromCharIndex(this._rtf.SelectionStart + this._rtf.SelectionLength - 1);
//获取选中的总行数
int totalLines = endLine - startLine + 1;
//获取最大行号这一数字的位数
int bits = (totalLines + this.updBeginNum.Value - 1).ToString().Length;
//获取起始行第一个字符在整个文档中的索引
int begin = this.GetLineStartCharIndex2(startLine);
//给每行加上行号
for(int i=0; i<totalLines; i++)
{
//防卫性编码,防止数组下标越界
if(i >= this._rtf.Lines.GetLength(0))
return;
//将插入点光标移到每行开头
this._rtf.SelectionStart = begin;
this._rtf.SelectionLength = 0;
this._rtf.SelectionColor = Color.Black;
//在当前行插入行号
this._rtf.SelectedText = this.GetLineNumber((int)(this.updBeginNum.Value + i), bits) + this.Space((int)this.updSpace.Value);
//将插入点移到下一行的开头,之所以要加1,是因为每行最后都有一个未显示出来的换行符
begin += this._rtf.Lines[startLine + i].Length + 1;
}
if(this.chkIsAll.Checked)
{
this.WindowState = FormWindowState.Normal;//复原窗体
this.btnInsert.Focus();
}
}
/// <summary>
/// 返回指定数量的空格
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
private string Space(int count)
{
string str = "";
for(int i=0; i<count; i++)
{
str += " ";
}
return str;
}
/// <summary>
/// 将第几行的数字转为以0打头的字串
/// </summary>
/// <param name="lineIndex">行号</param>
/// <param name="bits">代表总行数的数字的位数</param>
/// <returns></returns>
private string GetLineNumber(int lineIndex, int bits)
{
//将行号转为字串
string lineStr = lineIndex.ToString();
//生成由bits个零组成的字串
string strTemp = "";
for(int i=0; i<bits; i++)
{
strTemp += "0";
}
//'判断一下行号字串的长度
if(lineStr.Length < bits)
{
//若行号位数较少,缺少的位上补0
lineStr = strTemp.Substring(0, bits - lineStr.Length) + lineStr;
}
//向外界返回生成的行号字串
return lineStr;
}
/// <summary>
/// 获取每行第一个字符的索引
/// </summary>
/// <param name="lineIndex">整个文档中每行的行号,从0开始</param>
/// <returns></returns>
private int GetLineStartCharIndex1(int lineIndex)
{
//防卫性编码,防止数组下标越界
if(lineIndex >= this._rtf.Lines.GetLength(0))
return -1;
//第一行第一个字符肯定是0
if(lineIndex == 0)
return 0;
//以下计算行号大于0的行的首字符索引
int charIndex = 0;
for(int i=0; i<lineIndex; i++)
{
//每行最后要多加一个字符的长度
charIndex += this._rtf.Lines[i].Length + 1;
}
return charIndex;
}
#region 第二种获取每行第一个字符索引的方法
//通过调用Win32 API SendMessage来获取每行第一个字符的CharIndex值
[DllImport("User32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd,uint msg, int wp,int lp);
//此常数用于SendMessage函数
private const int EM_LINEINDEX = 0xBB;
//第二种方法,速度快,直接调用Win32API获取每行的首字符索引
private int GetLineStartCharIndex2(int lineIndex)
{
int charIndex = 0;
//每行第一个字符的CharIndex值
charIndex = SendMessage(this._rtf.Handle, EM_LINEINDEX, lineIndex, 0).ToInt32();
return charIndex;
}
#endregion
private void btnInsert_Click(object sender, System.EventArgs e)
{
this.OnInsert();
}
private void btnClose_Click(object sender, System.EventArgs e)
{
this.Hide();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -