Larry
Larry

Reputation: 192

WinForm RichTextBox text color changes too many characters

I have been working with an rtf box for a while in my winforms application running as a communcation interface between my external hardware device and my PC over serial. The issue I have is when using any example of colour change for a selection of text (that is sent before my actual command over serial) the echo back from my external device also has some text colour changed as well.

sending the symbol ';' I get the echo back and the reponse from my device all coloured in text.

;;[UART+ERROR]

My recieve event handler is the standard:

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        //fking threading
        string rxString = serialPort1.ReadExisting();    // running on worker thread

        this.Invoke((MethodInvoker)delegate
        {
            textLog.AppendText(rxString);    // runs on UI thread
        });
    }

To write to the screen I used the example below (among many others I have also tried) to get working in my application. I am unsure what I am doing wrong.

    private void AppendTextColor(RichTextBox box, Color color, string text)
    {
        int start = box.TextLength;
        box.AppendText(text);
        int end = box.TextLength;

        // Textbox may transform chars, so (end-start) != text.Length
        box.Select(start, end - start);
        {
            box.SelectionColor = color;
            // could set box.SelectionBackColor, box.SelectionFont too.
        }
        box.SelectionLength = 0; // clear
    }

Upvotes: 1

Views: 324

Answers (2)

Hans Passant
Hans Passant

Reputation: 941465

Your Select() call leaves the SelectionStart property at the start of the appended text instead of end of the text. You could restore it like you did for SelectionLength, but the simpler way to do it is:

    private static void AppendTextColor(RichTextBox box, Color color, string text) {
        box.SelectionStart = box.Text.Length;   // Optional
        var oldcolor = box.SelectionColor;
        box.SelectionColor = color;
        box.AppendText(text);
        box.SelectionColor = oldcolor;
    }

Note the // Optional comment, it isn't needed when the user cannot edit the text.

Do beware that you have a very serious fire-hose problem in your code. You are calling Invoke() at a very high rate, liable to cause the UI thread to start burning 100% core when the box starts filling up. Easy to tell when that happens, you can't see updates anymore and your program stops responding to input. Buffering in the DataReceived event handler is required, using ReadLine() instead of ReadExisting() is usually the simple way to get there. And use BeginInvoke() instead, Invoke() is very likely to cause the SerialPort.Close() call to deadlock.

Upvotes: 2

TaW
TaW

Reputation: 54433

You need to reset the color to the RTB's normal text color:

box.SelectionStart = box.Text.Length; // clear..
box.SelectionLength = 0; // clear     // ..selection
box.SelectionColor = box.ForeColor;   // reset color

Upvotes: 1

Related Questions