也谈制作带行号的Richtextbox

    技术2022-05-11  63

     

    以上是设计时的效果图,

    下面是运行时效果图:

    控件实现的主要功能:

    序号描述1自动计算行高绘制序号(回车,输入,粘贴,鼠标移动,键盘移动都没有问题)2绘制序号外围的边框3可以随着光标移动的当前行标志.(图片中的粉色矩形,当然也可以设置为图标.)4双击每行序号前的部分可以实现类似设置"断点"符号的功能.(例如,上图中的第2行和第6行)5序号右侧的绿色(虚线)分割线.6顶部的标尺(只提供类似WORD的点击标尺后,在RICHTEXTBOX中绘制对应位置的虚线.)

     

    最近做了一些控件,这个带行号有标尺的RICHTEXTBOX是其中之一.由于一些原因,这里只谈一下设计思路,控件本身由几个部分组成,一为一个继承了Richtextbox的控件(Jcsrtx),该控件主要实现了返回当前工作区看到的第一行字符的行号VisibleIndex,光标所在行的CursorIndex,在一系列的ON 前缀textchange,resize,mousedown,mousehover,vscroll方法中引发一公共事件EventTriger,二为一个布局在左侧的Pictruebox控件(Leftpix),在复合控件中对让EventTriger事件来响应Leftpix的Invalidate();来达到及时刷新行号的目的,在Leftpix的PAINT中来绘制Jcsrtx的从VisibleIndex到ClientRangle的所有行的行号.计算时高度采用每2行的POINT.Y的差,这样当因为字号不同时也不会影响效果.

    部分源代码:

     

    private   bool  _ismove  =   false ;         void  toppix_MouseUp( object  sender, MouseEventArgs e)         {            this._ismove = false;            this.Jcsrtx.Invalidate();        }              void  toppix_MouseDown( object  sender, MouseEventArgs e)         {            if (e.Button == MouseButtons.Left)                this._ismove = true;            Graphics g = this.Jcsrtx.CreateGraphics();            using (Pen p = new Pen(Color.Black), backpen = new Pen(SystemColors.WindowText))            {                p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;                p.Width = 1;                g.DrawLine(p, e.X - this.toppix.MoveValue+11, e.X - this.toppix.MoveValue+1this.Height - 3);            }        }          // void toppix_MouseMove(object sender, MouseEventArgs e)         // {         //     if (this._ismove)         //     {         //         Graphics g = this.Jcsrtx.CreateGraphics();         //         using (Pen p = new Pen(Color.Black), backpen= new Pen(SystemColors.WindowText ))         //         {         //             g.DrawLine(backpen, e.X , 1, e.X, this.Height - 3);         //             p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;         //             p.Width = 2;         //             g.DrawLine(p, e.X, 1, e.X, this.Height - 3);         //         }         //     }                   // }                void  numpix_Resize( object  sender, EventArgs e)         {            this.toppix.MoveValue = this.numpix.Width + 5;        }          void  numpix_MouseDoubleClick( object  sender, MouseEventArgs e)         {            if (this._israismouseclick)                GetMouseClickIndex(e.Y);        }          private   int  GetMouseClickIndex( int  value)         {            int clickindex = -1;            int clicky = 0;            int clickend = 0;            int firstindex = this.Jcsrtx.GetFirstVisbleRowIndex();            Graphics rtxgra = this.Jcsrtx.CreateGraphics();            int i = firstindex;            int rectheight = this.numpix.Height;            int sumheight = 0;            while (rectheight > sumheight)            {                if (i > this.Jcsrtx.Lines.Length - 1)                    break;                int index = Jcsrtx.GetFirstCharIndexFromLine(i);                int nextindex = Jcsrtx.GetFirstCharIndexFromLine(i + 1);                Point p = Jcsrtx.GetPositionFromCharIndex(index);                Point nextp = new Point(00);                if (i < this.Jcsrtx.Lines.Length - 1)                {                    nextp = Jcsrtx.GetPositionFromCharIndex(nextindex);                }                if (i == this.Jcsrtx.Lines.Length - 1)                {                    string firstchar = this.Jcsrtx.GetCharFromPosition(p).ToString();//this.rtx.Lines[i].ToString();                    if (firstchar.Trim() == "")                    {                        firstchar = "W";                    }                    SizeF size = rtxgra.MeasureString(firstchar, this.Jcsrtx.Font);                    if (value >= p.Y & value <= p.Y + size.Height + 2)                    {                        clickindex = i;                        clicky = p.Y;                        clickend = (int)(size.Height + 1);                        break;                    }                }                else                {                    if (value >= p.Y & value <= nextp.Y)                    {                        clickindex = i;                        clicky = p.Y;                        clickend = nextp.Y - p.Y;                        break;                    }                }                i++;            }            if (clickindex == -1)                return -1;            Graphics g = this.numpix.CreateGraphics();            if (this.PointList.Contains(clickindex))            {                this.PointList.Remove(clickindex);                this.numpix.Invalidate();            }            else            {                this.PointList.Add(clickindex);                //g.DrawIcon(new Icon("Icon1.ico"), new Rectangle(1,clicky +1,15,clickend ));                this.numpix.Invalidate();            }            return 0;        }

    最新回复(0)