C# RichTextBox 做簡單的HTML程式碼編輯器 ---------左側顯示行號
阿新 • • 發佈:2019-01-31
說明:此顯示行號為實際行號,不論是空行還是自動換行,都計算在內,跟實際IDE的行號不同,同步滾動會有半行高度以內的誤差。
實現原理,在RichTextBox 編輯器左側放置另一RichTextBox (或其它控制元件也可),行號為編輯器實際文字行數,滾動時計算文字滾動高度,再根據行高算出當前行大約位置,左側自動滾動到當前行。
如果想準確的話,可以不用行,直接拿到文字滾動高度,右側行號也滾動到相應高度即可。
//行號 生成顯示 這裡rtbLineNum用的 RichTextBox,也可以用其它 private void ShowLineNum() { rtbLineNum.Text = ""; //計算行高,行數 int linesLength = 0; var pFirst = tbEditor.GetPositionFromCharIndex(0); var pEnd = tbEditor.GetPositionFromCharIndex(tbEditor.Text.Length); if (pEnd.Y > pFirst.Y) { var pSecondLine = tbEditor.GetPositionFromCharIndex(tbEditor.GetFirstCharIndexFromLine(1)); var lineHeight = pSecondLine.Y - pFirst.Y; linesLength = (pEnd.Y - pFirst.Y) / lineHeight; } else { linesLength = 1; } //生成行數 for (var i = 0; i < linesLength; i++) { rtbLineNum.AppendText(i + 1 + "\n"); } //行號右對齊 rtbLineNum.SelectAll(); rtbLineNum.SelectionAlignment = HorizontalAlignment.Right; } //上次滾動位置 行 private int _scrollToLine = 0; //同步滾動 private void SyncSrollLocation() { //首行首字元初始位置 var p = new Point(1,1); //計算行高 int lineHeight = 0; var pFirst = tbEditor.GetPositionFromCharIndex(0);//首行位置 var pEnd = tbEditor.GetPositionFromCharIndex(tbEditor.Text.Length);//最後一行位置 if (pEnd.Y > pFirst.Y)//排除只有一行的情況 { var pSecondLine = tbEditor.GetPositionFromCharIndex(tbEditor.GetFirstCharIndexFromLine(1)); lineHeight = pSecondLine.Y - pFirst.Y; } //滾動高度 即首行位置移動高度 int scrollHeight = p.Y - pFirst.Y; //滾動到的行的位置 由於滾動大都並非整行滾動 所以四捨五入 ***程式的誤差就在這裡 var scrollTolineIndex = (int)Math.Round((double)(scrollHeight / lineHeight), MidpointRounding.AwayFromZero); if (_scrollToLine != scrollTolineIndex) { _scrollToLine = scrollTolineIndex; var sStart = rtbLineNum.GetFirstCharIndexFromLine(scrollTolineIndex);//左側行號 當前滾動到行 首字元位置 if (sStart >= 0) { rtbLineNum.SelectionStart = sStart; rtbLineNum.SelectionLength = 0; rtbLineNum.ScrollToCaret(); } } } //編輯器 Resize事件 private void tbEditor_Resize(object sender, EventArgs e) { ShowLineNum(); SyncSrollLocation(); } //編輯器 TextChanged事件 private void tbEditor_TextChanged(object sender, EventArgs e) { ShowLineNum(); SyncSrollLocation(); } //編輯器 VScroll事件 private void tbEditor_VScroll(object sender, EventArgs e) { SyncSrollLocation(); }