I write a code that counts the number of lines and text length from richtextbox content. With small chunks of text it work perfect. But when there large chunks of text (more than 100k) when I press "Enter" or "Backspace" in richtextbox, response time becomes very slow. For example: https://i.imgur.com/QO2UrAw.gifv
My question. What a better way to run this code asynchronously?
Archive with the test project https://gofile.io/?c=LpF409
private void StatusPanelTextInfo()
{
int currentColumn = 0;
int currentLine = 0;
int linesCount = 0;
if (statusStrip1.Visible)
{
currentColumn = 1 + richTextBox1.SelectionStart - richTextBox1.GetFirstCharIndexOfCurrentLine();
RichTextBox rtb = new RichTextBox
{
WordWrap = false,
Text = richTextBox1.Text
};
currentLine = 1 + rtb.GetLineFromCharIndex(richTextBox1.SelectionStart);
linesCount = richTextBox1.Lines.Count();
if (linesCount == 0)
{
linesCount = 1;
}
}
toolStripStatusLabel1.Text = "Length: " + richTextBox1.TextLength;
toolStripStatusLabel2.Text = "Lines: " + linesCount;
toolStripStatusLabel3.Text = "Ln: " + currentLine;
toolStripStatusLabel4.Text = "Col: " + currentColumn;
}
I downloaded your code and I can not understand why do you create a new RichTextBox every time you call StatusPanelTextInfo method:
RichTextBox rtb = new RichTextBox
{
WordWrap = false,
Text = richTextBox1.Text
};
This is the reason you got such a lag in your program. Each time you change/select text, you create a new RichTextBox object and copy a large amount of text to its Text property. You should remove this code, and then it works fast enough. Just replace rtb in your calculation of currentLine with richTextBox1.
Next time please provide your code in your question instead of making people download it from outer link. Your whole form class was about 60 lines. With proper selection you could have given us all the info we needed using 20 lines.
Related
So, I have been working with some texts.
I've trying to separate the text in multiple blocks when I encountered '$'sign in text. In my example I used two richTextBox. I tried using lists, and Split() method but it didn't work so well.
StreamReader read = new StreamReader(#"texte\Senzatii\definirea&caracterizarea_senzatiilor.txt");
string lines = "";
int state = 1;
while ((lines = read.ReadLine()) != null)
{
if (lines == "$".ToString())
state = 2;
if (state == 1)
richTextBox1.Text = richTextBox1.Text + lines + "\n";
else
richTextBox2.Text = richTextBox2.Text + lines + "\n";
}
This method works, it splits the text into two block of texts, but it doesn't look so good. Is there a better way to split the text into two blocks of text, a more c# way, solution to do this ?
I tried using lists, and Split() method but it didn't work so well.
Hard to help with almost no informations. But if you want to split on this $ sign. What's wrong with:
string[] bothParts = File.ReadAllText(#"texte\Senzatii\definirea&caracterizarea_senzatiilor.txt")
.Split('$');
string firstPart = bothParts[0];
string secondPart = bothParts.ElementAtOrDefault(1);
richTextBox1.Text = firstPart;
richTextBox2.Text = secondPart;
I use this code to delete lines one by one in richtextbox, but still leaving an empty line (whitespace).
var text = "";//Holds the text of current line being looped.
var startindex = 0;//The position where selection starts.
var endindex = 0;//The length of selection.
for (int i = 0; i < richtextbox1.Lines.Length; i++)//Loops through each line of text in RichTextBox
{
text = richtextbox1.Lines[i]; //Stores current line of text.
startindex = richtextbox1.GetFirstCharIndexFromLine(i);
endindex = text.Length;
richtextbox1.Select(startindex, endindex);
MessageBox.Show(richtextbox1.SelectedText);
richtextbox1.SelectedText = "";
}
How do I delete lines one by one without empty lines (whitespace)?
// Gets the number of newline characters in your rich text box
var numberOfNewLines = richTextBox1.Text.Count(r => r == '\n');
for (var i = 0; i < numberOfNewLines; i++)
{
// Finds the first occurance of the newline character
var newlineCharacterIndex = richTextBox1.Text.IndexOf('\n') + 1;
// Replaces the rich textbox text with everything but the above line
richTextBox1.Text = richTextBox1.Text.Substring(newlineCharacterIndex);
MessageBox.Show("OK!");
}
// Removes the final line.
richTextBox1.Text = string.Empty;
I think you were on the right track, but the way you were doing it was just removing the contents of the line and not the line itself.
I have been reading up on Split string. I am sending data from C# to Excel and some of this text can be rather long. So without using word wrap or autofit with Excel. I would like the data to break at a certain point and continue to the row below it.Can this be accomplished? ProdDescription is the targeted field here. Here is the code I am using to send the basic data over :
worksheet.Cells[3, "E"].Value = txtCustomer.Text;
worksheet.Cells[4, "E"].Value = txtDate.Text;
worksheet.Cells[5, "E"].Value = cboTerms.Text;
worksheet.Cells[6, "E"].Value = txtProposalID.Text;
worksheet.Cells[10, "D"].value = frmProposal.QtyMaintxt.Text;
worksheet.Cells[10, "E"].value = frmProposal.ProdName.Text;
worksheet.Cells[11, "E"].value = frmProposal.ProdDescription.Text;**
worksheet.Cells[10, "F"].value = frmProposal.ListPrice.Text;
worksheet.Cells[10, "G"].value = frmProposal.MaxDiscount.Text;
Try it like this:
string s = "This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. ";
s += "This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. ";
s += "This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. This is a rather long text. ";
var words = s.Split(new char[] { ' ' });
int maxLineCount = 35;
var sb=new System.Text.StringBuilder();
string part=words[0];
int i=1;
while (true) {
if (i >= words.Length)
break;
if ((part + " " + words[i]).Length < maxLineCount)
part += " " + words[i];
else {
sb.AppendLine(part);
part = words[i];
}
i++;
}
var result = sb.ToString();
You could write the generated "lines" into an array or directly into your cells too. I just used Stringbuilder to check the result easily...
I am developing a windows form application using C#.Net. In part of my code I defined a function to log system events. Here is the body of this function:
richTextBoxLog.Text += "-";
richTextBoxLog.Text += some logs and strings ...;
richTextBoxLog.Text += "." + new string(' ', 1000) + Environment.NewLine;
richTextBoxLog.Select(richTextBoxLog.GetFirstCharIndexFromLine(logCounter), richTextBoxLog.Lines[logCounter].Length);
richTextBoxLog.SelectionBackColor = (logCounter % 2 == 0) ? Color.LightBlue: Color.LightGray;
logCounter++;
richTextBoxLog.ScrollToCaret();
the initial value of logCounter is zero (the line of first event refers to logCounter=0). For odd lines the back color should be Color.LightGray and for even lines it should be Color.LightBlue. However as you can see below it does not change the back color properly.
Each time this function is called (to add new text line) the region of richTextBoxLog.Select is updated according to the new line's start and end indices. But when an even line is added to the text box the back color of all of the previous lines turn into blue (even color).
I appreciate your help in advance.
Documentation http://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox.selectionbackcolor.aspx states:
Characters that are entered from that position have the specified SelectionBackColor.
Which seems likely to cause your issues. Although I still can't see how it influences previously added text.
Anyways, you can solve it by repainting all line colors when you add text:
richTextBoxLog.Text += "-";
richTextBoxLog.Text += some logs and strings ...;
richTextBoxLog.Text += "." + new string(' ', 1000) + Environment.NewLine;
var lineCount = 0;
foreach (var line in richTextBoxLog.Lines) {
richTextBoxLog.Select(richTextBoxLog.GetFirstCharIndexFromLine(lineCount), line.Length);
richTextBoxLog.SelectionBackColor = (lineCount % 2 == 0) ? Color.LightBlue : Color.LightGray;
lineCount++;
}
richTextBoxLog.ScrollToCaret();
It should be Helpfull:
public void AppendText(string text, Color color,Color backColor)
{
richTextBox1.SelectionStart = richTextBox1.TextLength;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = color;
richTextBox1.AppendText(text);
richTextBox1.SelectionColor = richTextBox1.ForeColor;
richTextBox1.SelectionBackColor = backColor;
richTextBox1.ScrollToCaret();
}
I'm parsing a text file that has a semi-known repeating structure. There is a heading (1 line), a sub-heading(1 line or 2 lines), and a content area (arbitrary # of lines).
The format for each item in the document is shown below:
=========================
Head Text 1
=========================
SubHead Text1
SubHead Text2
=========================
Content Text Line 1
Content Text Line 2
...
Content Text Line 8
=========================
Head Text 2
=========================
SubHead Text1
SubHead Text2
=========================
Content Text Line 1
Content Text Line 2
...
Content Text Line 6
I would like each section to be inside a unique object, each with 3 sections... somethign like
section1.head
section1.subHead
section1.content
section2.head
section2.subHead
section2.content
The only way I can think of accomplishing this involves a lot of if and while statements. Is there an efficient way of accomplishing this?
I originally tried writing some code in JScipt, but I'm reading a RTF file and C# provides an easy way of converting RTF to plain text. It didn't work very well, I kept skipping some dividers and would get an error at the end of the file.
page = new Array();
fso = new ActiveXObject("Scripting.FileSystemObject");
f = fso.GetFile("test.rtf");
is = f.OpenAsTextStream( forReading, -2 );
var count = 0;
while( !is.AtEndOfStream ){
page[count] = is.ReadLine();
count++; ;
}
is.Close();
WScript.Echo( page[0].text);
var item = [];
var section = 0;
var i = 0, k = 0;
while (i < page.length) {
item[k] = {};
if (!page[i].indexOf("=====")) {
i++;
item[k].head = page[i];
i+=2;
while(page[i].indexOf("=====")) { // WScript.Echo( "index = " + i + " "+ page[i] +"\n" + "Next index = " + (i+1) + " "+ page[i+1] +"\n" );
item[k].subHead += page[i];
i++;
}
k++;
}
i++;
}
If you want to cut on the IFs, you could implement a state pattern submitting each line to the current state.
http://en.wikipedia.org/wiki/State_pattern