Reputation: 3594
This has been an issue with many of my applications and I don't know why Windows doesn't have an elegant solution for this.
I am working with Winforms in .Net 4.5 in VS2013
For example, I would like to change the color of one line of text in a multiline RichTextBox.
For this I am required to set the selection using something like
rtb.Select(rtb.GetFirstCharIndexFromLine(r), str.Length);
Then, I would set the color using
rtb.SelectionColor = Color.Red;
And presumably, cancel the selection with
rtb.DeselectAll();
Now the problem is the cursor/caret has moved back to the beginning of the line,
I try to fix it by saving the previous Caret Position,
rtb.CaretPosition
However, CaretPosition is not a method of RichTextBox, and everywhere online this is the primary method everyone uses.
I tried adding PresentationFramework to my References and to my code I added
using System.Windows.Framework;
As suggested here: http://msdn.microsoft.com/en-us/library/system.windows.controls.richtextbox.caretposition(v=vs.110).aspx
but I still do not see the CaretPosition property, only the ScrollToCaret() method.
My 2 questions are:
How do I get the CaretPosition property in my RichTextBox?
How can I change the text color without using selections and affecting the caret position, having to write complex logic to restore it for the user.
My application checks serial numbers, one per line, and highlights them red if they do not match the format, as shown below.
private void rtb_TextChanged(object sender, EventArgs e)
{
string pattern = @"[A-Z]{2}[A-Z, 0-9]{2}\d{4}";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
TextReader read = new System.IO.StringReader(rtb.Text);
SerialNumbers.Clear();
int selectStart = 0;
for (int r = 0; r < rtb.Lines.Length; r++)
{
string str = read.ReadLine();
if (str != null)
{
selectStart += str.Length;
MatchCollection matches = rgx.Matches(str);
if (matches.Count == 1)
{
SerialNumbers.Add(str);
}
else
{
rtb.Select(rtb.GetFirstCharIndexFromLine(r), str.Length);
rtb.SelectionColor = Color.Red;
rtb.DeselectAll();
}
}
}
}
Upvotes: 1
Views: 2448
Reputation: 3594
Fixed it by saving SelectionStart position
int selectionStart = SNbox.SelectionStart;
SNbox.Select(SNbox.GetFirstCharIndexFromLine(r), str.Length);
SNbox.SelectionColor = Color.Red;
SNbox.DeselectAll();
SNbox.SelectionStart = selectionStart;
SNbox.SelectionLength = 0;
Upvotes: 2
Reputation: 2160
You should be using SelectionCaret
(as @Mangist mentioned in a comment) because you're using WinForms and not WPF. The MSDN article you referenced only applies to WPF, which is very different from WinForms.
As an example, I use the following to easily log to a rich text box from anywhere in a WinForms app:
public static void Log(string text, ref RichTextBox rtbLogBox) {
//
if (text == null) return;
var timestamp = DateTime.Now.ToLongTimeString();
var logtext = string.Format("{0} - {1}\r\n\r\n", timestamp, text);
if (rtbLogBox.InvokeRequired) {
var logBox = rtbLogBox;
logBox.Invoke(new MethodInvoker(delegate {
logBox.AppendText(logtext);
logBox.Update();
logBox.SelectionStart = logBox.Text.Length;
logBox.ScrollToCaret();
}));
} else {
rtbLogBox.AppendText(logtext);
rtbLogBox.Update();
rtbLogBox.SelectionStart = rtbLogBox.Text.Length;
rtbLogBox.ScrollToCaret();
}
}
Notice how the ScrollToCaret()
is called after setting SelectionStart
to the length of text in the rich text box. This solves the 'issue' of AppendText
not scrolling to the bottom after adding text.
In your case you will simply want to save the SelectionStart
value before you format your text with the highlighting, and then restore it once you've finished.
Upvotes: 1