C#, Crazy VScroll in RichTextBox, OnVScroll override troubles
<p>I am having trouble with my code here. I am trying to have the RichTextBox that this code is in rewrite its lines when they are not shown and then fill them back in when they are shown. I pretty much have this working but I keep getting really bad scroll bar issues. </p>

<p>I think it is because at some point in UpdateVisibleLines OnVScroll is called, but i dont know when it is. Which in return calls itself a few more times. I just cannot seem to figure out where it is coming from. here is my code, I think this is all that is needed.</p>

<p>Code: </p>

<pre><code>protected override void OnVScroll(EventArgs e)
    {
        //Console.WriteLine("LineCount: " + LineCount + " VisibleLines: " + VisibleLines() + " TopVisibleLine: " + FirstVisibleLine());
        base.OnVScroll(e);
        Console.WriteLine("OnVScroll");
        if (!m_bSelNoChange)
            UpdateVisibleLines();
    }
    protected override void OnResize(EventArgs e)
    {
        //Console.WriteLine("LineCount: " + LineCount + " VisibleLines: " + VisibleLines() + " TopVisibleLine: " + FirstVisibleLine());
        base.OnResize(e);
        Console.WriteLine("Resize");
        UpdateVisibleLines();
    }

    protected override void OnSelectionChanged(EventArgs e)
    {
        base.OnSelectionChanged(e);
        int cavetOffset = SelectionStart - m_nLastCavetPos;
        int sizeOffset = Text.Length - m_nLastKnownSize;

        if (!m_bSelNoChange)
        {
            Console.WriteLine("LineCount: " + LineCount + " VisibleLines: " + VisibleLines() + " TopVisibleLine: " + FirstVisibleLine());

            if (sizeOffset &gt; 0)
            {
                /*if (sizeOffset == 1)
                    //Console.WriteLine("Typed \"" + (Text.Substring(SelectionStart - cavetOffset, sizeOffset)) + "\" At Position " + (SelectionStart - cavetOffset));
                else if (sizeOffset &gt; 1)
                    //Console.WriteLine("Pasted \"" + (Text.Substring(SelectionStart - cavetOffset, sizeOffset)) + "\" At Position " + (SelectionStart - cavetOffset));
                */theText.Text = theText.Text.Insert(SelectionStart - cavetOffset, Text.Substring(SelectionStart - cavetOffset, sizeOffset));
                //Console.WriteLine(theText.Text);
                //UpdateVisibleLines();
            }
            else if (sizeOffset == 0)
            {
                //Console.WriteLine("Moved Caret to " + SelectionStart + " From " + m_nLastCavetPos);
            }
            else
            {
                if (sizeOffset == -1)
                {
                   // Console.WriteLine("Backspaced at " + (SelectionStart - cavetOffset) + " took " + (-sizeOffset) + " Characters");
                    //Console.WriteLine("CavetOffset: " + cavetOffset);
                    if (cavetOffset != 0)
                        theText.Text = theText.Text.Substring(0, (SelectionStart - cavetOffset - 1)) + theText.Text.Substring((SelectionStart - cavetOffset - 1) + (sizeOffset * -1));
                    else
                        theText.Text = theText.Text.Substring(0, (SelectionStart - cavetOffset)) + theText.Text.Substring((SelectionStart - cavetOffset) + (sizeOffset * -1));
                }
                if (sizeOffset &lt; -1)
                {
                    //Console.WriteLine("HiliteDelete at " + ((SelectionStart - cavetOffset) + -sizeOffset) + " deleted " + (-sizeOffset) + " characters");
                    theText.Text = theText.Text.Substring(0, (SelectionStart - cavetOffset)) + theText.Text.Substring((SelectionStart - cavetOffset) + (sizeOffset * -1));
                }
                // Console.WriteLine(theText.Text);
                //UpdateVisibleLines();
            }

            m_nLastKnownSize = Text.Length;
            m_nLastCavetPos = SelectionStart;
        }
    }

    private void UpdateVisibleLines()
    {
        m_bSelNoChange = true;

        int caretPos = SelectionStart;
        if (LineCount &gt; VisibleLines())
        {
            string[] tmpArr = this.Lines;
            for (int i = 0; i &lt; this.LineCount-1; i++)
            {
                if (i &lt; FirstVisibleLine() || i &gt; (FirstVisibleLine() + VisibleLines()))
                {
                    Console.WriteLine("Updating line " + i);
                    int lineLen = tmpArr[i].Length;
                    tmpArr[i] = tmpArr[i].Remove(0, lineLen);
                    for (int j = 0; j &lt;= lineLen-1; j++)
                    {
                        tmpArr[i] = tmpArr[i].Insert(tmpArr[i].Length, ".");
                    }
                }
                else
                {
                    int lineLen = tmpArr[i].Length;
                    tmpArr[i] = tmpArr[i].Remove(0, lineLen);
                    for (int j = 0; j &lt;= lineLen-1; j++)
                    {
                        tmpArr[i] = theText.Lines[i];
                    }
                }
            }
            this.Lines = tmpArr;
        }
        SelectionStart = caretPos;

        m_bSelNoChange = false;
    }

    private int VisibleLines()
    {
        //Get the height of the text area.
        int height = TextRenderer.MeasureText(this.Text, this.Font).Height;
        //rate = visible height / Total height.
        float rate = (1.0f * this.Height) / height;
        //Get visible lines.
        return (int)(this.Lines.Length * rate);
    }

    public int LineCount
    {
        get
        {
            Message msg = Message.Create(this.Handle, EM_VISIBLELINES, IntPtr.Zero, IntPtr.Zero);
            base.DefWndProc(ref msg);
            return msg.Result.ToInt32();
        }
    }
    private int FirstVisibleLine()
    {
        //return this.GetCharIndexFromPosition(new Point(0, 0));
        return this.GetLineFromCharIndex(this.GetCharIndexFromPosition(new Point(1, 1)));
    }
</code></pre>
