I have a variable, lets say it = 5, and then I would like the line number 5 to be highlighted "blue" in my RichTextBox1. is that possible at all?
Or should I use something like a ListBox, DataGridView etc.
This will highlight the text in a given line in a RichTextBox if WordWrap is off:
void highLightALine(RichTextBox rtb, int line, Color hiLight)
{
int i1 = rtb.GetFirstCharIndexFromLine(line);
int i2 = rtb.GetFirstCharIndexFromLine(line + 1);
if (i2 < 0) i2 = rtb.Text.Length;
rtb.SelectionStart = i1;
rtb.SelectionLength = i2 - i1;
rtb.SelectionBackColor = hiLight;
}
Note that if WordWrap is true it will still highlight the line but only as far as it is visible. Its continuation on the next line will not be changed.
Also note that only Text can be highlighted. Trailing empty space can't be highlighted afaik. Here is an example of trying to owner-draw an RTB subclass..
Related
I wrote a Vacuum tube Cross reference program.
I can't figure out how to iterate through the RichTextBox1 to make the requested tube value Bold.
Existing output when searching for 6AU8A
Tube Cross1 Cross2 Cross3 Qty Location
6AU8 6AU8A 6BH8 6AW8 2 PM BOX 3
6AU8A 6AU8 6BH8 6AW8 6 BOX 9
6BA8A 6AU8 6AU8A 8AU8A 1 BOX 11
6CX8 6AU8A 6EB8 6GN8 2 BOX 16
6EH5 6AU8A 2081 6AW8A# 1 BOX 19
6GH8 6EA8 6GH8A 6AU8A 2 BOX 23
6GH8A 6GH8 6EA8 6AU8A 10 BOX 22
6GH8A 6GH8 6EA8 6AU8A 5 BOX 23
So, I need any occurrence for search term (6AU8A in this example) in Bold.
Using VS 2019, Windows Application, compiled for .NET 4.8.1, runs on Windows 7 & 10 PC's.
public int FindMyText(string text)
{
length = text.Length;
// Initialize the return value to false by default.
int returnValue = -1;
// Ensure that a search string has been specified and a valid start point.
if (text.Length > 0)
{
// Obtain the location of the first character found in the control
// that matches any of the characters in the char array.
int indexToText = richTextBox1.Find(text);
// Determine whether the text was found in richTextBox1.
if (indexToText >= 0)
{
// Return the location of the character.
returnValue = indexToText;
start = indexToText;
}
}
return returnValue;
}
Once you call Find(), the value will be SELECTED (if it exists). Then you can change the Font to include Bold. The Find() function has a "Start" position, which allows you to find the NEXT occurrence. So you start at 0, then add the length of the search string to get the next starting position. If the value returned is -1, then there were no more matches and you can stop.
Looks something like this:
private void button1_Click(object sender, EventArgs e)
{
BoldText("6AU8A"); // get your input from somewhere...
}
private void BoldText(String value)
{
int startAt = 0;
int indexToText = richTextBox1.Find(value, startAt, RichTextBoxFinds.None);
while (indexToText != -1)
{
richTextBox1.SelectionFont = new Font(richTextBox1.SelectionFont, FontStyle.Bold);
startAt = startAt + value.Length;
indexToText = richTextBox1.Find(value, startAt, RichTextBoxFinds.None);
}
}
Here it is in action:
If you actually need to use a RichTextBox for this, you could use a simple Regex to match one or more terms, then use Index and Length properties of each Match to perform the selection and change the Font and/or other styles (in the code here, optionally, the color)
Pass a collection of terms to match (containing one or more terms) to the method:
string[] parts = { "6AU8A", "6GH8" };
Highlight(richTextBox1, parts, FontStyle.Bold);
// also specifying a Color
Highlight(richTextBox1, parts, FontStyle.Bold, Color.Red);
// or deselect previous matches
Highlight(richTextBox1, parts, FontStyle.Regular);
The Regex only matches complete sequences, e.g., passing 6GH8, it won't partially highlight 6GH8A
If you prefer a partial selection, remove both the \b boundaries in the pattern
using System.Text.RegularExpressions;
private void Highlight(RichTextBox rtb, IEnumerable<string> terms, FontStyle style, Color color = default)
{
color = color == default ? rtb.ForeColor : color;
string pattern = $#"\b(?:{string.Join("|", terms)})\b";
var matches = Regex.Matches(rtb.Text, pattern, RegexOptions.IgnoreCase);
using (var font = new Font(rtb.Font, style)) {
foreach (Match m in matches) {
rtb.Select(m.Index, m.Length);
rtb.SelectionColor = color;
rtb.SelectionFont = font;
};
}
}
I'm making a spelling game for kids in Unity. I've got it so when the right letter is clicked, the letter is highlighted. I couldn't figure out how to highlight a specific char on the fly in a Text field, so I just put a highlighted version of the text behind the regular, and have the regular char disappear when clicked instead. Now, I need this text centered in the beginning, but the problem is it auto centers whenever a char disappears, misaligning the text.
Any ideas on how to stop getting it to auto center?
newWord = new StringBuilder (startWord.text);
i = 0;
if (Letter.gameObject.GetComponent<MoveLetter> ().checkIfClicked (startWord.text[i]))
{
newWord [i] = ' ';
startWord.text = newWord.ToString();
Destroy (Letter);
letters.Remove (Letter);
i++;
}
My answer will try to help you fix your first problem : highlighting characters.
I would advise you to not duplicate text to show the highlighted characters. Instead, use rich text
You can change the color of individual characters by surrounding them with the color tag, as follow :
<color=#ffff00ff>H</color><color=#ffff00ff>E</color>LP
This string in the text attribute of your Text component will make the H and E letters yellow, while the other letters will stay black (or whatever color you have chosen for the Text component)
Here is a function you can use to highlight specific letters of a given string :
using System;
// ....
public void Foo()
{
// Give the indices of the letters of the string, starting at 0
GetComponent<UnityEngine.UI.Text>().text = Highlight("HELP", "#ffff00ff", 3, 1, 2);
// Will output :
// H<color=#ffff00ff>E</color><color=#ffff00ff>L</color><color=#ffff00ff>P</color>
}
private string Highlight(string text, string color, params int[] indices)
{
Array.Sort(indices);
for (int i = indices.Length - 1 ; i >= 0; i--)
{
if( indices[i] == text.Length - 1 )
text = String.Format( "{0}<color={1}>{2}</color>", text.Substring(0, indices[i]), color, text[indices[i]] ) ;
else if( indices[i] == 0 )
text = String.Format( "<color={0}>{1}</color>{2}", color, text[indices[i]], text.Substring(1));
else if( indices[i] < text.Length )
text = String.Format( "{0}<color={1}>{2}</color>{3}", text.Substring(0, indices[i]), color, text[indices[i]], text.Substring(indices[i] + 1));
}
return text;
}
I'm not sure exactly how Shadow works (I'm a newbie), but maybe you could try to put a Shadow component on the right letter when clicked and that way it may be easier to make it work.
EDIT:
Here, you could do it like this. Dunno how efficient it is, but I'm sure you can control it from code somehow. Add 4 components and cast a shadow in each direction
http://imgur.com/gD4zs9N
#Hellium answer is the right one: using rich text is probably your best solution.
However there are two other possibilities I can think of right now:
keep your 2 text elements (one being the background and the other being the overlay) and use a monospaced font: this way the background could be "HELP" while the overlay would be " LP" (simply make sure both are the same size/alignment)
use TextMesh Pro which is now part of Unity :)
Hope this helps,
This question already has an answer here:
C# RichTextBox Highlight Line
(1 answer)
Closed 6 years ago.
I want to highlight the entire line, from start to end doesn't matter whether characters are present or not and line may be blank but it should highlight the complete line.
Like
This will highlight a full line in a RichTextBox if WordWrap is off:
void highLightALine(RichTextBox rtb, int line, Color hiLight)
{
int i1 = rtb.GetFirstCharIndexFromLine(line);
int i2 = rtb.GetFirstCharIndexFromLine(line + 1);
if (i2 < 0) i2 = rtb.Text.Length;
rtb.SelectionStart = i1;
rtb.SelectionLength = i2 - i1;
rtb.SelectionBackColor = hiLight;
}
Note that if WordWrap is true it will still highlight the line but only as far as it is visible. Its continuation on the next line will not be changed.
Also note that only Text can be highlighted. Empty space can't be highlighted afaik. Here is an example of trying to owner-draw an RTB subclass..
Good Afternoon. I am new to stack overflow as a poster but have referenced it for years. I have been researching this problem of mine for about 2 weeks and while I've seen solutions that are close I still am left with an issue.
I am writing a C# gui that reads in an assembly code file and highlights different text items for further processing via another program. My form has a RichTextBox that the text is displayed in. In the case below I am trying to select the text at the location of the ‘;’ until the end of the line and change the text to color red. Here is the code that I am using.
Please note: The files that are read in by the program are of inconsistent length, not all lines are formatted the same so I cannot simply search for the ';' and operate on that.
On another post a member has given an extension method for AppendText which I have gotten to work perfectly except for the original text is still present along with my reformatted text. Here is the link to that site:
How to use multi color in richtextbox
// Loop that it all runs in
Foreach (var line in inArray)
{
// getting the index of the ‘;’ assembly comments
int cmntIndex = line.LastIndexOf(';');
// getting the index of where I am in the rtb at this time.
int rtbIndex = rtb.GetFirstCharIndexOfCurrentLine();
// just making sure I have a valid index
if (cmntIndex != -1)
{
// using rtb.select to only select the desired
// text but for some reason I get it all
rtb.Select(cmntIndex + rtbIndex, rtb.SelectionLength);
rtb.SelectionColor = Color.Red;
}
}
Below is the sample assembly code from a file in it's original form all the text is black:
;;TAG SOMETHING, SOMEONE START
ASSEMBLY CODE ; Assembly comments
ASSEMBLY CODE ; Assembly comments
ASSEMBLY CODE ; Assembly comments
;;TAG SOMETHING, SOMEONE FINISH
When rtb.GetFirstCharIndexOfCurrentLine() is called it returns a valid index of the RTB and I imagine that if I add the value returned by line.LastIndexOf(';') I will then be able to just select the text above that looks like ; Assembly comments and turn it red.
What does happen is that the entire line turns red.
When I use the AppendText method above I get
ASSEMBLY CODE (this is black) ; Assembly comments (this is red) (the rest is black) ASSEMBLY CODE ; Assembly comments
The black code is the exact same code as the recolored text. In this case I need to know how to clear the line in the RTB and/or overwrite the text there. All the options that I have tried result in deletion of those lines.
Anywho, I'm sure that was lengthy but I'm really stumped here and would greatly appreciate advice.
I hope I've understood you correctly.
This loops over each line in the richtextbox, works out which lines are the assembly comments, then makes everything red after the ";"
With FOREACH loop as requested
To use a foreach loop you simply need to keep track of the index manually like so:
// Index
int index = 0;
// Loop over each line
foreach (string line in richTextBox1.Lines)
{
// Ignore the non-assembly lines
if (line.Substring(0, 2) != ";;")
{
// Start position
int start = (richTextBox1.GetFirstCharIndexFromLine(index) + line.LastIndexOf(";") + 1);
// Length
int length = line.Substring(line.LastIndexOf(";"), (line.Length - (line.LastIndexOf(";")))).Length;
// Make the selection
richTextBox1.SelectionStart = start;
richTextBox1.SelectionLength = length;
// Change the colour
richTextBox1.SelectionColor = Color.Red;
}
// Increase index
index++;
}
With FOR loop
// Loop over each line
for(int i = 0; i < richTextBox1.Lines.Count(); i++)
{
// Current line text
string currentLine = richTextBox1.Lines[i];
// Ignore the non-assembly lines
if (currentLine.Substring(0, 2) != ";;")
{
// Start position
int start = (richTextBox1.GetFirstCharIndexFromLine(i) + currentLine.LastIndexOf(";") + 1);
// Length
int length = currentLine.Substring(currentLine.LastIndexOf(";"), (currentLine.Length - (currentLine.LastIndexOf(";")))).Length;
// Make the selection
richTextBox1.SelectionStart = start;
richTextBox1.SelectionLength = length;
// Change the colour
richTextBox1.SelectionColor = Color.Red;
}
}
Edit:
Re-reading your question I'm confused as to whether you wanted to make the ; red as well.
If you do remove the +1 from this line:
int start = (richTextBox1.GetFirstCharIndexFromLine(i) + currentLine.LastIndexOf(";") + 1);
Private Sub RichTextBox1_Click(sender As Object, e As EventArgs) Handles RichTextBox1.Click
Dim MyInt1 As Integer
Dim MyInt2 As Integer
' Reset your RTB back color to white at each click
RichTextBox1.SelectionBackColor = Color.White
' Define the nth first character number of the line you clicked
MyInt1 = RichTextBox1.GetFirstCharIndexOfCurrentLine()
' use that nth to find the line number in the RTB
MyInt2 = RichTextBox1.GetLineFromCharIndex(MyInt1)
'Select the line using an array property of RTB (RichTextBox1.Lines())
RichTextBox1.Select(MyInt1, RichTextBox1.Lines(MyInt2).Length)
' This line would be for font color change : RichTextBox1.SelectionColor = Color.Maroon
' This one changes back color :
RichTextBox1.SelectionBackColor = Color.Yellow
End Sub
' There are a few bugs inherent to the rtb.select method
' It bugs if a line wraps, or fails on an "http" line... probably more.
(I just noticed the default stackoverflow.com character colors on my above code are not correct for comment lines and others.)
I have a RichTextBox with a search box under it. I use the following code for the search functionality:
TabPage activePage = tabs.SelectedTab;
RichTextBox xmlBox = activePage.Controls.Find("xmlBox", true).Single() as RichTextBox;
xmlBox.DeselectAll();
int index = 0;
int len = xmlBox.TextLength;
int lastIndex = xmlBox.Text.LastIndexOf(tbSearch.Text);
while (index < lastIndex)
{
xmlBox.Find(tbSearch.Text, index, len, RichTextBoxFinds.WholeWord);
xmlBox.SelectionBackColor = Color.Yellow;
index = xmlBox.Text.IndexOf(tbSearch.Text, index) + 1;
}
What I want is that lets say a user types the word User. When he types the U I want all the Us to be highlighted, etc. and then if he deletes the r I want only Use to be highlighted. I was thinking that DeselectAll() would do the trick, but this isn`t working. Any other way to do this?
DeselectAll() will simply unselect any current selection. Your code actually changed the BackColor() of previous text so you'd have to undo this...possibly by selecting everything and resetting it to the default color before again highlighting the new search value.