【C#】行番号付きリッチテキストボックス

C#

できること

  • 行番号付きのリッチテキストボックスを実現
  • ユーザは行番号部分を編集できない、
  • テキスト部分のみ編集可能

サンプルコード

RichTextBoxを継承したクラスを作成してビルド。成功するとツールボックスにRichTextBoxLNが表示されるので、フォームに配置して使用します。namespaceは自身の環境に合わせて変更してください。

バグ等含まれている可能性ありますので、ご自身でデバッグをお願いします。

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices; // DllImport

namespace RichTextBoxWithLineNumber
{
    class RichTextBoxLN : RichTextBox
    {
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
        const int WM_PAINT = 15;
        const int EM_SETMARGINS = 0xD3;

        // 左端マージン
        public int LeftMargin = 50;

        public new string Text
        {
            // そのまま取得
            get { return base.Text; }
            // マージン設定してテキストをセット
            set { SetLeftMargin(); base.Text = value; }
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_PAINT)
            {
                Invalidate();
                base.WndProc(ref m);
                using (Graphics g = base.CreateGraphics())
                {
                    DrawLineNo(g);
                }
            }
            else
            {
                base.WndProc(ref m);
            }
        }

        private void SetLeftMargin()
        {
            SendMessage(this.Handle, EM_SETMARGINS, (IntPtr)1, (IntPtr)LeftMargin);
        }

        protected void DrawLineNo(Graphics g)
        {
            // 指定位置に最も近い文字のインデックスを取得
            int charIndex = this.GetCharIndexFromPosition(new Point(LeftMargin, 0));

            // コントロールのテキスト内の指定した文字位置から行番号(0から始まる)を取得
            int lineIndex = this.GetLineFromCharIndex(charIndex);

            for (; lineIndex < this.Lines.Length; lineIndex++)
            {
                // 指定された行の先頭文字のインデックスを取得
                charIndex = this.GetFirstCharIndexFromLine(lineIndex);
                if (charIndex < 0) break;

                // 指定の文字インデックスにおけるコントロール内の位置を取得
                Point point = this.GetPositionFromCharIndex(charIndex);
                if (point.Y > this.ClientRectangle.Height) break;

                // 行番号を描画
                string strLineNo = (lineIndex + 1).ToString();
                g.DrawString(strLineNo, this.Font, Brushes.Black, new PointF(0, point.Y));
            }
        }
    }
}

■参考(背景描画の仕方について下記を参考にしました)
https://stackoverflow.com/questions/16989957/drawing-over-richtextbox

タイトルとURLをコピーしました