I'm having difficulty creating a code that able to pick up specific words and color them.
I'm currently using this code:
private void Colorize(string word, Color color, int startIndex)
{
if (this.richTextBox1.Text.Contains(word))
{
int index = -1;
int selectStart = this.richTextBox1.SelectionStart;
while ((index = this.richTextBox1.Text.IndexOf(word, (index + 1))) != -1)
{
this.richTextBox1.Select((index + startIndex), word.Length);
this.richTextBox1.SelectionColor = color;
this.richTextBox1.Select(selectStart, 0);
this.richTextBox1.SelectionFont = new Font(richTextBox1.Font, FontStyle.Regular);
this.richTextBox1.SelectionColor = Color.Black;
}
this.richTextBox1.SelectionColor = Color.Black;
}
}
The problem is that when the text of the RichTextBox is too large it hangs and runs from top to bottom, is there any way to instantly color keywords?
I'm doing a basic IDE, but I need some color java-based keywords.
Any error sorry I used the google translator.
You are aware that String.Contains does not check for words, aren't you?
If you use String.Contains("able"), then indeed you will find the word "able", but you'll also find words like "disabled", "sable" and "IEquatable".
To check for words you'll need a regular expression.
Whenever you need to process sequences of something, LINQ is your friend. Consider to familiarize yourself with the possibilities of LINQ.
Introduction of LINQ
Using Regular expressions and LINQ I could colorize the complete works of shakespeare (over five million characters) in about 5 seconds
// on load form: fill the rich text box with
// the complete works of William Shakespeare
private async void Form1_Load(object sender, EventArgs e)
{
const string completeShakespeare = "http://www.gutenberg.org/cache/epub/100/pg100.txt";
using (var downloader = new HttpClient())
{
this.richTextBox1.Text = await downloader.GetStringAsync (completeShakespeare);
}
}
// on button click: mark all "thee" red
private void button1_Click(object sender, EventArgs e)
{
var stopwatch = Stopwatch.StartNew();
this.Colorize2("thee", Color.Red);
var elapsed = stopwatch.Elapsed;
Debug.WriteLine ("Coloring a text with {0} characters took {1:F3} sec",
this.richTextBox1.Text.Length,
elapsed.TotalSeconds);
}
private void Colorize2(string word, Color color)
{
string regString = String.Format(#"\b{0}\b", word);
// regex: match substring that match word,
// with boundaries to non alphanumeric characters like space and \n \r \t
var regex = new Regex(regString, RegexOptions.IgnoreCase);
var matches = regex.Matches(richTextBox1.Text);
foreach (Match match in matches.Cast<Match>())
{
this.richTextBox1.Select(match.Index, match.Length);
this.richTextBox1.SelectionColor = color;
}
}
Once Iv'e needed to implement C#, Python and Matlab syntax highlighting so I've spent some time researching about it.
The problem with this Select method in RichTextBox is that the selection itself takes time since it also grafically select the text and when you want to dinamically color the syntax when the code is written there are many selections which makes it slow.
Trying to parse the modify the rtf is possible but is a real headache and requires you and the ones that will maintain the code after you to understand this format.
A good solution I've found is that there are many open sources implement a Control of their own for syntax highlighting which you acn use.
In FastColoredTextBox, the one I used, you can choose the language to highlight and the format in which you want it to be shown, you can also add your own language to that list and configure it to indent the hightlighted code automatically using Regex.
Sorry if this is not the answer you expected but this is exacly the type of thing to search for and not implement by yourself.
Related
I'm working on my own basic syntax highlight editor in C#. I've already completed the automatic coloring of keywords, functions etc etc. I don't need any other fancy stuff like automatic code indentation.
However, I do wish to have a code minify / maxify button. Nothing fancy. I just want it to automaticly set a newline before any opening bracket and one behind it with either tab characters or changing the SelectionIndent Property.
So something like this:
test { test { test } test }
Becomes:
test
{
test
{
test
}
}
And of course the minify button should do the exact opposite, putting everything on 1 line.
I've already tried working with the Regex.Replace Method. I didn't quite get it to work, but thinking about that approach, it would cause issues if the opening and closing brackets get mixed up. Anyway, this is what I had untill I gave up and decided to ask you guys for some help:
string tabs = "";
private void btnMax_Click(object sender, EventArgs e)
{
var count = codeRichTextBox.Text.Count(x => x == '{');
for(int i=1; i<= count; i++)
{
// The idea was to add \t to tabs here on each iteration
}
string pattern = "{";
string replacement = "\n{\n\t";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(codeRichTextBox.Text, replacement);
codeRichTextBox.Text = result;
}
Obviously that solution is the wrong approach and isn't going to work. So what should I do instead?
Edit: Although it would be nice, it doesn't have to take into account that part of the string already has code indentation. The maxify button only needs to work on a string that's on a single line.
My idea: You'll need to parse the text, counting the current nesting level of { and } .
For each { or } found, decide on the proper whitespace-string-before (prefix) and whitespace-string-after (suffix) based on the current nesting level (for example just \n { \n for the first level).
See if the desired prefix is already there. If not, delete any existing whitespace then add the prefix. Do the same for the suffix.
Hello sorry if the answer for this is already out there somewhere but I did not find it, or did not understand it. What I have to do is I have a list box in visual studio (C#) and in this list box are some options to click on.
PinturaV $100
PinturaA $105
PinturaE $115
Lijas_Ag $112
Solvente $101
If I select a line for example PinturaA $105 from the list box in a text box that I have it should show only 105. Then if I select for example Lijas_Ag $112, the text box should show...
105
112
And so on until I press the total button and it would give me the total.
My problem is having just the numbers appear on the text box. I coded so that the program can read the line selected and tell me where the space is located but I don't know if this was even needed to be able to get the number into the text box. I have no Idea how to do this. Any help would be much appreciated. I left some pics in case that helps.
Thank You
main selected
Code I have so far
You should use Regex to get your desired output. You need to apply Regex in your ListBox event. Please check below for Regex & C# example.
Regex:
\d+
Above Regex will give you all digit from your string
CODE C#:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// Your others code & logic
//string data = "PinturaV $100";
string data = listBox1.Text;
textBox1.Text = Regex.Match(data, #"\d+").Value;
}
Considering the selected text is PinturaA $105 .. you can use regular expression (or) string library method to get only the numbers like
string str = "PinturaA $105";
string val = (str.IndexOf("$") > 0)
? str.Substring(str.IndexOf("$"), str.Length - str.IndexOf("$"))
: string.Empty;
You can do this easily with a regex:
var oldtext = "Solvente $101";
var newtest = Regex.Match(oldText, "\\d+$").Groups[0].Value;
The variable newtext will contain the digits.
You could use Regex and just do
var item = "Solvente $101";
var val = Regex.Match(item, #"\$(\d+)").Groups[1];
The other answers are OK and will probably work. But just so you know, the typical way to handle this sort of thing is to put the data you want in the ListItems' Value property and the text in the Text property, like this:
private void PopulateListBox1()
{
listBox1.Add(new ListItem("100","PinturaV $100"));
listBox1.Add(new ListItem("105","PinturaA $105"));
listBox1.Add(new ListItem("115","PinturaE $115"));
listBox1.Add(new ListItem("112","Lijas_Ag $112"));
listBox1.Add(new ListItem("101","Solvente $101"));
}
And then get the Value instead of Text, like this:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
textBox1.Text = listBox1.SelectedValue;
}
As you can see this is far, far simpler than parsing the string returned by ListItem.Text.
Since I have not been able to find an resolution via my searching endeavor, I believe I may have a unique problem. Essentially I am creating a gene finding/creation application in c#.NET for my wife and am using RichTextBoxes for her to be able to highlight, color, export, etc the information she needs. I have made several custom methods for it because, as I am sure we all know, RichTextBoxes from Microsoft leave much to the imagination.
Anyway, here is my issue: I need to be able to search for a term across hard returns. The users have strings in 60 letter intervals and they need to search for items that may cross that hard return barrier. For instance let's say I have 2 lines (I will make them short for simplicity):
AAATTTCCCGGG
TTTCCCGGGAAA
If the user runs a search for GGGTTT, I need to be able to pull the result even though there is a line break/hard return in there. For the life of me I cannot think of a good way to do this and still select the result in the RichTextBox. I can always find the result but getting a proper index for the RichTextBox is what eludes me.
If needed I am not against richTextBox.SaveFile() and LoadFile() and parsing the rtf text as a string manually. It doesnt have to be pretty, in this case, it just has to work.
I appreciate any help/guidance you may give.
Here is a relevant snippet:
//textbox 2 search area (examination area)
private void button5_Click(object sender, EventArgs e)
{
textBox3.Text = textBox3.Text.ToUpper();
if (textBox3.Text.Length > 0)
{
List<string> lines = richTextBox2.Lines.ToList();
string allText = "";
foreach (string line in lines)
allText = allText + line.Replace("\r", "").Replace("\n", "");
if (findMultiLineRTB2(allText, textBox3.Text) != -1)
{
richTextBox2.Select(lastMatchForRTB2, textBox3.Text.Length);
richTextBox2.SelectionColor = System.Drawing.Color.White;
richTextBox2.SelectionBackColor = System.Drawing.Color.Blue;
}//end if
else
MessageBox.Show("Reached the end of the sequence", "Finished Searching");
}//end if
}//end method
private int findMultiLineRTB2(string rtbText, string searchString)
{
lastMatchForRTB2 = rtbText.IndexOf(searchString, lastMatchForRTB2 + 1);
return lastMatchForRTB2;
}
So i make an assumption: you want to search a word across all lines where each line is 60 characters long. The desired result is the index of that word.
You just have to build a string that has no line breaks, for example with string.Join:
string allText = string.Join("", richTextBox.Lines);
int indexOf = allText.IndexOf("GGGTTT"); // 9 in your sample
My Goal: I want to parse a file and display it in a textbox. Here's the code (thanks to Aviral Singh).
private void Form1_Load(object sender, EventArgs e)
{
var path = #"C:\Users\Smith\Desktop\Settings.txt"; //Path to settings file.
RichTextBox rtb = new RichTextBox();
System.IO.StreamReader sis = new System.IO.StreamReader(path);
rtb.Text = sis.ReadToEnd();
sis.Close();
foreach (string line in rtb.Lines)
{
if (line.Contains("Installation Technical Manual:") == true)
{
string numbers = line.Substring(line.IndexOf("Installation Technical Manual:"));
textBox1.Text = numbers;
}
}
}
Text file looks like this:
My Problem: The textbox in my program displays entire line: Installation Technical Manual: (1234567890).
I just want the number with brackets (1234567890). to be displayed in the textbox. What changes should I make to the code to remove the words and just display numbers with brackets around it? Thanks for your help. :)
numbers = "(" + new String(numbers.Where(Char.IsDigit).ToArray()) + ")";
The problem is that IndexOf() is going to give you the starting position of the string which you're asking for the index of. Which in your example is going to be 0, so a Substring call that starts at 0 is going to return you the entire string.
What you really want to do is Substring(IndexOf("Installation Technical Manual:") + "Installation Technical Manual:".Length). That will give you whatever comes after your string.
Assuming you have ':' in your line always,
if(line.Contains(":"))
{
string numbers = line.Split(':')[1];
textBox1.Text = numbers;
}
The reason your code is not working as you have used the substring method as with one parameter, so it is used as :
public string Substring(
int startIndex
)
See: http://msdn.microsoft.com/en-us/library/hxthx5h6.aspx
And you are passing in, line.IndexOf("Installation Technical Manual:")
which will return ).
See here: http://msdn.microsoft.com/en-us/library/k8b1470s.aspx
So you are essentially saying return Substring of string Installation Technical Manual:(number) starting at 0 which basically returns the whole line.
Using the richTextBox control, how to change in real time the background color of words that are separated by a comma, and put a blank space instead of the comma? A bit like the keywords' presentation of Stackoverflow.
Here you have a small code red-colouring the background when certain word ("anything") is written in a richtextbox. I hope that this will be enough to help you understand how to interact with a richtextbox at runtime. Bear in mind that it is pretty simplistic: it colours "anything" only if it is first word you introduce; and stops coloring if you write any other character after it.
int lastStart = 0;
int lastEnd = 0;
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
richTextBox1.Select(lastStart, lastEnd + 1);
if (richTextBox1.SelectedText.ToLower() == "anything")
{
richTextBox1.SelectionBackColor = Color.Red;
lastStart = richTextBox1.SelectionStart + richTextBox1.SelectionLength;
}
else
{
richTextBox1.SelectionBackColor = Color.White;
}
lastEnd = richTextBox1.SelectionStart + richTextBox1.SelectionLength;
richTextBox1.Select(lastEnd, 1);
}
The following string: "One, Two, Three, Four" can be converted to a list of strings with the items "One" - "Two" - "Three" - "Four" with the following code:
string FullString = "One, Two, Three, Four";
Regex rx = new Regex(", ");
List<string> ListOfStrings = new List<string>();
foreach (string newString in rx.Split(FullString))
{
ListOfStrings.Add(newString);
}
Regarding the color you can take a look here:
Rich Text Box how to highlight text block
To be able to do this in realtime I suggest you use the TextChanged event for the RTB and from there you can call a function changing the color.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.textchanged.aspx
When this is done you can use the String.Replace(char, char) function to remove the comas and change them to blank spaces.
http://msdn.microsoft.com/en-us/library/czx8s9ts.aspx