I'm trying to create a chat application like msn. When i do "textBox.Text = textBox.Text+text" it updates the textbox and the text i got selected is no longer selected. In MSN you can have selected text and still recieve messages in different colors etc.. How do they do it? I figure its something like push messages, maybe they create a new textbox under another textbox? Any clues?
I hope you guys know what i'm talking about here. I just want my text to behave like MSN used to do, not update the whole textbox, just push a new message under the current message etc.
If I understand your question, you just want text to stay selected when you append messages to a RichTextBox?
int selectionStart = textBox.SelectionStart;
int selectionLength = textBox.SelectionLength;
int carat = textBox.TextLength;
textBox.Text += Environment.NewLine;
textBox.Text += newText;
//optional styling code for newly appended text
textBox.Select(carat, newText.Length);
textBox.SelectionColor = //value;
//etc.
//reapply original selection
if(selectionStart >= 0 && selectionLength > 0)
{
textBox.Select(selectionStart, selectionLength);
}
Related
I have not dealt with WinForms for a long time.
Now I'm stuck with something trivial but cannot figure it out.
I have a Winform and when a Timer Tick happens I want to show a message in a new form message box:
frmMessage frmM = new frmMessage();
frmM.txtMessage.Text = ConfigurationSettings.AppSettings["Message"];
frmM.Show();
It works but the text in the textbox shows as selected(with a blue background).
I tried
txtMessage.SelectionLength = 0;
Did not help.
Also tried to set focus to a different control, did not help either.
for now, as a workaround, I will use a Label.
This is a consequence of the way TextBox Class is implemented. If a selection is not specifically set, all text will be selected when the control gets focus.
From TextBox.OnGotFocus:
Protected override void OnGotFocus(EventArgs e) {
base.OnGotFocus(e);
If (!selectionSet) {
// We get one shot at selecting when we first get focus. If we don't
// do it, we still want to act Like the selection was set.
selectionSet = true;
// If the user didn't provide a selection, force one in.
If (SelectionLength == 0 && Control.MouseButtons == MouseButtons.None) {
SelectAll();
}
}
Additionally due to the way the SelectionLength Property is implemented, setting that property to zero does not set the selectionSet` flag as it is already zero.
Instead, set the TextBox.SelectionStart Property immediately after setting the text as this will set that flag.
txtMessage.SelectionStart = 0;
However, your work-a-round of using a Label to display a message is much more appropriate than using an input control.
This is not the best answer but it works. You can try this
frmMessage frmM = new frmMessage();
frmM.txtMessage.Text = "";
frmM.txtMessage.AppendText(ConfigurationSettings.AppSettings["Message"]);
frmM.Show();
I'm working on a text editor which includes a RichTextBox. One of the features that I want to implement is to show in a TextBox the current Line and Column of the caret of the forementioned RichTextBox at any moment.
Here's part of the code that I use (the rest of my code has nothing to do with my issue):
int selectionStart = richTextBox.SelectionStart;
int lineFromCharIndex = richTextBox.GetLineFromCharIndex(selectionStart);
int charIndexFromLine = richTextBox.GetFirstCharIndexFromLine(lineFromCharIndex);
currentLine = richTextBox.GetLineFromCharIndex(selectionStart) + 1;
currentCol = richTextBox.SelectionStart - charIndexFromLine + 1;
At this point, I should mention that when someone is using a RichTextBox, there are three ways that the caret can change location:
By changing the Text of the RichTextBox
By using the arrow keys on the keyboard
By clicking anywhere on the RichTextBox
The code that I posted above works with no issues in the first two cases. However, it doesn't really work in the third case.
I tried using the Click event and I noticed that the selectionStart variable would always get the value of 0, which means that I always get the same and wrong results. Moreover, using the same code on other events like MouseClick and MouseUp did not solve my problem since selectionStart is 0 even in the duration of these events.
So, how can I get the current Line and column everytime the user clicks on the RichTextBox?
You want something like:
private void richTextBox1_MouseUp(object sender, MouseEventArgs e)
{
RichTextBox box = (RichTextBox)sender;
Point mouseLocation = new Point(e.X, e.Y);
box.SelectionStart = box.GetCharIndexFromPosition(mouseLocation);
box.SelectionLength = 0;
int selectionStart = richTextBox.SelectionStart;
int lineFromCharIndex = box.GetLineFromCharIndex(selectionStart);
int charIndexFromLine = box.GetFirstCharIndexFromLine(lineFromCharIndex);
currentLine = box.GetLineFromCharIndex(selectionStart) + 1;
currentCol = box.SelectionStart - charIndexFromLine + 1;
}
It seems to me that what you really want is to handle the TextBoxBase.SelectionChanged event. Then any action that causes the selection to change will invoke your code, and as an added benefit the current selection will have been updated by the time your event handler is called, and you'll be assured of getting correct values.
If that does not address your specific need, then I must not be understanding the question. In that case, please provide a good, minimal, complete code example that shows clearly what you're trying to do, with a precise description of what that code does and how that's different from what you want it to do.
I'm using the RichEditBox to build a simple editor.
I found a piece of code which toggles bold text on a selection within the document window
private void RichEditBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
var state = Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Control);
if ((state & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down)
{
if (e.Key == Windows.System.VirtualKey.B)
{
if (Editor.Document.Selection.Text.Length > 0)
{
ITextCharacterFormat format = Editor.Document.Selection.CharacterFormat;
format.Bold = FormatEffect.On;
}
else
{
// CTRL + B should toggle bold mode on or off here.
}
}
}
}
When I highlight a piece of text, and press CTRL+B, it bolds the text. Result. However, anything I type after that point is also in bold.
This is not what I expected. According to the code above, I'm affecting the format of the Selection only.
When I select some text and press CTRL+B it should toggle bold formatting on that selection and leave the default format as is.
I've tried using FormatEffect.Toggle
format.Bold = FormatEffect.Toggle
I've tried saving out the Document Character format first, then reapplying
ITextCharacterFormat original_format = Editor.Document.GetDefaultCharacterFormat();
ITextCharacterFormat format = Editor.Document.Selection.CharacterFormat;
format.Bold = FormatEffect.On;
Editor.Document.SetDefaultCharacterFormat(original_format);
This should reset the default back to what it was after bolding. But it doesn't
I could set the selection to nothing, then set format.Bold = FormatEffect.Off again, then reselect the text, but that seems like the long way around (and it probably won't work). There must be a simple way to do this?
NOTE: I have tagged this with the RichTextBox tag as there is no RichEditBox tag. Can someone with >1500 rep add one?
That's the normal behaviour when using SelectionFont and setting bold style with richtextbox.
If the current text selection has more than one font specified, this
property is null. If no text is currently selected, the font specified
in this property is applied to the current insertion point and to all
text that is typed into the control after the insertion point.
It's probably the same issue that you have.
Wordpad and Word work this way too.
I have found a hack, that works. I'm posting this as an answer for anyone who's stuck, but I'm not accepting the answer, because there must be a better one.
private void RichEditBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
var state = Window.Current.CoreWindow.GetKeyState(Windows.System.VirtualKey.Control);
if ((state & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down)
{
if (e.Key == Windows.System.VirtualKey.B)
{
if (Editor.Document.Selection.Text.Length > 0)
{
// text is selected. make it bold
ITextCharacterFormat format =
Editor.Document.Selection.CharacterFormat;
format.Bold = FormatEffect.On;
var start_pos = Editor.Document.Selection.StartPosition;
Editor.Document.Selection.StartPosition =
Editor.Document.Selection.EndPosition;
format.Bold = FormatEffect.Off;
// Editor.Document.Selection.StartPosition = start_pos;
// this is where I was re-selecting the text after switching bold OFF
// but doing so switches it back on again. which makes no sense
}
else
{
// no text selected. just enable bold mode
ITextCharacterFormat format =
Editor.Document.Selection.CharacterFormat;
format.Bold = FormatEffect.Toggle;
}
}
}
}
This isn't perfect, because after you've selected and bolded the text it is automatically de-selected. However in practice I find that this actually works fine for me. Still, it feels like a hack, because it is a hack
I'm calling a public method from another class. It takes in a List as a parameter, and goes through the list printing out each item into a text field. The problem is the text field is remaining empty!. I've checked that the list is populated by outputing the item to the console before I put it into the text box, and the text is coming up fine there.
The list contains strings, and should output each string to the textfield followed by a semi colon.
This is the method which is being called:
public void fillAttachment(List<string> attachList)
{
for (int i = 0; i < attachList.Count; i++)
{
Console.WriteLine("List: " + attachList[i]);
txtAttach.Text += attachList[i] + ";";
}
}
I would solve it in this way:
foreach(var attach in attachList)
{
Console.WriteLine(attach);
txtAttach.AppendText(string.Format("{0};", attach));
}
Setting the text property on a text box and it not displaying could be one of the following:
You are not looking at the same control as you are setting the text in
Could you have instantiated a second copy of the form object and it is this form that you are setting the txtAttach text property in?
Could the control that you are expecting to be populated be a different one? Right click the text box that you want the text to appear in click properties and check the name.
Something else is clearing the textbox after you set it
Right click the txtAttach.Text and click Find All References, this will show you all the places that the Text property is referenced - written and read - in your project. This is a very useful way to locate other interaction with this control.
Fomatting is making the text box appear empty
Is the Font too small, or in the same colour as the background. Can you select the text in the text box?
The easiest way to test all of the above is to create a new text control on your form with a different name, change your code to populate it, check that it is indeed populated, then replace the old one.
As an aside, you could also reduce the code with a single line as follows:
public void fillAttachment(List<string> attachList)
{
txtAttach.Text = String.Join(";", attachList.ToArray());
}
Although this obviously skips out the console write line function.
Not sure why yours doesn't work but I would have done it like this...
public void fillAttachment(List<string> attachList)
{
string result = "";
//OR (if you want to append to existing textbox data)
//string result = txtAttach.Text;
for (int i = 0; i < attachList.Count; i++)
{
Console.WriteLine("List: " + attachList[i]);
result += attachList[i] + ";";
}
txtAttach.Text = result;
}
Does that work for you? If not then there is something else very wrong that is not obvious from your code
I am programatically adding text in a custom RichTextBox using a KeyPress event:
SelectedText = e.KeyChar.ToString();
The problem is that inserting text in such a way doesn't trigger the CanUndo flag.
As such, when I try to Undo / Redo text (by calling the Undo() and Redo() methods of the textbox), nothing happens.
I tried programatically evoking the KeyUp() event from within a TextChanged() event, but that still didn't flag CanUndo to true.
How can I undo text that I insert without having to create lists for Undo and Redo operations ?
Thanks
I finally decided to create my own undo-redo system using stacks.
Here's a quick overview of how I did it :
private const int InitialStackSize = 500;
private Stack<String> undoStack = new Stack<String>(InitialStackSize);
private Stack<String> redoStack = new Stack<String>(InitialStackSize);
private void YourKeyPressEventHandler(...)
{
// The user pressed on CTRL - Z, execute an "Undo"
if (e.KeyChar == 26)
{
// Save the cursor's position
int selectionStartBackup = SelectionStart;
redoStack.Push(Text);
Text = undoStack.Pop();
// Restore the cursor's position
SelectionStart = selectionStartBackup;
}
// The user pressed on CTRL - Y, execute a "Redo"
if (e.KeyChar == 25)
{
if (redoStack.Count <= 0)
return;
// Save the cursor's position
int selectionStartBackup = SelectionStart + redoStack.ElementAt(redoStack.Count - 1).Length;
undoStack.Push(Text);
Text = redoStack.Pop();
// Restore the cursor's position
SelectionStart = selectionStartBackup;
return;
}
undoStack.Push(Text);
SelectedText = e.KeyChar.ToString();
}
It's just an idea but what if you set the caret position to where you would insert your text and instead of modifying the Text property, just send the keys?
SendKeys.Send("The keys I want to send");
There are bound to be quirks but as I said, it's just an idea.
You can use TestBox.Paste. The documentation in the class overview, saying "Sets the selected text to the specified text without clearing the undo buffer.", seems confusing. I have just tried it and it sets the Undo as expected.
Is spite of its name it has no relation to Clipboard at all, it just replaces the currently selected text with the text you provide as an argument, and therefore seems just to do what the question asks for, in very simple manner.