c# RichTextBox顯示行號,滾動條繫結,取消閃爍,對齊準確
阿新 • • 發佈:2019-02-01
這兩天都在看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);
}
}