Replace to Colored Text - c#

So I want to use the Text.Replace function to replace non-colored text with colored text, but that non-colored text has to be a specific word.
eg.
private void timer1_Tick(object sender, EventArgs e)
{
int index = 0;
while(index < richTextBox1.Text.LastIndexOf(textBox1.Text))
{
richTextBox1.Find("if");
richTextBox1.Text.Replace("if", Text.Color.DarkGreen "if");
}
}
}

The coloring is not so hard but defining the term 'word' is not so simple..
Here is an example for both:
I assume that you can live with the Regex definition of word boundaries. You may need to improve on the wordPattern depending on your needs, i.e. on your grammar! (See here for an example!)
int ColorWord(RichTextBox rtb, string word, Color foreColor, Color backColor)
{
string wordPattern = #"\b" + word + #"\b";
var matches = Regex.Matches(rtb.Text, wordPattern);
for (int i = matches.Count - 1; i >= 0; i--)
{
var m = matches[i];
rtb.SelectionStart = m.Index;
rtb.SelectionLength = m.Length;
rtb.SelectionColor = foreColor;
rtb.SelectionBackColor = backColor;
}
return matches.Count;
}
This function will set fore- and backcolor for each occurance of a given word in a RichTextBox. It transverses the matches from the back just for good measure as we don't really modify any text, so the letters won't shift; so we could have looped from start to end as well; but maybe you want to adapt it one day for changing words..
Once you understand how coloring (or formatting in any other way) the RTB text works, i.e. by first selecting a portion of the text and then changing the RTB.SelectedXXX property, it should be simple to modify..
Note that the word boundaries are meant to work with normal text. It is up to you to define maybe new rules to include or exclude characters for the language you want to highlight..

Related

Make search terms on richtextbox case insensitive c#

I have a richtextbox that I've added a search and highlight function to but it will only search for exactly what the user types. I know this is because of the MatchCase property but none of the other options seem to do the job. Here is my code:
private void btnSourceSearch_Click(object sender, EventArgs e)
{
int start = 0;
int end = richTextBox1.Text.LastIndexOf(textBox1.Text);
richTextBox1.SelectAll();
richTextBox1.SelectionBackColor = Color.White;
while(start < end)
{
richTextBox1.Find(textBox1.Text, start, richTextBox1.TextLength, RichTextBoxFinds.MatchCase);
richTextBox1.SelectionBackColor = Color.Yellow;
start = richTextBox1.Text.IndexOf(textBox1.Text, start) + 1;
}
}
Any help would be greatly appreciated. It's probably simple but I've been looking at code for a good few hours over the last week and it's beginning to look a lot like the Matrix!
Thanks
I don’t know if you are familiar with regular expressions, but they are useful in this situation. I am not that familiar with them but felt I would give this a shot using them. Without them, using your approach, you will have to check somehow all the case possibilities. That’s where regular expressions are your friend. Below is the code that creates a regular expression from the text in the text box. Then I use that expression to get the Matches in the text in the RichTexBox to highlight. Hope this helps.
private void button1_Click(object sender, EventArgs e) {
richTextBox1.SelectAll();
richTextBox1.SelectionBackColor = Color.White;
if (textBox1.Text.Length < 1)
return;
string pattern = #"\b" + textBox1.Text.Trim() + #"\b";
Regex findString = new Regex(pattern, RegexOptions.IgnoreCase);
foreach (Match m in findString.Matches(richTextBox1.Text)) {
richTextBox1.Select(m.Index, m.Length);
richTextBox1.SelectionBackColor = Color.Yellow;
}
}
You could do your search by adding Text.ToUpper() method.
Add .ToUpper() method in your richTextBox1.Text and search text both.
As mentioned use the ToUpper() or ToLower() method for all texts that you operate with. But I also wonder if you shouldn't add the event to search while typing instead of waiting for full string. That would be more intuitive and easier to troubleshoot at all.

c# rtb: Bolden inline overrides another bolden inline

My projekt is a Windows 10 universal app!
I almost have for two month the problem, that when I bold two words in one rtb, the second overrides the first bold inline.
Example:
I want to bold:
Hello; Bye
Text from rtb:
Hello and Bye
Now I search with regex, weather ther is "Hello"/ "Bye" in rtb.
For each time there is "Hello" in rtb I insert a bolden inline with the text "Hello" in the same Position than "hello" stand befor.
After that I make the same with "Bye".
My Code:
string text = run.Text; -> "Hello and Bye"
MatchCollection mc = Regex.Matches(text, "Hello", RegexOptions.Multiline);
int i = 0;
var bold = new Bold();
int iIn = 0;
int iLe = 0;
p.Inlines.Clear(); -> p = Paragraph from rtb
foreach (Match match in mc)
{
p.Inlines.Add(new Run { Text = text.Substring(i, match.Index - i) });
bold.Inlines.Add(new Run { Text = text.Substring(match.Index, match.Length) });
p.Inlines.Add(bold);
i = match.Index + match.Length;
if (i < text.Length)
{
p.Inlines.Add(new Run { Text = text.Substring(i) });
}
}
This is followed by the same Code with bye.
Now the Problem is, that I clear the first bold inline (Hello) while insert the second bold inline (Bye).
Does anyone know an alternative to bold an specific word in a rtb or a Suggestion to improve the Code? I almost tryed everything but nothing really worked...
Use the following in order to select the relevant characters to make bold:"
public void Select(
TextPointer start,
TextPointer end
)
In order to get TextPointer, try this (not checked):
TextPointer pointer = document.ContentStart;
TextPointer start = pointer.GetPositionAtOffset(0);
TextPointer end = start.GetPositionAtOffset(5);
rtb.Select (start,end); // for example to select Hello
// Then change the font to bold

Displaying coloured text in a RichTextbox

so i have a string of characters that are typically formatted like this:
" text" where the bold character is red.
i want to display these types of strings in a richtextbox with the bold character being red.
i have the text in a string variable and i have the location of the red character (in the string) in an int variable.
my solution is:
get characters before the red character
get red character
get characters after the red character
display characters before the red character
display red character (with foreground = Brushes.Red)
display characters after the red characters
this is what i've got so far:
https://github.com/icebbyice/rapide/blob/master/rapide/SpreadWindow.xaml.cs
find: "//stackoverflow" (also, seperateOutputs is not completed)
i stopped there because i thought there had to be a more efficient way to do it because i will be changing the content of the rich text box often (up to 1000 content changes / 60 seconds).
so, is there a better way to do this?
You could do this:
// getting keywords/functions
string keywords = #"\b(e)\b";
MatchCollection keywordMatches = Regex.Matches(codeRichTextBox.Text, keywords);
// saving the original caret position + forecolor
int originalIndex = codeRichTextBox.SelectionStart;
int originalLength = codeRichTextBox.SelectionLength;
Color originalColor = Color.Black;
// MANDATORY - focuses a label before highlighting (avoids blinking)
menuStrip1.Focus();
// removes any previous highlighting (so modified words won't remain highlighted)
codeRichTextBox.SelectionStart = 0;
codeRichTextBox.SelectionLength = codeRichTextBox.Text.Length;
codeRichTextBox.SelectionColor = originalColor;
// scanning...
foreach (Match m in keywordMatches)
{
codeRichTextBox.SelectionStart = m.Index;
codeRichTextBox.SelectionLength = m.Length;
codeRichTextBox.SelectionFont = new Font(codeRichTextBox.Font, FontStyle.Bold);
}
// restoring the original colors, for further writing
codeRichTextBox.SelectionStart = originalIndex;
codeRichTextBox.SelectionLength = originalLength;
codeRichTextBox.SelectionColor = originalColor;
codeRichTextBox.SelectionFont = new Font(codeRichTextBox.Font, FontStyle.Regular);
// giving back the focus
codeRichTextBox.Focus();
That belongs in the RichTextBox TextChanged Event
If you type e, it will display it Bold. Any other text will be displayed as Font.Regular
If you would like to change the syntax from e, then look at the keywords string
This is all I have for this, I hope it helps you :)

Keep text positions after saving richtextbox to RTF file

i'm trying to create some RTF files from richtextbox content ( which is load from RTF files )
After opening file by some code and applying some changes and saving back new file (output) to another location. i find that positions text have changed and also font colors. please see attached captures for more clarifications.
input:
output:
desired ouput
I think i need to talk a bit about what i apply to input from the code: well i need to replace every variables begining by $ by some variables from databases:
I used this portion of code for that:
foreach (Match match in Regex.Matches(richTextBox1.Text, "(\\$\\w+)"))
{
if (match.Groups[1].Value.Substring(1).Equals("Add1"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getAdress1(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("Add2"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getAdress2(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("Add3"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getAdress3(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("Add4"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getLand(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("Rechnr"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, nums_res[j]);
if (match.Groups[1].Value.Substring(1).Equals("Datum"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getDatum(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("resname"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getName1(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("resvorname"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getVorname(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("resroom"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getZimmer(nums_res[j].ToString()));
if (match.Groups[1].Value.Substring(1).Equals("anz"))
richTextBox1.Text = richTextBox1.Text.Replace(match.Groups[1].Value, getAnz(nums_res[j].ToString()));
}
int indexToText = richTextBox1.Find(getAdress1(nums_res[j].ToString()));
int endIndex = richTextBox1.Find(getAdress1(nums_res[j].ToString()));
if(indexToText > 0 && endIndex > 0)
richTextBox1.Select(indexToText, endIndex); richTextBox1.SelectionAlignment = System.Windows.Forms.HorizontalAlignment.Center;
int indexToText2 = richTextBox1.Find(getLand(nums_res[j].ToString()));
int endIndex2 = richTextBox1.Find(getLand(nums_res[j].ToString()));
if (indexToText2 > 0 && endIndex2 > 0)
richTextBox1.Select(indexToText2, endIndex2); richTextBox1.SelectionAlignment = System.Windows.Forms.HorizontalAlignment.Center;
richTextBox1.SaveFile("d:\\ryadmogadoroutput" + nums_res[j].ToString());
i = i + 1;
richTextBox1.Clear();
for now i dont replace all of them but just some and i want to know where the difference comes between my output and desired output. ( as u can see, i tried to center first variables from the code)
i'm wondering if theres a way to keep original format of the file after applying the changed i talked about
Thank you
EDIT: After changing the property .text to rtf here the improved output. still some details to fix: font color, and some deplaced ( i dont know why ) strings, please see date:$datum
EDIT: solution suggestion by #TaW:
output:
compilation error:
I Think you should change the text format to RTF Format by changing "richTextBox1.Text" to "richTextBox1.RTF"
You must never change the Text directly after any formatting has been applied to the RichText. Instead you need to work strictly on the SelectedText using Copy, Paste, Append and the other specialized methods.
So at the very least you need to write an appropriate Replace function!
Maybe, with a little luck, not working on the Text but the Rtf property will also help, but it may be interwoven with formatting stuff that might be in the way..
Here is a function that will to do it :
void RtfReplace(RichTextBox RTB, Match match, string replace, ref int offset)
{
RTB.Select(match.Index + offset, match.Length);
RTB.SelectedText = replace;
offset += replace.Length - match.Length;
}
And a few respective calls
int offset = 0;
foreach (Match match in Regex.Matches(richTextBox1.Text, "(\\$\\w+)"))
{
if (match.Groups[1].Value.Substring(1).Equals("Add1"))
RtfReplace(richTextBox1, match, getAdress1(nums_res[j].ToString()), ref offset);
if (match.Groups[1].Value.Substring(1).Equals("Add2"))
RtfReplace(richTextBox1, match, getAdress2(nums_res[j].ToString()), ref offset);
//..
Update: Since each replacement is likely to change the length of the replaced piece of text we will need to adjust all positions in the matches collection by that difference (or repeatedly call the whole replacement code until no more matches are found.) The fix is simple, though..

RichTextBox SelectionStart offset with linebreaks

I'm using a RichTextBox for coloured text. Let's assume I want to use different colours for different portions of the text. This is working fine so far.
I'm currently having a problem with the SelectionStart property of the RichTextBox. I've set some text to the Text property of the RichTextBox. If the text contains \r\n\r\n the SelectionStart Position won't match the position of characters with the assigned String.
Small example (WinformsApplication. Form with a RichTextBox):
public Form1()
{
InitializeComponent();
String sentence1 = "This is the first sentence.";
String sentence2 = "This is the second sentence";
String text = sentence1 + "\r\n\r\n" + sentence2;
int start1 = text.IndexOf(sentence1);
int start2 = text.IndexOf(sentence2);
this.richTextBox1.Text = text;
String subString1 = text.Substring(start1, sentence1.Length);
String subString2 = text.Substring(start2, sentence2.Length);
bool match1 = (sentence1 == subString1); // true
bool match2 = (sentence2 == subString2); // true
this.richTextBox1.SelectionStart = start1;
this.richTextBox1.SelectionLength = sentence1.Length;
this.richTextBox1.SelectionColor = Color.Red;
this.richTextBox1.SelectionStart = start2;
this.richTextBox1.SelectionLength = sentence2.Length;
this.richTextBox1.SelectionColor = Color.Blue;
}
The RichTextBox looks like this:
As you can see, the first two characters of the second sentence are not coloured. This is the result of an offset produced by \r\n\r\n.
What is the reason for this? Should I use another control for colouring text?
How do I fix the problem in a reliable way? I've tried replacing the "\r\n\r\n"with a String.Empty, but that produces other offset problem.
Related question:
Inconsistent behaviour between in RichTextBox.Select with SubString method
It seems that the sequence \r\n counts for one character only when doing selections. You can do the measurements in a copy of the string where all \r\n are replaced by \n.
Just for completeness (I'll stick to linepogls answer for now):
I've found another way to get indices for the SelectionStart property. The RichTextBox offers a Find method, that can be used to retrieve index positions based on a specified string.
Be aware of the fact, that the text you want to highlight might not be unique and occur multiple times. You can use an overload to specify a start position for the search.

Categories