带有行数和标尺的RichTextBox

项目需要一个带有行数和标尺功能的RichTextBox,先是打算在RichTextBox里面自画,但最终没有实现,最终用UserControl实现了该功能.
1.原理:
1)行数:在RichTextBox旁边放一个Label,设置Label字体大小,然后在RichTextBox的TextChaged方法中判断是否换行,换行就重新为Label设值.
2)标尺:在RichTextBox上面放一个Panel,在Panel上面画尺.
代码如下:
 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel;
 4using System.Drawing;
 5using System.Data;
 6using System.Text;
 7using System.Windows.Forms;
 8
 9namespace NumberedTextBox
10{
11    public partial class NumberedTextBoxUC : UserControl
12    {
13
14        public NumberedTextBoxUC()
15        {
16            InitializeComponent();
17
18            numberLabel.Font = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size + 1.019f);
19           
20        }

21
22        int _currentLine = 0;
23        public int CurrentLine
24        {
25            get
26            {
27                return _currentLine;
28            }

29            set
30            {
31                _currentLine = value;
32            }

33        }

34        private void updateNumberLabel()
35        {
36            //we get index of first visible char and number of first visible line
37            Point pos = new Point(00);
38            int firstIndex = richTextBox1.GetCharIndexFromPosition(pos);
39            int firstLine = richTextBox1.GetLineFromCharIndex(firstIndex);
40
41            //now we get index of last visible char and number of last visible line
42            pos.X = ClientRectangle.Width;
43            pos.Y = ClientRectangle.Height;
44            int lastIndex = richTextBox1.GetCharIndexFromPosition(pos);
45            int lastLine = richTextBox1.GetLineFromCharIndex(lastIndex);
46            int myStart = this.richTextBox1.SelectionStart;
47            int myLine = this.richTextBox1.GetLineFromCharIndex(myStart) + 1;
48            pos = richTextBox1.GetPositionFromCharIndex(lastIndex);
49            if (lastIndex > _currentLine||lastIndex<_currentLine)
50            {
51                //finally, renumber label
52                numberLabel.Text = "";
53                for (int i = firstLine; i <= lastLine + 1; i++)
54                {
55                    numberLabel.Text += i + 1 + "\n";
56                }

57            }

58            _currentLine = lastIndex;
59            //this is point position of last visible char, we'll use its Y value for calculating numberLabel size 
60
61        }

62
63
64        private void richTextBox1_TextChanged(object sender, EventArgs e)
65        {
66            updateNumberLabel();            
67        }

68
69        private void richTextBox1_VScroll(object sender, EventArgs e)
70        {
71            //move location of numberLabel for amount of pixels caused by scrollbar
72            int d = richTextBox1.GetPositionFromCharIndex(0).Y % (richTextBox1.Font.Height + 1);
73            numberLabel.Location = new Point(0, d);
74
75            updateNumberLabel();
76        }

77
78        private void richTextBox1_Resize(object sender, EventArgs e)
79        {
80            richTextBox1_VScroll(nullnull);
81        }

82
83        private void richTextBox1_FontChanged(object sender, EventArgs e)
84        {
85            updateNumberLabel();
86            richTextBox1_VScroll(nullnull);
87        }
            
88
89
90    }

91}

92
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Drawing;
 5using System.Windows.Forms;
 6
 7namespace Yqun.Client.ReportTools
 8{
 9    public class RulerPanel:Panel
10    {
11        protected override void OnPaint(PaintEventArgs e)
12        {
13            Graphics g = e.Graphics;
14            int top = 0;
15            int width = e.ClipRectangle.Width;
16            int temHeight = 5;
17            for (int i = 0; i < width-5; )
18            {
19                
20                int height = temHeight;
21                int j = i / 5;
22                if (j % 10 == 0)
23                {
24                    height = 15;
25                }

26                else if (j % 5 == 0)
27                {
28                    height = 10;
29                }
               
30                Pen p = new Pen(new SolidBrush(Color.Black));
31                p.Width = 1;
32                g.DrawLine(p, i + 5, top, i + 5, top + height);
33                i += 5;               
34            }

35            g.Flush();
36            base.OnPaint(e);
37        }

38    }

39}

40

最终实现效果图:
posted @ 2006-09-01 09:01  Robin Zhang  阅读(6423)  评论(17编辑  收藏  举报