Windows Forms RichTextBox cursor position - c#

I have a C# Windows Forms program that has a RichTextBox control. Whenever the text inside the box is changed (other than typing that change), the cursor goes back to the beginning.
In other words, when the text in the RichTextBox is changed by using the Text property, it makes the cursor jump back.
How can I keep the cursor in the same position or move it along with the edited text?
Thanks

You can store the cursor position before making the change, and then restore it afterwards:
int i = richTextBox1.SelectionStart;
richTextBox1.Text += "foo";
richTextBox1.SelectionStart = i;
You might also want to do the same with SelectionLength if you don't want to remove the highlight. Note that this might cause strange behaviour if the inserted text is inside the selection. Then you will need to extend the selection to include the length of the inserted text.

Be careful, if someone refreshes or changes totally the RichTextBox content, the focus method must be invoqued previously in order to move the caret:
richTextBox1.Focus();
int i = richTextBox1.SelectionStart;
richTextBox1.Text = strPreviousBuffer;
richTextBox1.SelectionStart = i;

here's a smaller one, that has the same effect. this.richTextBox1.Select(this.richTextBox1.Text.Length, 0);
That marks 0 chars at the end of the text and sets the cursor to end

Related

Rich text formatting using RichEditBox

I am using RichEditBox for a rich text editor: I use different colors for different keywords in the text while user types the text in the richEditBox control.
Before making changes I save current selection position:
ITextSelection selection = richEditBox.Document.Selection;
int originalStartPosition = selection.StartPosition;
int originalEndPosition = selection.EndPosition;
then I change color of some parts of the text, for example:
selection.SetRange(startIndex, stopIndex);
selection.CharacterFormat.ForegroundColor = Colors.Red;
and after making all changes I restore current selection position:
selection.SetRange(originalStartPosition, originalEndPosition);
This works fine, but SetRange() function affects scrolling position of the text in richEditBox, because it automatically scrolls to make the selected part of the text visible on the screen. So, after all color modifications the scroll position of richEditBox control becomes modified.
Final SetRange() function call puts cursor in its initial place, but not the scroll position.
So, my question is: how can I restore scrolling position of richEditBox control after making color changes? Or how can I modify text color without affecting the scroll position?
It seems it is by design. When we set the cursor in the RichEditBox, then we can scroll the text that we can not see the cursor. After we use the SetRange method, it will scroll to the position that we set the cursor. If the cursor is in the view, it will not scroll.
If you want to scroll to the text range that you set, you should be able to set the PointOptions.Start to the ScrollIntoView method. It will scroll the end of the text range into view.
For example:
ITextSelection selection = MyRichEditBox.Document.Selection;
int originalStartPosition = selection.StartPosition;
int originalEndPosition = selection.EndPosition;
selection.SetRange(600, 610);
selection.CharacterFormat.ForegroundColor = Colors.Red;
selection.SetRange(originalStartPosition, originalEndPosition);
selection.ScrollIntoView(PointOptions.Start);
Edit code:
ITextSelection selection = MyRichEditBox.Document.Selection;
int originalStartPosition = selection.StartPosition;
int originalEndPosition = selection.EndPosition;
selection.SetRange(600, 610);
selection.ScrollIntoView(PointOptions.Start);
await Task.Delay(2000);
selection.CharacterFormat.ForegroundColor = Colors.Red;
selection.SetRange(originalStartPosition, originalEndPosition);

Richtextbox - scroll only if scrollbar is at bottom

I have a RichTextBox and it scrolls with every AppendText, but it shall only scroll if the scrollbar is at bottom. I would like for example to easily select and copy something from the middle of the richtextbox while text is appended to the RichTextBox. Tried many solutions, but nothing really worked correct. Is this even possible?
It depends how you are Appending, but you can tell it to focus back to where the selection (or just cursor) is after appending.
eg (untested, assuming WinForms):
int selStart = rtb.SelectionStart
int selLength = rtb.SelectionLength
rtb.AppendText("test")
rtb.SelectionStart = selStart
rtb.SelectionLength = selLength
That will always push the selection back to where it was before the append - but won't scroll down if it was at the bottom previously. To me, that seems like expected behaviour.

C# Get cursor line in RichTextBox

In C#, I have a RichTextBox, and I want to get the current line of the cursor. Every answer I've found says to use:
int currentLine = richTextBox1.GetLineFromCharIndex(richTextBox1.SelectionStart);
However, richTextBox1.SelectionStart only updates when you make changes to the text. If you move the cursor with the arrow keys, it does not update (I've verified this by printing SelectionStart as I move around).
How do I get the current line of the cursor, in a way that tracks it even if you use the arrow keys to move the cursor around?
I'm using VS2012 in Win8.
Edit: terrybozzio's answer showed the problem. For anyone else with this problem, you can't put the code in richTextBox1_TextChanged. You need to put it in richTextBox1_SelectionChanged.
First you need to get selectionstart,If there isn't
any selected text, the value returned is the position of the caret(with offset in characters from the start of the text),then you call getlinefromcharindex and pass that value,place it in the selectionchanged event and even with arrow keys moving the caret position it will update:
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
int index = richTextBox1.SelectionStart;
int line = richTextBox1.GetLineFromCharIndex(index);
label1.Text = "cursor at line " + line.ToString();
}

Automatic scrolling of textbox choppy

I am redirecting CMD output to a multi-line textbox, I'm trying to auto-scroll down using the following code:
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
textBox1.Refresh();
However it's really choppy looking, by that I mean, each time a line comes in, it positions the scroll bar at the top of the textbox, then to the bottom, it's hard to describe so I made a .gif of it happening: http://i.imgur.com/mudqrZy.gif
Is there any way to fix it?
For the same purpose I use RichTextBox:
richTextBox1.AppendText(cmdOutputMsg + "\r\n");
richTextBox1.ScrollToCaret();
In this way the new text is always added at the end of the existing text, and with ScrollToCaret the focus remains on the last inserted text.
I think with normal TextBox will work in the same way.

TextBox.TextAlign right-side alignment has no effect in certain conditions?

I have a path selector in my Visual C# Express 2010 form application.
I do it using a FolderBrowserDialog and a (single line) TextBox, to show the selected path. Using the following line in my UI refresh code.
this.textBoxFolder.Text = this.folderBrowserDialog1.SelectedPath;
The ReadOnly property is set to true and TextAlign property is set to Right using the form designer, because the selected path is often longer than the TextBox, and I prefer to show the right-side of the path. The forms designer generates this:
//
// textBoxFolder
//
this.textBoxFolder.Location = new System.Drawing.Point(40, 72);
this.textBoxFolder.Name = "textBoxFolder";
this.textBoxFolder.ReadOnly = true;
this.textBoxFolder.Size = new System.Drawing.Size(160, 20);
this.textBoxFolder.TabIndex = 13;
this.textBoxFolder.TabStop = false;
this.textBoxFolder.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
Whenever the chosen path is shorter than the textbox size, the Right alignment works. (But this is not really important)
Whenever the chosen path is longer than the textbox size, the Right alignment has no effect, the string in the textbox is displayed such that the left-most character is visible, and right-most are hidden.
I know that in a normal single line TextBox (ReadOnly = false), when an overly-long string is typed in by hand, the right most chars are visible, even when focus goes away, regardless of whether TextAlign is set to Left / Right / Center!
In other words, my goal is, when TextBox.Text is programmatically set (as opposed to typed in), and the string is longer than the width of the TextBox, how do I get the right-most chars to be visible?
Instead of setting the TextAlign property, you should move the caret to the last character:
textBoxFolder.Text = this.folderBrowserDialog1.SelectedPath;
textBoxFolder.SelectionStart = textBox1.Text.Length - 1;
Setting SelectionStart actually moves the caret to the specified position. And that makes the character at that position visible in the TextBox.
If you can use a Label instead of a text box, you can use the one created by Hans Passant here that uses TextFormatFlags.PathEllipses flag while drawing the text.
Windows Mobile for Pocket PC, Windows Mobile for Smartphone, Windows CE Platform Note: In Pocket PC-based applications, a single-line text box supports only left alignment. A multiline text box can be aligned on the left, right, or center.

Categories