当前位置: 移动技术网 > IT编程>开发语言>.net > Winform中使用用户控件实现带行数和标尺的RichTextBox(附代码下载)

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

2020年03月11日  | 移动技术网IT编程  | 我要评论

displaylink,恶弟的强宠,寡人之疾txt下载

场景

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

效果

 

 

 

注:

博客主页:

关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

新建一个用户控件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;//返回文本信息的宽度
            else
                return titheight;//返回文本信息的高度
        }
        #endregion
    }
}

 

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

 

 

代码下载

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网