22822


お世話になります。  
表題の通りなのですがリッチテキストコントロール(winForm)で行毎に背景色を設定したいのですがどのような方法が考えられますでしょうか？

イメージとしてはSyntaxHighlighterのようなイメージです。

RichTextBox.SelectionBackColorを使って出来るかなとも考えましたが改行記号までしか選択出来ないと考えておりますので一行すべての色を変える訳には行かないと見ております。

ご存知の方おられましたらよろしくお願いします。

[![画面イメージ](https://i.stack.imgur.com/eHezH.png)](https://i.stack.imgur.com/eHezH.png)

開発環境  
Windows10  
VB.NET(.NetFramework4.0)  
WinFormアプリケーション


CC BY-SA 3.0
2016-03-04T10:33:22.047
22801
2016-03-06T00:48:05.940
14436
question
vb.net winforms
RichTextBoxで行ごとに背景色を指定したい


背景を透過させて、行ごとに背景を描画

vb

[code]

    Friend Class RichTextBoxEx
        Inherits RichTextBox
    
        Private Const WM_PAINT As Integer = 15
    
        Private Const WS_EX_TRANSPARENT As Integer = 32
    
        Private Gray As Brush = New SolidBrush(Color.FromArgb(255, 240, 240, 240))
    
        Protected Overrides ReadOnly Property CreateParams As CreateParams
            Get
                Dim parms As CreateParams = MyBase.CreateParams
                parms.ExStyle = parms.ExStyle Or WS_EX_TRANSPARENT
                Return parms
            End Get
        End Property
    
        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            If m.Msg = WM_PAINT Then
                Invalidate()
                Using graphic As Graphics = MyBase.CreateGraphics()
                    Dim pevent = New PaintEventArgs(graphic, Me.ClientRectangle)
                    OnPaintBackground(pevent)
                End Using
    
                MyBase.WndProc(m)
            Else
                MyBase.WndProc(m)
            End If
        End Sub
    
        Protected Overrides Sub OnPaintBackground(ByVal pevent As PaintEventArgs)
            MyBase.OnPaintBackground(pevent)
            Dim topleftIndex = Me.GetCharIndexFromPosition(Me.ClientRectangle.Location)
            Dim topleftLine = Me.GetLineFromCharIndex(topleftIndex)
            Dim linefirstIndex As Integer = GetFirstCharIndexFromLine(topleftLine)
            Dim p0 = Me.GetPositionFromCharIndex(topleftIndex)
            Dim lineCharIndexies As List(Of Integer) = New List(Of Integer)()
            lineCharIndexies.Add(0)
            Dim index As Integer = 0
            For Each s As String In Lines
                index += s.Length + 1
                lineCharIndexies.Add(index)
            Next
    
            Dim textLineIndex As Integer = lineCharIndexies.FindIndex(Function(i) i >= topleftIndex)
    
            Do While (textLineIndex < lineCharIndexies.Count - 1 AndAlso p0.Y < Me.ClientRectangle.Bottom)
                Dim nextLineCharIndex As Integer = lineCharIndexies(textLineIndex + 1)
                Dim nextLinePoint = GetPositionFromCharIndex(nextLineCharIndex)
                Dim h = nextLinePoint.Y - p0.Y
                If (textLineIndex Mod 2) = 0 Then
                    Dim rect = New Rectangle(p0.X, p0.Y, Me.ClientRectangle.Width, h)
                    pevent.Graphics.FillRectangle(Gray, rect)
                End If
    
                p0.Y = nextLinePoint.Y
                textLineIndex += 1
            Loop
        End Sub
    End Class
    
[/code]

c#

[code]

    class RichTextBoxEx : RichTextBox
    {
        private const int WM_PAINT = 15;
        private const int WS_EX_TRANSPARENT = 0x20;
        private Brush Gray = new SolidBrush(Color.FromArgb(0xFF,0xF0,0xF0,0xF0));
    
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams parms = base.CreateParams;
                parms.ExStyle |= WS_EX_TRANSPARENT;
                return parms;
            }
        }
    
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_PAINT)
            {
                Invalidate();
                using (Graphics graphic = base.CreateGraphics())
                {
                    var pevent = new PaintEventArgs(graphic, this.ClientRectangle);
                    OnPaintBackground(pevent);
                }
    
                base.WndProc(ref m);
            }
            else
            {
                base.WndProc(ref m);
            }
        }
        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            base.OnPaintBackground(pevent);
            var topleftIndex = this.GetCharIndexFromPosition(this.ClientRectangle.Location);
            var topleftLine = this.GetLineFromCharIndex(topleftIndex);
            int linefirstIndex = GetFirstCharIndexFromLine(topleftLine);
            var p0 = this.GetPositionFromCharIndex(topleftIndex);
    
            List<int> lineCharIndexies = new List<int>();
            lineCharIndexies.Add(0);
            int index = 0;
            foreach (string s in Lines)
            {
                index += s.Length + 1;
                lineCharIndexies.Add(index);
            }
            int textLineIndex = lineCharIndexies.FindIndex(_ => _ >= topleftIndex);
    
            for (; textLineIndex < lineCharIndexies.Count-1 && p0.Y < this.ClientRectangle.Bottom; textLineIndex++)
            {
                int nextLineCharIndex=lineCharIndexies[textLineIndex + 1];
                var nextLinePoint = GetPositionFromCharIndex(nextLineCharIndex);
                var h = nextLinePoint.Y - p0.Y;
    
                if ((textLineIndex % 2) == 0)
                {
                    var rect = new Rectangle(p0.X, p0.Y, this.ClientRectangle.Width, h);
                    pevent.Graphics.FillRectangle(Gray, rect);
                }
                p0.Y = nextLinePoint.Y;
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2016-03-05T02:23:08.393
22822
2016-03-06T00:48:05.940
2016-03-06T00:48:05.940
4926
4926
22801
answer