场景

RichTextBox控件允许用户输入和编辑文本的同时提供了比普通的TextBox控件更高级的格式特征。

效果

注:

博客主页:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

新建一个用户控件GuageRichTextBox。

编辑用户控件,相当于自己定义了一个控件,和其他控件一样在窗体中使用,是一个类。

然后打开其设计页面,放置一个RichTextBox

然后进入其代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace 带行数和标尺的RichTextBox
{public partial class GuageRichTextBox : UserControl{public GuageRichTextBox(){InitializeComponent();richTextBox1.WordWrap = false;richTextBox1.Top = Distance_X;richTextBox1.Left = Distance_Y;richTextBox1.Width = this.Width - Distance_X - 2;richTextBox1.Height = this.Height - Distance_Y - 2;}#region 变量及常量const int Distance_X = 30;//设置RichTextBox控件的X位置const int Distance_Y = 30;//设置RichTextBox控件的Y位置const int SpaceBetween = 3;//设置标尺的间距public static float thisleft = 0;//设置控件的左边距public static float StartBitH = 0;//记录横向滚动条的位置public static float StartBitV = 0;//记录纵向滚动条的位置const int Scale1 = 3;//设置刻度最短的线长const int Scale5 = 6;//设置刻度为5时的线长const int Scale10 = 9;//设置刻度为10是垢线长public static float Degree = 0;//度数public static float CodeSize = 1;//代码编号的宽度#endregion#region 属性[Browsable(true), Category("设置标尺控件"), Description("设置RichTextBox控件的相关属性")] //在“属性”窗口中显示DataStyle属性public RichTextBox NRichTextBox{get { return richTextBox1; }}public enum Ruler{Graduation = 0,//刻度Rule = 1,//尺子}private bool TCodeShow = false;[Browsable(true), Category("设置标尺控件"), Description("是否在RichTextBox控件的前面添加代码的行号")] //在“属性”窗口中显示DataStyle属性public bool CodeShow{get { return TCodeShow; }set{TCodeShow = value;this.Invalidate();}}private Ruler TRulerStyle = Ruler.Graduation;[Browsable(true), Category("设置标尺控件"), Description("设置标尺样式:\nGraduation为刻度\nRule为尺子")] //在“属性”窗口中显示DataStyle属性public Ruler RulerStyle{get { return TRulerStyle; }set{TRulerStyle = value;this.Invalidate();}}public enum Unit{Cm = 0,//厘米Pels = 1,//像素}private Unit TUnitStyle = Unit.Cm;[Browsable(true), Category("设置标尺控件"), Description("设置标尺的单位:\nCm为厘米\nPels为像素")] //在“属性”窗口中显示DataStyle属性public Unit UnitStyle{get { return TUnitStyle; }set{TUnitStyle = value;this.Invalidate();}}#endregion#region 事件private void GuageRichTextBox_Paint(object sender, PaintEventArgs e){e.Graphics.DrawRectangle(new Pen(Color.DarkGray), 0, 0, this.Width - 1, this.Height - 1);//绘制外边框if (CodeShow)//如查在文本框左边添加行号{//获取行号的宽度float tem_code = (float)StringSize((Convert.ToInt32(CodeSize+(float)(richTextBox1.Height / (StringSize(CodeSize.ToString(), richTextBox1.Font, false))))).ToString(),this.Font, true);richTextBox1.Top = Distance_X;//设置控件的顶端距离richTextBox1.Left = Distance_Y + (int)Math.Ceiling(tem_code);//设置控件的左端距离richTextBox1.Width = this.Width - Distance_X - 2 - (int)Math.Ceiling(tem_code);//设置控件的宽度richTextBox1.Height = this.Height - Distance_Y - 2;//设置控件高度thisleft = Distance_Y + tem_code;//设置标尺的左端位置}else{richTextBox1.Top = Distance_X;//设置控件的顶端距离richTextBox1.Left = Distance_Y;//设置控件的左端距离richTextBox1.Width = this.Width - Distance_X - 2;//设置控件的宽度richTextBox1.Height = this.Height - Distance_Y - 2;//设置控件高度thisleft = Distance_Y;//设置标尺的左端位置}//绘制文本框的边框e.Graphics.DrawRectangle(new Pen(Color.LightSteelBlue), richTextBox1.Location.X - 1, thisleft - 1, richTextBox1.Width + 1, richTextBox1.Height + 1);e.Graphics.FillRectangle(new SolidBrush(Color.Silver), 1, 1, this.Width - 2, Distance_Y - 2);//文本框的上边框e.Graphics.FillRectangle(new SolidBrush(Color.Silver), 1, 1, Distance_X - 2, this.Height - 2);//文本框的左边框e.Graphics.FillRectangle(new SolidBrush(Color.Gray), 3, 3, Distance_X - 7, Distance_Y - 8);//绘制左上角的方块边框e.Graphics.DrawRectangle(new Pen(SystemColors.Control), 3, 3, Distance_X - 8, Distance_Y - 8);//绘制左上角的方块if (RulerStyle == Ruler.Rule)//标尺{//绘制上边的标尺背景e.Graphics.FillRectangle(new SolidBrush(Color.Gray), thisleft - 3, 3, this.Width - (thisleft - 2) , Distance_Y - 9);//绘制左上角的方块边框e.Graphics.DrawLine(new Pen(SystemColors.Control), thisleft - 3, 3, this.Width - 2, 3);//绘制方块的上边线e.Graphics.DrawLine(new Pen(SystemColors.Control), thisleft - 3, Distance_Y - 5, this.Width - 2, Distance_Y - 5);//绘制方块的下边线e.Graphics.FillRectangle(new SolidBrush(Color.WhiteSmoke), thisleft - 2, 9, this.Width - (thisleft - 2) - 1, Distance_Y - 19);//绘制方块的中间块//绘制左边的标尺背景e.Graphics.FillRectangle(new SolidBrush(Color.Gray), 3, Distance_Y - 3, Distance_X - 7, this.Height - (Distance_Y - 3) - 2);//绘制左边的方块e.Graphics.DrawLine(new Pen(SystemColors.Control), 3, Distance_Y - 3, 3, this.Height - 2);//绘制方块的左边线e.Graphics.DrawLine(new Pen(SystemColors.Control), Distance_X - 5, Distance_Y - 3, Distance_X - 5, this.Height - 2);//绘制方块的右边线e.Graphics.FillRectangle(new SolidBrush(Color.WhiteSmoke), 9, Distance_Y - 3, Distance_X - 19, this.Height - (Distance_Y - 3) - 2);//绘制方块的中间块}int tem_temHeight = 0;string tem_value = "";int tem_n = 0;int divide = 5;Pen tem_p = new Pen(new SolidBrush(Color.Black));//横向刻度的设置if (UnitStyle == Unit.Cm)//如果刻度的单位是厘米Degree = e.Graphics.DpiX / 25.4F;//将像素转换成毫米if (UnitStyle == Unit.Pels)//如果刻度的单位是像素Degree = 10;//设置10像素为一个刻度int tem_width = this.Width - 3;tem_n = (int)StartBitH;//记录横向滚动条的位置if (tem_n != StartBitH)//如果横向滚动条的位置值为小数StartBitH = (int)StartBitH;//对横向滚动条的位置进行取整for (float i = 0; i < tem_width; )//在文本框的项端绘制标尺{tem_temHeight = Scale1;//设置刻度线的最小长度float j = (i + (int)StartBitH) / Degree;//获取刻度值tem_value = "";j = (int)j;//对刻度值进行取整if (j % (divide * 2) == 0)//如果刻度值是10进位{tem_temHeight = Scale10;//设置最长的刻度线if (UnitStyle == Unit.Cm)//如果刻度的单位为厘米tem_value = Convert.ToString(j / 10);//记录刻度值if (UnitStyle == Unit.Pels)//如果刻度的单位为像素tem_value = Convert.ToString((int)j * 10);//记录刻度值}else if (j % divide == 0)//如果刻度值的进位为5{tem_temHeight = Scale5;//设置刻度线为中等}tem_p.Width = 1;if (RulerStyle == Ruler.Graduation)//如果是以刻度值进行测量{//绘制刻度线e.Graphics.DrawLine(tem_p, i + 1 + thisleft, SpaceBetween, i + 1 + thisleft, SpaceBetween + tem_temHeight);if (tem_value.Length > 0)//如果有刻度值//绘制刻度值ProtractString(e.Graphics, tem_value.Trim(), i + 1 + thisleft, SpaceBetween, i + 1 + thisleft, SpaceBetween + tem_temHeight, 0);}if (RulerStyle == Ruler.Rule)//如果是以标尺进行测量{if (tem_value.Length > 0)//如果有刻度值{e.Graphics.DrawLine(tem_p, i + 1 + thisleft, 4, i + 1 + thisleft, 7);//绘制顶端的刻度线e.Graphics.DrawLine(tem_p, i + 1 + thisleft, Distance_Y - 9, i + 1 + thisleft, Distance_Y - 7);//绘制底端的刻度线float tem_space = 3 + (Distance_X - 19F - 9F - StringSize(tem_value.Trim(),this.Font, false)) / 2F;//设置文本的横向位置//绘制文本ProtractString(e.Graphics, tem_value.Trim(), i + 1 + thisleft, (float)Math.Ceiling(tem_space), i + 1 + thisleft, (float)Math.Ceiling(tem_space) + tem_temHeight, 0);}}i += Degree;//累加刻度的宽度}//纵向刻度的设置if (UnitStyle == Unit.Cm)//如果刻度的单位是厘米Degree = e.Graphics.DpiX / 25.4F;//将像素转换成毫米if (UnitStyle == Unit.Pels)//如果刻度的单位是像素Degree = 10;//刻度值设为10像素int tem_height = this.Height - 3;tem_n = (int)StartBitV;//记录纵向滚动条的位置if (tem_n != StartBitV)//如果纵向滚动条的位置为小数StartBitV = (int)StartBitV;//对其进行取整for (float i = 0; i < tem_height; )//在文本框的左端绘制标尺{tem_temHeight = Scale1;//设置刻度线的最小值float j = (i + (int)StartBitV) / Degree;//获取当前的刻度值tem_value = "";j = (int)j;//对刻度值进行取整if (j % 10 == 0)//如果刻度值是10进位{tem_temHeight = Scale10;//设置刻度线的长度为最长if (UnitStyle == Unit.Cm)//如果刻度的单位是厘米tem_value = Convert.ToString(j / 10);//获取厘米的刻度值if (UnitStyle == Unit.Pels)//如果刻度的单位是像素tem_value = Convert.ToString((int)j * 10);//获取像素的刻度值}else if (j % 5 == 0)//如果刻度值是5进位{tem_temHeight = Scale5;//设置刻度线的长度为中等}tem_p.Width = 1;if (RulerStyle == Ruler.Graduation)//如果是以刻度值进行测量{//绘制刻度线e.Graphics.DrawLine(tem_p, SpaceBetween, i + 1 + Distance_Y, SpaceBetween + tem_temHeight, i + 1 + Distance_Y);if (tem_value.Length > 0)//如果有刻度值//绘制刻度值ProtractString(e.Graphics, tem_value.Trim(), SpaceBetween, i + 1 + Distance_Y, SpaceBetween + tem_temHeight, i + 1 + Distance_Y, 1);}if (RulerStyle == Ruler.Rule)//如果是以标尺进行测量{if (tem_value.Length > 0)//如果有刻度值{e.Graphics.DrawLine(tem_p, 4, i + 1 + Distance_Y, 7, i + 1 + Distance_Y);//绘制左端刻度线e.Graphics.DrawLine(tem_p, Distance_Y - 9, i + 1 + Distance_Y, Distance_Y - 7, i + 1 + Distance_Y);//绘制右端刻度线float tem_space = 3 + (Distance_X - 19F - 9F - StringSize(tem_value.Trim(),this.Font, false)) / 2F;//设置文本的纵向位置//绘制文本ProtractString(e.Graphics, tem_value.Trim(), (float)Math.Floor(tem_space), i + 1 + Distance_Y, (float)Math.Floor(tem_space) + tem_temHeight, i + 1 + Distance_Y, 1);}}i += Degree;//累加刻度值}if (CodeShow)//如果显示行号{//设置文本的高度float tem_FontHeight = (float)(richTextBox1.Height / (StringSize(CodeSize.ToString(), richTextBox1.Font, false)));float tem_tep = richTextBox1.Top;//获取文本框的顶端位置int tem_mark = 0;for (int i = 0; i < (int)tem_FontHeight; i++)//绘制行号{tem_mark = i + (int)CodeSize;//设置代码编号的宽度//绘制行号e.Graphics.DrawString(tem_mark.ToString(), this.Font, new SolidBrush(Color.Red), new PointF(richTextBox1.Left - StringSize(tem_mark.ToString(), this.Font, true) - 2, tem_tep));tem_tep = tem_tep + StringSize("懂", richTextBox1.Font, false);//设置下一个行号的X坐标值}}}private void GuageRichTextBox_Resize(object sender, EventArgs e){richTextBox1.Top = Distance_X;//设置控件的顶端位置richTextBox1.Left = Distance_Y;//设置控件的左端位置richTextBox1.Width = this.Width - Distance_X - 2;//设置控件的宽度richTextBox1.Height = this.Height - Distance_Y - 2;//设置控件的高度this.Invalidate();}private void richTextBox1_HScroll(object sender, EventArgs e){StartBitH = (int)(Math.Abs((float)richTextBox1.GetPositionFromCharIndex(0).X - 1));//检索控件横向内指定字符索引处的位置this.Invalidate();}private void richTextBox1_VScroll(object sender, EventArgs e){StartBitV = (int)(Math.Abs((float)richTextBox1.GetPositionFromCharIndex(0).Y - 1));//检索控件纵向内指定字符索引处的位置if (CodeShow)//如果显示行号CodeSize = (int)Math.Abs((richTextBox1.GetPositionFromCharIndex(0).Y / StringSize("懂", richTextBox1.Font, false)));//设置行号的高度this.Invalidate();}#endregion#region 方法/// <summary>/// 在指定的位置绘制文本信息/// </summary>/// <param e="Graphics">封装一个绘图的类对象</param>/// <param str="string">文本信息</param>/// <param x1="float">左上角x坐标</param>/// <param y1="float">左上角y坐标</param>/// <param x2="float">右下角x坐标</param>/// <param y2="float">右下角y坐标</param>/// <param n="float">标识,判断是在横向标尺上绘制文字还是在纵向标尺上绘制文字</param>public void ProtractString(Graphics e, string str, float x1, float y1, float x2, float y2, float n){float TitWidth = StringSize(str,this.Font, true);//获取字符串的宽度if (n == 0)//在横向标尺上绘制文字e.DrawString(str, this.Font, new SolidBrush(Color.Black), new PointF(x2 - TitWidth / 2, y2 + 1));else//在纵向标尺上绘制文字{StringFormat drawFormat = new StringFormat();//实例化StringFormat类drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;//设置文本为垂直对齐//绘制指定的文本e.DrawString(str, this.Font, new SolidBrush(Color.Black), new PointF(x2 + 1, y2 - TitWidth / 2), drawFormat);}}/// <summary>/// 获取文本的高度或宽度/// </summary>/// <param str="string">文本信息</param>/// <param font="Font">字体样式</param>/// <param n="bool">标识,判断返回的是高度还是宽度</param>public float StringSize(string str,Font font,bool n)//n==true为width{Graphics TitG = this.CreateGraphics();//创建Graphics类对象SizeF TitSize = TitG.MeasureString(str, font);//将绘制的字符串进行格式化float TitWidth = TitSize.Width;//获取字符串的宽度float TitHeight = TitSize.Height;//获取字符串的高度if (n)return TitWidth;//返回文本信息的宽度elsereturn TitHeight;//返回文本信息的高度}#endregion}
}

右击项目,生成一下,就可以看到窗体的工具箱上面多了一组工具,可以看到我们定义的控件

代码下载

https://download.csdn.net/download/BADAO_LIUMANG_QIZHI/12240495

Winform中使用用户控件实现带行数和标尺的RichTextBox(附代码下载)相关推荐

  1. c#在WinForm中重写ProgressBar控件(带%的显示)

    c#在WinForm中重写ProgressBar控件(带%的显示) 2009-05-14 13:13 #region 定义textProgressBar控件的类 namespace csPublish ...

  2. C#语言实例源码系列-实现带行数和标尺的RichTextBox

    专栏分享 点击跳转=>Unity3D特效百例 点击跳转=>案例项目实战源码 点击跳转=>游戏脚本-辅助自动化 点击跳转=>Android控件全解手册

  3. Winform中实现实时颜色拾取器显示RGB和16进制颜色(附代码下载)

    场景 效果 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 新建一个窗体 ...

  4. 关于从页面中获取用户控件中的其它控件(如DropDownList)事件的方法

    在项目中经常把一些经常使用的代码做成用户控件以提高代码的可重用性, 一个经常遇到的就是在页面中调用用户控件中的服务器控件的事件,下面给出简单的代码示列. 我们在一个用户控件(MaterialRepor ...

  5. 使用观察者模式在 Silverlight 中切换用户控件

    有一篇技巧,见 http://tech.sina.com.cn/s/2008-07-03/1528718607.shtml 或 http://kb.cnblogs.com/page/42897/?pa ...

  6. 技巧:在Silverlight 2应用程序中切换用户控件

    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://terrylee.blog.51cto.com/342737/85341 ...

  7. WinForm中使用Excel控件

     最近项目中要在WinForm中使用Excel控件,经过几天的研究,现在总结一下成果. 在WinForm中使用Excel控件主要有三种方法:WebBrowser.DSOFramer.OWC.下面分别 ...

  8. winform中使用ZedGraphControl控件做图

    winform中使用ZedGraphControl控件做图. 一些方法的总结 public class ChartEx : ZedGraph.ZedGraphControl{#region initp ...

  9. WinForm中关于DataGridView控件的一些应用

    转载于新浪 美林居士 的博客:            blog.sina.com.cn/s/blog_797a56d20101daiw.html4 在.NET4.0中,以表格形式存储的数据通常是Dat ...

最新文章

  1. 《机器学习》、《算法数据结构》、《LeetCode原创题解》开放下载!
  2. 20岁的谷歌,和它“最成功”的大败笔
  3. python matplotlab.pyplot.grid() 函数
  4. HTML标签类型及特点
  5. linux安装nagios客户端
  6. c# 中如何设置combox 让出现text value两个值 winform开发
  7. 马斯克2021五大预测:重返月球并比赛遥控汽车,全面实现自动驾驶,你pick哪一个?...
  8. oracle odi 资料档案库访问期间出现未分类的异常错误,oracle学习_基本语法
  9. PMC联手云合作伙伴Canonical加入其Ubuntu OpenStack互通性实验室
  10. [教程]控制反转(IoC)与依赖注入(DI)
  11. 毕业设计!Python实现学生教师刷脸签到系统
  12. 天翼网关 ddns设置_UCloud物理云网关百G级集群设计实践
  13. 雅加达建筑_雅加达EE:干净的板岩
  14. The import com. cannot be resolved
  15. 【信息系统项目管理师】第十二章 项目采购管理思维导图
  16. 有道云笔记markdown字体增大、生成目录
  17. (Arduino)蓝牙和 APPinventor实现一键SOS求救(一)
  18. 异常篇 之 记录一次因“MIUI 优化”引发的无奈。。。
  19. EasyExcel 筛选导出
  20. 3.【Python编程】字典Dict相关知识及基本操作

热门文章

  1. 王道计算机考研 数据结构 (树与二叉树)
  2. Java线程6个状态详解
  3. Java进阶:多线程Lock管理多个Condition的实践
  4. 运城学院数学与计算机系,运城学院数学与信息技术学院.doc
  5. 《Spring Cloud微服务架构开发实战》_董超笔记
  6. 遮挡摄像头 判断_长治一学校门口树枝遮挡信号灯,危险!
  7. python类与继承person类_关于python中类的继承及self
  8. tarjan算法_【朝夕的ACM笔记】树上问题-最近公共祖先-倍增算法
  9. Chrome浏览器官方离线安装包下载
  10. Perl 正则表达式 html,使用正则表达式验证表单中的HTML字段使用perl