1. 程式人生 > >c# RichTextBox顯示行號,滾動條繫結,取消閃爍,對齊準確

c# RichTextBox顯示行號,滾動條繫結,取消閃爍,對齊準確

這兩天都在看RichTextBox行號問題,發現網上的實現方式都有各種各樣的問題
要麼是 對齊不準,要麼是閃爍,要麼滾動條繫結有問題
結合各篇文章最後 就寫了一個相對完美解決方案

效果圖
這裡寫圖片描述
思路:
1.新建控制元件繼承自RichTextBox
2.設定SelectionIndent 使這個現實區域向右移動
3.在移動出來的空白區域顯示一個panl 使用Graphics 繪圖 繪製行號內容
4.繫結繪製事件到 OnTextChanged OnVScroll

閃爍問題解決:
首先使用雙緩衝技術,發現還是閃爍
最終使用的方案是 先在一張圖上繪製,繪製完畢之後 把圖繪到空白區域

最終原始碼:

public class AdaScrollRichTextBox:RichTextBox
    {
        Panel panel1;
        public AdaScrollRichTextBox()
        {
            InitializeLineId();
        }

        private void InitializeLineId()
        {
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw
| ControlStyles.AllPaintingInWmPaint, true); this.panel1 = new Panel(); this.panel1.Font = new System.Drawing.Font("宋體", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.panel1.Width = 35; this.panel1.Dock
= DockStyle.Left; this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(5)))), ((int)(((byte)(5)))), ((int)(((byte)(5))))); this.SelectionIndent = 35; this.Controls.Add(this.panel1);Controls。 } public void showLineNo() { this.SelectionIndent = 35; Point p = this.Location; int crntFirstIndex = this.GetCharIndexFromPosition(p); int crntFirstLine = this.GetLineFromCharIndex(crntFirstIndex); Point crntFirstPos = this.GetPositionFromCharIndex(crntFirstIndex); p.Y += this.Height; int crntLastIndex = this.GetCharIndexFromPosition(p); int crntLastLine = this.GetLineFromCharIndex(crntLastIndex); Point crntLastPos = this.GetPositionFromCharIndex(crntLastIndex); //準備畫圖 Graphics g = this.panel1.CreateGraphics(); //新建圖,之後的繪製在圖上進行,繪製完畢之後繪製到g上 Bitmap bufferimage = new Bitmap(this.panel1.Width, this.panel1.Height); Graphics g1 = Graphics.FromImage(bufferimage); g1.Clear(this.BackColor); g1.SmoothingMode = SmoothingMode.HighQuality; //高質量 g1.PixelOffsetMode = PixelOffsetMode.HighQuality; //高畫素偏移質量 Font font = new Font(this.Font, this.Font.Style); SolidBrush brush = new SolidBrush(Color.Green); //畫圖開始 Rectangle rect = this.panel1.ClientRectangle; brush.Color = this.panel1.BackColor; g1.FillRectangle(brush, 0, 0, this.panel1.ClientRectangle.Width, this.panel1.ClientRectangle.Height); brush.Color = Color.Green; //繪製行號 int lineSpace = 0; if (crntFirstLine != crntLastLine) { lineSpace = (crntLastPos.Y - crntFirstPos.Y) / (crntLastLine - crntFirstLine); } else { lineSpace = Convert.ToInt32(this.Font.Size); } //這裡2.6引數可以按程式碼實際修改 int brushX = this.panel1.ClientRectangle.Width - Convert.ToInt32(font.Size * 2.6); //這裡0.1引數可以按程式碼實際修改 int brushY = crntLastPos.Y + Convert.ToInt32(font.Size * 0.1f); for (int i = crntLastLine; i >= crntFirstLine; i--) { g1.DrawString((i + 1).ToString(), font, brush, brushX, brushY); brushY -= lineSpace; } g.DrawImage(bufferimage, 0, 0); g1.Dispose(); g.Dispose(); font.Dispose(); brush.Dispose(); } protected override void OnTextChanged(EventArgs e) { showLineNo(); base.OnTextChanged(e); } protected override void OnVScroll(EventArgs e) { showLineNo(); base.OnVScroll(e); } }