richTextBox1 contains text
I click on a word and Console displays that word for me and it highlights/selects the word i clicked on.
To do this, I keep the index of the character I clicked on then go left and right until I hit a space, -1, or end of file. Now I have the indexes of the beginning and end of the word. The last two lines are supposed to select the word between those two indexes.
However, what happens is that sometimes it highlights the word I want and sometimes it highlights all the words to the right of the character I clicked on.
"omar hello where are you going"
If I click on h in hello, it highlights hello where instead of highlighting hello
If I click on o in going, it will highlight going only as it should
If I click on o in you, it will highlight you going
I used console to check the start and end indexes of the word and they're always right yet for some reason, other words are selected in addition to the word i clicked on
private void richTextBox1_Click(object sender, EventArgs e)
{
int length = richTextBox1.Text.Length;
int rightPart = richTextBox1.SelectionStart;
int leftPart = richTextBox1.SelectionStart - 1;
string rightText = "";
string leftText = "";
while (rightPart != length)
{
if (richTextBox1.Text[rightPart].ToString().CompareTo(" ") != 0)
{
rightText += richTextBox1.Text[rightPart];
rightPart++;
}
else
{
break;
}
}
while (leftPart != -1)
{
if (richTextBox1.Text[leftPart].ToString().CompareTo(" ") != 0)
{
leftText = richTextBox1.Text[leftPart] + leftText;
leftPart--;
}
else
{
break;
}
}
leftPart++;
Console.WriteLine("\nSelected word is " + leftText + rightText + "\n");
richTextBox1.SelectionStart = leftPart;
richTextBox1.SelectionLength = rightPart;
}
The problem appears to be that you are setting the SelectionLength equal to rightPart. Remember this property represents the length of the selection, not the last index of the selection.
Instead, try changing your code to calculate the length by getting the difference between leftPart and rightPart:
richTextBox1.SelectionLength = rightPart - leftPart;
For what it's worth, your code can be shortened a little:
private void richTextBox1_Click(object sender, EventArgs e)
{
if (richTextBox1.TextLength == 0) return;
int rightPart = richTextBox1.SelectionStart;
int leftPart = richTextBox1.SelectionStart - 1;
while (rightPart < richTextBox1.TextLength && richTextBox1.Text[rightPart] != ' ')
{
rightPart++;
}
while (leftPart > -1 && richTextBox1.Text[leftPart] != ' ')
{
leftPart--;
}
leftPart++;
Console.WriteLine($"\nSelected word is " +
richTextBox1.Text.Substring(leftPart, rightPart - leftPart) + "\n");
richTextBox1.SelectionStart = leftPart;
richTextBox1.SelectionLength = rightPart - leftPart;
}
Or even a little more, using IndexOf and LastIndexOf instead of loops to find the spaces:
private void richTextBox1_Click(object sender, EventArgs e)
{
if (richTextBox1.TextLength == 0) return;
// Find the space before this word and after this word
var selStart = Math.Min(richTextBox1.SelectionStart, richTextBox1.TextLength - 1);
var firstSpace = richTextBox1.Text.LastIndexOf(' ', selStart);
var lastSpace = richTextBox1.Text.IndexOf(' ', selStart);
var start = firstSpace + 1;
var length = (lastSpace < 0 ? richTextBox1.TextLength : lastSpace) - start;
Console.WriteLine($"\nSelected word is {richTextBox1.Text.Substring(start, length)} \n");
richTextBox1.SelectionStart = start;
richTextBox1.SelectionLength = length;
}
I was wondering how I would make a picture box become invisible or visible when a certain integer matches.
My program revolves around 2 players going around a board, and when they add there 2 Di up, they will move the amount of spaces.
My problem being, My friend and I have no idea what is wrong with the current code we have, it throws no errors which baffles him, especially myself.
I've made it so my program add's the Di up on every roll, and add's it to the integer.
Anyone have any idea's on whats wrong? If not, a better approach?
Code
private void SelectPos(PictureBox pic)
{
PictureBox[] numbers = { P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7, P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15, P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23, P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31, P1_32, P1_33, P1_34, P1_35, P1_36, P1_37, P1_38, P1_39, P1_40, P1_41, P1_42, P1_43, P1_44, P1_45, P1_46, P1_47, P1_48, P1_49 };
for (int i = 0; i < numbers.Length; i++)
{
if (pic == numbers[i])
{
numbers[i].Visible = true;
MessageBox.Show("k");
}
{
numbers[i].Visible = false;
MessageBox.Show("l");
}
}
}
private void bunifuFlatButton1_Click(object sender, EventArgs e)
{
Roll();
System.Threading.Thread.Sleep(100);
Roll2();
Goes_Num.Text = (int.Parse(Goes_Num.Text) + 1).ToString();
if (Convert.ToInt32(Goes_Num.Text) % 2 == 0)
{
WhichPlayer.Text = "Player 2";
P2_Number.Text = (int.Parse(P2_Number.Text) + 1).ToString();
int p2Int = Convert.ToInt32(P2_Pos.Text);
P2_Pos.Text = (p2Int + dice + dice2).ToString();
}
else if (Convert.ToInt32(Goes_Num.Text) % 2 != 0)
{
WhichPlayer.Text = "Player 1";
P1_Number.Text = (int.Parse(P1_Number.Text) + 1).ToString();
int p1Int = Convert.ToInt32(P1_Pos.Text);
P1_Pos.Text = (p1Int + dice + dice2).ToString();
int P1 = (Convert.ToInt32(P1_Pos.Text));
SelectPos(P1_1);
/*switch (P1)
{
case 1:
P1_1.Visible = true;
break;
case 2:
P1_2.Visible = true;
break;
}*/
/*String[] hi = { "1", "2" };
for (int i = 0; i < hi.Length; i++)
{
var visible = p1
if(visible == hi[i])
{
hi[i].Visible = true;
}
else
{
hi[i].Visible = false;
}
}*/
}
}
(P1-1 all the way to P1-49 are images)
Thanks,
James
It looks like you're trying to pass an int to your SelectPos function but it expects a PictureBox. You could fix this doing something similar to the following:
private void SelectPos(int pic)
{
PictureBox[] numbers = { P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7, P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15, P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23, P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31, P1_32, P1_33, P1_34, P1_35, P1_36, P1_37, P1_38, P1_39, P1_40, P1_41, P1_42, P1_43, P1_44, P1_45, P1_46, P1_47, P1_48, P1_49 };
//Set all picture boxes to be not visible
for (int i = 0; i < numbers.Length; i++)
{
numbers[i].Visible = false;
}
//Set the picture at the given index to visible
numbers[pic].Visible = true;
}
private void bunifuFlatButton1_Click(object sender, EventArgs e)
{
Roll();
System.Threading.Thread.Sleep(100);
Roll2();
Goes_Num.Text = (int.Parse(Goes_Num.Text) + 1).ToString();
if (Convert.ToInt32(Goes_Num.Text) % 2 == 0)
{
WhichPlayer.Text = "Player 2";
P2_Number.Text = (int.Parse(P2_Number.Text) + 1).ToString();
int p2Int = Convert.ToInt32(P2_Pos.Text);
P2_Pos.Text = (p2Int + dice + dice2).ToString();
}
else if (Convert.ToInt32(Goes_Num.Text) % 2 != 0)
{
WhichPlayer.Text = "Player 1";
P1_Number.Text = (int.Parse(P1_Number.Text) + 1).ToString();
int p1Int = Convert.ToInt32(P1_Pos.Text);
P1_Pos.Text = (p1Int + dice + dice2).ToString();
int P1 = (Convert.ToInt32(P1_Pos.Text));
SelectPos(P1);
}
}
You may have to manipulate the value of pic so that it is within the bounds of the array (0-48). For example if pic is between 1 and 49 you would need to subtract 1: numbers[pic-1]. Without seeing your whole program I can't tell you exactly how that part of the code would look but it should be pretty easy to figure out. If you aren't familiar with arrays and indexing check out this link or just Google C# Arrays.
As a side note it would be better to the numbers array as a private member of the class this code is in. Unless the values in the array change there's no point in building the array every time the method is called.
Complete code:
private void SelectPos(int pic)
{
PictureBox[] numbers = { P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7, P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15, P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23, P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31, P1_32, P1_33, P1_34, P1_35, P1_36, P1_37, P1_38, P1_39, P1_40, P1_41, P1_42, P1_43, P1_44, P1_45, P1_46, P1_47, P1_48, P1_49 };
//Set all picture boxes to be not visible
for (int i = 0; i < numbers.Length; i++)
{
numbers[i].Visible = false;
}
//Set the picture at the given index to visible
numbers[pic].Visible = true;
}
private void SelectPos2(int pic2)
{
PictureBox[] numbers2 = { P2_1, P2_2, P2_3, P2_4, P2_5, P2_6, P2_7, P2_8, P2_9, P2_10, P2_11, P2_12, P2_13, P2_14, P2_15, P2_16, P2_17, P2_18, P2_19, P2_20, P2_21, P2_22, P2_23, P2_24, P2_25, P2_26, P2_27, P2_28, P2_29, P2_30, P2_31, P2_32, P2_33, P2_34, P2_35, P2_36, P2_37, P2_38, P2_39, P2_40, P2_41, P2_42, P2_43, P2_44, P2_45, P2_46, P2_47, P2_48, P2_49 };
//Set all picture boxes to be not visible
for (int i = 0; i < numbers2.Length; i++)
{
numbers2[i].Visible = false;
}
//Set the picture at the given index to visible
numbers2[pic2].Visible = true;
}
private void bunifuFlatButton1_Click(object sender, EventArgs e)
{
Roll();
System.Threading.Thread.Sleep(100);
Roll2();
Goes_Num.Text = (int.Parse(Goes_Num.Text) + 1).ToString();
if (Convert.ToInt32(Goes_Num.Text) % 2 == 0)
{
WhichPlayer.Text = "Player 2";
P2_Number.Text = (int.Parse(P2_Number.Text) + 1).ToString();
int p2Int = Convert.ToInt32(P2_Pos.Text);
P2_Pos.Text = (p2Int + dice + dice2).ToString();
int P2 = (Convert.ToInt32(P2_Pos.Text));
SelectPos2(P2);
}
else if (Convert.ToInt32(Goes_Num.Text) % 2 != 0)
{
WhichPlayer.Text = "Player 1";
P1_Number.Text = (int.Parse(P1_Number.Text) + 1).ToString();
int p1Int = Convert.ToInt32(P1_Pos.Text);
P1_Pos.Text = (p1Int + dice + dice2).ToString();
int P1 = (Convert.ToInt32(P1_Pos.Text));
SelectPos(P1);
}
}
text box area that automatically cuts a long paragraph text into 30 characters sentences
i am trying run this code but occurs exception [exception of type 'System.StackOverflowException']
private void txtCutParagraph_TextChanged(object sender, EventArgs e)
{
int limitNum = 30;
string sentence = txtCutParagraph.Text;
string[] words = sentence.Split(' ');
string line = "";
foreach (string word in words)
{
if ((line + word).Length > limitNum)
{
newLine += line + "\r\n";
line = "";
}
line += word + " ";
}
if (line.Length > 0)
newLine += line + "\r\n";
txtCutParagraph.Text = newLine;
}
If the form is freezing is because that txtCutParagraph_TextChanged event is firing infinitely, because you are changing the text of textbox at the end of the event: txtCutParagraph.Text = newLine;, so it means that change text in the textbox, and the event will fire again and again.
To prevent this form from freezing please move your code to another event of textbox, named KeyPress as:
private void txtCutParagraph_KeyPress(object sender, KeyPressEventArgs e)
{
int limitNum = 30;
string sentence = txtCutParagraph.Text;
string[] words = sentence.Split(' ');
string line = "";
foreach (string word in words)
{
if ((line + word).Length > limitNum)
{
newLine += line + "\r\n";
line = "";
}
line += word + " ";
}
if (line.Length > 0)
newLine += line + "\r\n";
txtCutParagraph.Text = newLine;
}
What you are trying to do is called Word wrapping. TextBox class has Wordwrap option by default. unfortunately you cant limit number of characters per line.
You have to write an algorithm instead. I have noticed that your algorithm does not work correctly. so i decided to write one my self (as it was a good practice!). It is hard to handle all situations that can happen inside text formatting. I tried my best anyway you have to write one your self if you are not satisfied with results.
Before using this algorithm you have to disable Wordwrap feature of Textbox. So they will not Interfere each other. In InitializeComponent inside Form Designer add this line.
this.textBox1.WordWrap = false;
Now use this algorithm to do it for you! Note that textbox1 is a multi line text box.
private StringBuilder stringBuilder = new StringBuilder();
private bool _isInsideTextChanged = false;
private const int MaximumChars = 30; // Maximum characters
private StringBuilder WrapText(StringBuilder text, ref int position)
{
StringBuilder newStringBuilder = new StringBuilder(text.ToString());
int charsPerLine = 0;
int lastSpace = -1; // index of last space per line
for (int i = 0; i < newStringBuilder.Length; i++)
{
if (newStringBuilder[i] == ' ')
{
if (newStringBuilder.Length > i + 2 && newStringBuilder.ToString(i + 1, 2) == "\r\n")
{
if (newStringBuilder.Length > i + 3)
{
int next = newStringBuilder.ToString().IndexOf(' ', i + 3);
if (next != -1 && charsPerLine + next - i <= MaximumChars || charsPerLine + newStringBuilder.Length - i - 2 <= MaximumChars)
{
newStringBuilder.Remove(i + 1, 2);
if (i <= textBox1.SelectionStart)
{
position -= 2;
}
continue;
}
}
i++;
continue;
}
if (newStringBuilder.Length > i + 1 && newStringBuilder[i + 1] != ' ')
{
lastSpace = i;
}
}
if (newStringBuilder[i] == '\n' || newStringBuilder[i] == '\r')
{
lastSpace = -1;
charsPerLine = 0;
}
if (++charsPerLine > MaximumChars && lastSpace != -1)
{
newStringBuilder.Insert(lastSpace + 1, "\r\n");
if (lastSpace <= textBox1.SelectionStart)
{
position += 2;
}
charsPerLine = i - lastSpace;
lastSpace = -1;
i++;
}
}
return newStringBuilder;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (_isInsideTextChanged) return;
_isInsideTextChanged = true;
stringBuilder.Clear();
stringBuilder.Append(textBox1.Text);
int position = textBox1.SelectionStart;
string newText = WrapText(stringBuilder, ref position).ToString();
textBox1.Text = newText;
textBox1.SelectionStart = position;
_isInsideTextChanged = false;
}
Here is the test that shows the results.
How this wroks?
This algorithm will count the number of characters from last line break index (default value is 0) up to last space character index per line.(default value is -1 means no space in that line). Then it will put line break after last space if the number of characters on that line is more than 30. How ever this algorithm test other things too to better handle text formatting.
This is done every time a textbox value is changed. StringBuilder is used instead of string to increase performance.
To prevent stack overflow exception as described by #KhaksarWeqar I used a boolean value _isInsideTextChanged with TextChanged event:
private bool _isInsideTextChanged = false;
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (_isInsideTextChanged) return; // return if was inside TextChanged.
_isInsideTextChanged = true; // inside TextChanged
// Do stuff...
_isInsideTextChanged = false; // outside TextChanged
}
There is also a better way explained on wiki. you can create your own even better!. https://en.wikipedia.org/wiki/Line_wrap_and_word_wrap
i was doing a ITP assignment, when i got an error. The code for the part with the problem is:
private void btnAddWord_Click(object sender, EventArgs e)
{
//if the textbox is empty
if (string.IsNullOrEmpty(tbxAddWord.Text))
{
MessageBox.Show("You have entered no characters in the textbox.");
tbxAddWord.Focus();
}
//if the number of items in the listbox is greater than 29
else if (lbxUnsortedList.Items.Count > 29)
{
MessageBox.Show("You have exceeded the maximum number of words in the list.");
tbxAddWord.Text = "";
}
//error message for entering word that is already in the list
bool contains = false;
for (int i = 0; i < lbxUnsortedList.Items.Count; i++)
{
if (lbxUnsortedList.Items[i].ToString().ToLower() == this.tbxAddWord.Text.ToString().ToLower())
{
contains = true;
}
}
//if there is no match in the list
if (!contains)
{
//add word to the listbox
lbxUnsortedList.Items.Add(tbxAddWord.Text);
//update tbxListBoxCount
tbxListboxCount.Text = lbxUnsortedList.Items.Count.ToString();
//onclick, conduct the bubble sort
bool swapped;
string temp;
do
{
swapped = false;
for (int i = 0; i < lbxUnsortedList.Items.Count - 1; i++)
{
int result = CarNameData[i].ToString().CompareTo(CarNameData[i + 1]);
if (result > 0)
{
temp = CarNameData[i];
CarNameData[i] = CarNameData[i + 1];
CarNameData[i + 1] = temp;
swapped = true;
}
}
} while (swapped == true);
tbxAddWord.Text = "";
}
// if there is a match in the list
else
{
MessageBox.Show("The word that you have added is already on the list");
tbxAddWord.Text = "";
tbxAddWord.Focus();
}
}
When i leave the textbox blank and click the add button, it comes up with the error message, but still adds a blank space. how do i stop this from happening?
You need to return from the method if you don't want to execute more code:
if (string.IsNullOrEmpty(tbxAddWord.Text))
{
MessageBox.Show("You have entered no characters in the textbox.");
tbxAddWord.Focus();
return;
}
//if the number of items in the listbox is greater than 29
else if (lbxUnsortedList.Items.Count > 29)
{
MessageBox.Show("You have exceeded the maximum number of words in the list.");
tbxAddWord.Text = "";
return;
}
First thing is if you are using CarNameData list as Generic collection list List<string> its allows inbuilt sort method like CarNameData.Sort();
Second thing you have to put your code in else part like this
private void btnAddWord_Click(object sender, EventArgs e)
{
//if the textbox is empty
if (string.IsNullOrEmpty(tbxAddWord.Text))
{
MessageBox.Show("You have entered no characters in the textbox.");
tbxAddWord.Focus();
}
else
{
//if the number of items in the listbox is greater than 29
if (lbxUnsortedList.Items.Count > 29)
{
MessageBox.Show("You have exceeded the maximum number of words in the list.");
tbxAddWord.Text = "";
}
//error message for entering word that is already in the list
bool contains = false;
for (int i = 0; i < lbxUnsortedList.Items.Count; i++)
{
if (lbxUnsortedList.Items[i].ToString().ToLower() == this.tbxAddWord.Text.ToString().ToLower())
{
contains = true;
}
}
//if there is no match in the list
if (!contains)
{
//add word to the listbox
lbxUnsortedList.Items.Add(tbxAddWord.Text);
//update tbxListBoxCount
tbxListboxCount.Text = lbxUnsortedList.Items.Count.ToString();
//onclick, conduct the bubble sort
bool swapped;
string temp;
do
{
swapped = false;
for (int i = 0; i < lbxUnsortedList.Items.Count - 1; i++)
{
int result = CarNameData[i].ToString().CompareTo(CarNameData[i + 1]);
if (result > 0)
{
temp = CarNameData[i];
CarNameData[i] = CarNameData[i + 1];
CarNameData[i + 1] = temp;
swapped = true;
}
}
} while (swapped == true);
tbxAddWord.Text = "";
}
// if there is a match in the list
else
{
MessageBox.Show("The word that you have added is already on the list");
tbxAddWord.Text = "";
tbxAddWord.Focus();
}
}
}
I'm developing a text editor in C#, and I'm trying to make a line count.
private void updateNumberLabel()
{
Point pos = new Point(0, 0);
int firstIndex = Document.GetCharIndexFromPosition(pos);
int firstLine = Document.GetLineFromCharIndex(firstIndex);
pos.X = ClientRectangle.Width;
pos.Y = ClientRectangle.Height;
int lastIndex = Document.GetCharIndexFromPosition(pos);
int lastLine = Document.GetLineFromCharIndex(lastIndex);
int actualLine = Document.GetLineFromCharIndex(actualPos);
pos = Document.GetPositionFromCharIndex(lastIndex);
if (lastLine != actualLine)
{
numberLabel.Text = "";
for (int i = firstLine; i <= lastLine + 1; i++)
{
numberLabel.Text += i + 1 + "\n";
}
}
}
It works fine and adds the number of lines while you write them, but if you delete one, it will only update if you delete or add one more line.
I want make it instantaneous. If you delete one, the count shall be decreased instantaneously.
Maybe this is too easy, but what about that:
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
var lineCount = richTextBox.Lines.Count();
numberLabel.Text = lineCount.ToString();
}
Make sure you assign it to the TextChanged event.
If this is not what you need, please add some more information what you are trying to achieve.
I'm really late, but Lines is an array of string. Just get the length.
richTexBox.Lines.Length.ToString();
I have found one open source and applied it to this problem.
I have confirmed that it works well and have implemented it.
RichTextBox Colums and Row
Simple Code(
The link has a demo source.):
this.rtb.CursorPositionChanged +=
new System.EventHandler(this.rtb_CursorPositionChanged);
this.rtb.SelectionChanged +=
new System.EventHandler(this.rtb_SelectionChanged);
.
.
.
private void rtb_CursorPositionChanged(object sender, System.EventArgs e)
{
int line = rtb.CurrentLine;
int col = rtb.CurrentColumn;
int pos = rtb.CurrentPosition;
statusBar.Text = "Line " + line + ", Col " + col +
", Position " + pos;
}
private void rtb_SelectionChanged(object sender, System.EventArgs e)
{
int start = rtb.SelectionStart;
int end = rtb.SelectionEnd;
int length = rtb.SelectionLength;
statusBar.Text = "Start " + start + ", End " + end +
", Length " + length;
}
namespace Nik.UserControls
{
public class RicherTextBox2 : System.Windows.Forms.RichTextBox
{
public event EventHandler CursorPositionChanged;
protected virtual void OnCursorPositionChanged( EventArgs e )
{
if ( CursorPositionChanged != null )
CursorPositionChanged( this, e );
}
protected override void OnSelectionChanged( EventArgs e )
{
if ( SelectionLength == 0 )
OnCursorPositionChanged( e );
else
base.OnSelectionChanged( e );
}
public int CurrentColumn
{
get { return CursorPosition.Column( this, SelectionStart ); }
}
public int CurrentLine
{
get { return CursorPosition.Line( this, SelectionStart ); }
}
public int CurrentPosition
{
get { return this.SelectionStart; }
}
public int SelectionEnd
{
get { return SelectionStart + SelectionLength; }
}
}
internal class CursorPosition
{
[System.Runtime.InteropServices.DllImport("user32")]
public static extern int GetCaretPos(ref Point lpPoint);
private static int GetCorrection(RichTextBox e, int index)
{
Point pt1 = Point.Empty;
GetCaretPos(ref pt1);
Point pt2 = e.GetPositionFromCharIndex(index);
if ( pt1 != pt2 )
return 1;
else
return 0;
}
public static int Line( RichTextBox e, int index )
{
int correction = GetCorrection( e, index );
return e.GetLineFromCharIndex( index ) - correction + 1;
}
public static int Column( RichTextBox e, int index1 )
{
int correction = GetCorrection( e, index1 );
Point p = e.GetPositionFromCharIndex( index1 - correction );
if ( p.X == 1 )
return 1;
p.X = 0;
int index2 = e.GetCharIndexFromPosition( p );
int col = index1 - index2 + 1;
return col;
}
}
}
Los799
Sorry for answering a "bit" late, I saw this question just now.
But if the problem still stands, here's a simple way to count lines, just use a foreach loop:
int CountOfLines = 1;//1 because min 1 line is always in a text of a control, that has a Text property
foreach (char c in YourText)
{
if (c == '\r' | c == '\n')//these are all equal the ENTER key
{
CountOfLines++;
}
}
You can also use foreach to count characters as well, but with foreach you can choose characters, that you don't want to be counted in the count of characters. For example:
int CountOfCharacters = 0;//0 because by default there are no characters in a textbox or label.
foreach (char c in YourText)
{
if (c != '\t' & c != '\n' & c != '\r')//in this example I want to count only the characters that are not an ENTER or a TAB.
{
CountOfCharacters++;
}
}
Hope this helps you and everybody else, who's reading this, even if it's a bit late answer. :)
Instead of trying to battle with the default rich text box, why don't you try making your own control so you have full control of the text formatting?
After all, if you're developing your own text editor, it would make sense to have text stored and managed in a way that makes sense to you, the developer, instead of trying to fight with a format designed for a slightly different purpose.
Newer solution to this question for WPF applications
DOK1 is a WPF flow document
TX1 is a TextBox control
TX1.Text = DOK1.Blocks.Count.ToString();