问题
I'm working on a program that calls python script and shows the output in richtextbox. I have a problem with coloring specific strings in output. For example: if the string "hey 123" will appear in the output it will colored red. Does someone have an answer? Thanks! snippet of my code:
Process _cmd;
delegate void setTextCallBack(string text);
private void setText (string text)
{
if (this.richTextBox1.InvokeRequired)
{
setTextCallBack d = new setTextCallBack(setText);
this.Invoke(d, new object[] { text });
}
else
{
this.richTextBox1.Text += text + Environment.NewLine;
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}
}
_cmd = new Process();
_cmd.StartInfo = cmdStartInfo;
if (_cmd.Start())
{
_cmd.OutputDataReceived += new DataReceivedEventHandler(_cmd_OutputDataReceived);
_cmd.ErrorDataReceived += new DataReceivedEventHandler(_cmd_ErrorDataReceived);
_cmd.Exited += new EventHandler(_cmd_Exited);
_cmd.BeginOutputReadLine();
_cmd.BeginErrorReadLine();
}
else
{
_cmd = null;
}
void _cmd_Exited(object sender, EventArgs e)
{
_cmd.OutputDataReceived -= new DataReceivedEventHandler(_cmd_OutputDataReceived);
_cmd.Exited -= new EventHandler(_cmd_Exited);
}
void _cmd_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
UpdateConsole(e.Data, Brushes.Red);
}
void _cmd_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
UpdateConsole(e.Data, Brushes.Green);
}
private void UpdateConsole (string text)
{
UpdateConsole(text, null);
}
private void UpdateConsole(string text, Brush color)
{
WriteLine(text, color);
}
private void WriteLine(string text, Brush color)
{
if (text != null)
{
setText(text);
}
}
回答1:
Here is the Golden Rule for RichTextBoxes
: Don't touch the Text!
Do not use richTextBox1.Text += "more text"
to append Text once you have done any coloring or formatting! This will mess up all formatting you have. There are special functions for everything you need, and you need to use those.
To add use
richTextBox1.AppendText("more text")
Other methods you may need when editing are Copy, Paste & Cut
plus of course the select properties and methods, you need for the coloring and formatting as well..
To color a piece of text you need to select it and then apply the Color you want like this:
richTextBox1.SelectionBackColor = Color.MistyRose; // Backcolor
richTextBox1.SelectionColor = Color.Red; // TextColor
Other formatting will use SelectionFont
, SelectionIndent
, SelectionAlignment
and then some..
As you see it all works by first selecting and then working on that selection.
In your code you could change the setText method header to:
setText (string text, Color color)
and change its code like this:
else
{
int start = richTextBox1.Text.Length; //*
richTextBox1.AppendText(text + Environment.NewLine);
richTextBox1.SelectionStart = start; //*
richTextBox1.SelectionLength = text.Length;
richTextBox1.SelectionColor = color;
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.SelectionLength = 0;
richTextBox1.ScrollToCaret();
}
The last three lines are optional; I include them since you seem to want the Caret always at the end..
I would also make it more readable by changing the function's name to something like addText or addColoredText and maybe even make it more flexible by adding a bool parameter to control whether a NewLine
should be added or not..
Update:
I notice that you are also calling the UpdateConsole
and WriteLine
methods with a null
for the Brushes
.
This has two problems:
- We don't need a
Brush
but aColor
for coloring theRichTextBox
. - And you can't pass in a
null
for aColor
.
You could workaround by declaring them to be SolidBrushes
and the using their brush.Color
.
But that is just a useless and confusing twist.
Instead pass in the Color
you want directly and instead of null pass in Black
or the RTF's ForeColor
or a default color you define..:
UpdateConsole(text, Color.Black);
or
UpdateConsole(text, richTextBox1.ForeColor);
etc..
Update 2
Please note the correction (*) in the code; AppendText moves the SelectionStart, so we need to store the start value.
If you have a list of error messages, say
List<string> errors;
You could fill it from a file, maybe like this:
errors = File.ReadAllLines("d:\\errors.txt").ToList();
And then either test for equality:
setText(text, errors.Contains(text) ? Color.Red : Color.Blue);
Or, if only parts match
setText(text, isError(text) ? Color.Red : Color.Blue);
using a function like this:
bool isError(string msg)
{ foreach (string err in errors)
if (msg.IndexOf(err) >= 0) return true; return false; }
来源:https://stackoverflow.com/questions/25957207/color-output-strings-in-richtextbox