How to append \line into RTF using RichTextBox control - c#

When using the Microsoft RichTextBox control it is possible to add new lines like this...
richtextbox.AppendText(System.Environment.NewLine); // appends \r\n
However, if you now view the generated rtf the \r\n characters are converted to \par not \line
How do I insert a \line control code into the generated RTF?
What does't work:
Token Replacement
Hacks like inserting a token at the end of the string and then replacing it after the fact, so something like this:
string text = "my text";
text = text.Replace("||" "|"); // replace any '|' chars with a double '||' so they aren't confused in the output.
text = text.Replace("\r\n", "_|0|_"); // replace \r\n with a placeholder of |0|
richtextbox.AppendText(text);
string rtf = richtextbox.Rtf;
rtf.Replace("_|0|_", "\\line"); // replace placeholder with \line
rtf.Replace("||", "|"); // set back any || chars to |
This almost worked, it breaks down if you have to support right to left text as the right to left control sequence always ends up in the middle of the placeholder.
Sending Key Messages
public void AppendNewLine()
{
Keys[] keys = new Keys[] {Keys.Shift, Keys.Return};
SendKeys(keys);
}
private void SendKeys(Keys[] keys)
{
foreach(Keys key in keys)
{
SendKeyDown(key);
}
}
private void SendKeyDown(Keys key)
{
user32.SendMessage(this.Handle, Messages.WM_KEYDOWN, (int)key, 0);
}
private void SendKeyUp(Keys key)
{
user32.SendMessage(this.Handle, Messages.WM_KEYUP, (int)key, 0);
}
This also ends up being converted to a \par
Is there a way to post a messaged directly to the msftedit control to insert a control character?
I am totally stumped, any ideas guys? Thanks for your help!

Adding a Unicode "Line Separator" (U+2028) does work as far as my testing showed:
private void Form_Load(object sender, EventArgs e)
{
richText.AppendText("Hello, World!\u2028");
richText.AppendText("Hello, World!\u2028");
string rtf = richText.Rtf;
richText.AppendText(rtf);
}
When I run the program, I get:
Hello, World!
Hello, World!
{\rtf1\ansi\ansicpg1252\deff0\deflang1031{\fonttbl{\f0\fnil\fcharset0 Courier New;}}
{\colortbl ;\red255\green255\blue255;}
\viewkind4\uc1\pard\cf1\f0\fs17 Hello, World!\line Hello, World!\line\par
}
It did add \line instead of \par.

Since you want to use a different RTF code, I think you may need to forget about the simplistic AppendText() method and manipulate the .Rtf property of your RichTextBox directly instead. Here is a sample (tested) to demonstrate:
RichTextBox rtb = new RichTextBox();
//this just gets the textbox to populate its Rtf property... may not be necessary in typical usage
rtb.AppendText("blah");
rtb.Clear();
string rtf = rtb.Rtf;
//exclude the final } and anything after it so we can use Append instead of Insert
StringBuilder richText = new StringBuilder(rtf, 0, rtf.LastIndexOf('}'), rtf.Length /* this capacity should be selected for the specific application */);
for (int i = 0; i < 5; i++)
{
string lineText = "example text" + i;
richText.Append(lineText);
//add a \line and CRLF to separate this line of text from the next one
richText.AppendLine(#"\line");
}
//Add back the final } and newline
richText.AppendLine("}");
System.Diagnostics.Debug.WriteLine("Original RTF data:");
System.Diagnostics.Debug.WriteLine(rtf);
System.Diagnostics.Debug.WriteLine("New Data:");
System.Diagnostics.Debug.WriteLine(richText.ToString());
//Write the RTF data back into the RichTextBox.
//WARNING - .NET will reformat the data to its liking at this point, removing
//any unused colors from the color table and simplifying/standardizing the RTF.
rtb.Rtf = richText.ToString();
//Print out the resulting Rtf data after .NET (potentially) reformats it
System.Diagnostics.Debug.WriteLine("Resulting Data:");
System.Diagnostics.Debug.WriteLine(rtb.Rtf);
Output:
Original RTF data:
{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}
\viewkind4\uc1\pard\f0\fs17\par
}
New RTF Data:
{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}
\viewkind4\uc1\pard\f0\fs17\par
example text0\line
example text1\line
example text2\line
example text3\line
example text4\line
}
Resulting RTF Data:
{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}
\viewkind4\uc1\pard\f0\fs17\par
example text0\line example text1\line example text2\line example text3\line example text4\par
}

if you are using paragraphs to write to richtextbox you can use the LineBreak() same code shown below
Paragraph myParagraph = new Paragraph();
FlowDocument myFlowDocument = new FlowDocument();
// Add some Bold text to the paragraph
myParagraph.Inlines.Add(new Bold(new Run(#"Test Description:")));
myParagraph.Inlines.Add(new LineBreak()); // to add a new line use LineBreak()
myParagraph.Inlines.Add(new Run("my text"));
myFlowDocument.Blocks.Add(myParagraph);
myrichtextboxcontrolid.Document = myFlowDocument;
Hope this helps!

Related

Storing only bold text from a richTextBox

I'm currently in the process of working on a text editor. I want to save only bold words throughout a richTextBox as a string for better search results, but I have no idea how I would accomplish this. If anyone has any ideas please throw them my way. Thanks!
Based on my research, you could get the bold text from the richtextbox by filtering the text from th rtf string.
We note that the bold text will have the following text in the rtf text.
\b Nice\b0
Therefore, we can use the regex to get the bold text
"\\\\b(.*?)\\\\b0"
Here is a code example you can refer to.
private void button1_Click(object sender, EventArgs e)
{
string s = richTextBox1.Rtf;
var match = Regex.Match(s, "\\\\b(.*?)\\\\b0");
string t = string.Empty;
while (match.Success)
{
t = t + match.Groups[1].Value;
match = match.NextMatch();
}
textBox1.Text = t;
textBox1.Font = new Font(textBox1.Font, FontStyle.Bold);
}
Result:

RichTextBox with source of rtf string displays incorrect

I have string with rft formatted text. I believe th string is correct, because when i enter in in notepad and save as rtf document, it is displayed correctly.
The problem is that the highlight is not applied to the text when i try to pass it to RichTextBox.
Expected result is RichtextBox with grey bold text with highlighted word "PORTS", but i get only bold grey text
Rtf string that I pass to RichTextBox:
"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Segoe UI;}}{\colortbl;\red50\green146\blue255;\red235\green153\blue45;\red105\green105\blue105;}\viewkind0\uc1\pard\sa0\sl276\slmult1\cf0\f0\fs32\lang9\b\cf3\highlight2 PORTS\highlight0 documentation. \cf0\b0\par}"
Rtf string that I save as rtf document:
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Segoe UI;}}{\colortbl;\red50\green146\blue255;\red235\green153\blue45;\red105\green105\blue105;}\viewkind0\uc1\pard\sa0\sl276\slmult1\cf0\f0\fs32\lang9\b\cf3\highlight2 PORTS\highlight0 documentation. \cf0\b0\par}
Example of rtf string that is displayed correctly(here text is not bald and not grey):
"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Segoe UI;}}{\colortbl;\red50\green146\blue255;\red235\green153\blue45;\red105\green105\blue105;}\viewkind0\uc1\pard\sa0\sl276\slmult1\cf0\f0\fs30\lang9\highlight2 Port\highlight0 Serial \highlight2 port\highlight0 that uses COM \highlight2 port\highlight0 s\par}"
Method that i use to set string to RithTextBox:
private void UpdateRtf()
{
MemoryStream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(RtfString));
TextRange range = new TextRange(Document.ContentStart, Document.ContentEnd);
range.Load(stream, DataFormats.Rtf);
}

Combobox loading text with invisible linefeed (\r) or newline (\n)

I'm using c#, visual studio 2017, winforms and
I'm having a problem with a combobox which is loading some text from a text file and when I select another line of text from the combobox, a linefeed (\r) is added there, and it looks like it's somewhat invisible or better saying, it looks like a newline (\n).
This is the combobox in question and the invisible linefeed (\r).
https://i.stack.imgur.com/Xhymg.png
When I debug the application I can see \r added after that line of text.
https://i.stack.imgur.com/km4F3.png
I've tried to use Encoding.Unicode when saving the text, but to no avail.
//This is how I save text to a file
private void SaveVarNameToFile()
{
using (var writer = File.AppendText("savedVarName.txt"))
{
writer.Write(comboBox1.Text, Encoding.Unicode);
}
}
//This is how I load the text to combobox
private void LoadStrTextFromFile(string fileName, ComboBox cb)
{
if (!File.Exists(fileName))
return;
using (StreamReader reader = new StreamReader(fileName))
{
string x = reader.ReadToEnd();
string[] y = x.Split('\n');
foreach (string s in y)
{
cb.Items.Add(s);
}
reader.Close();
}
}
Contents of the text file:
BOOST_ROOT
NUMBER_OF_PROCESSORS
OS
PROCESSOR_LEVEL
I'm having a hard time figuring out how to remove that pesky little thing. Perhaps there's an easy fix.
If someone can help me find a way or remove it or modify the code so it won't load the \r, I would be very grateful. Thanks.
Windows uses \r\n to mark the end of a line of text. *NIX and Macs use different markers. You can see how different systems handle this here.
Instead of handling the splitting of lines manually, I recommend using built-in functionality for doing this (i.e. File.ReadLines()):
private void LoadStrTextFromFile(string fileName, ComboBox cb)
{
if (!File.Exists(fileName))
return;
foreach (string line in File.ReadLines(fileName))
cb.Items.Add(line);
}
My approach
// remember to use double back slash on the path
string[] text = System.IO.File.ReadAllLines("C:\\test.txt").Where(line => !string.IsNullOrWhiteSpace(line)).Distinct().ToArray(); // read the file into a string array with removing the duplicates and empty lines
comboBox1.Items.AddRange(text); // finally fill in the combobox with the array

Bullets and pasting into flow document

I need to paste some rtf text from a datagrid into a flow document. I want to paste it at the caret position in the richtextbox. This works except when i have a bullet or Numbered list. It will paste it before the bullet or number.
I have searched every where for this with no luck.
private void dgStandardText_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
if (dgStandardText.SelectedItems.Count > 0) {
foreach(DataRowView row in dgStandardText.SelectedItems) {
byte[] byteArray = Encoding.ASCII.GetBytes(row[3].ToString());
using(MemoryStream ms = new MemoryStream(byteArray)) {
TextRange tr = new TextRange(txtAreaText.CaretPosition, txtAreaText.CaretPosition);
tr.Load(ms, DataFormats.Rtf);
}
}
}
NeedSave = true;
dgStandardText.SelectedItems.Clear();
}
Before Paste
After Paste
This seems to happen when the content you're pasting includes block elements, as opposed to inline elements. For plain text, WPF seems to treat newlines (e.g., \r\n) as paragraph breaks, so multi-line content would be translated into multiple blocks. What you want to do is insert just the inline content from each of those source blocks, such that it goes into the current block of the target document (in this case, a list item). Do this for the first source block, then insert a paragraph break, update the caret position, and move on to the next block.
Is the content of the grid row actually RTF content, or is it plain text? If it's plain text, then this should be pretty straightforward. Try changing your foreach loop body to something like this:
var text = row[3].ToString();
var lines = text.Split(
new[] { '\r', '\n' },
StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var p = txtAreaText.CaretPosition;
txtAreaText.BeginChange();
p.InsertTextInRun(line);
p = p.InsertParagraphBreak();
txtAreaText.EndChange();
txtAreaText.CaretPosition = p;
}
Now, if the source content really is RTF, then things will get more complicated. I suspect you'll need to load it into an in-memory flow document and walk through the elements to figure out where the paragraph breaks are. For each paragraph, locate the inline contents that intersect the selection range, and insert them into the target document. Insert a paragraph break when you reach the end of each paragraph in the source range, just like in the example above.
I'm afraid the Documents API is the one area of WPF that I haven't explored very thoroughly, so I can only give you a general idea of what to do. Perhaps someone else can provide more detail.

RichTextBox loses all the formatting when exporting to word

I copied word content to richtextbox without loosing format perfectly, but now I am editing the content in the richtextbox.
Now I want to export the richtextbox content to a word document without losing any formating, in C# using WinForms. How do you do it?
WordApp.ActiveDocument.SaveAsQuickStyleSet("abc.doc");
Range rng = WordApp.ActiveDocument.Range(0, 0);
for (int i = 0; i < _dgvrow.Cells.Count; ++i)
{
// add code to loop thru controls and TypeText into word document
Label lb = (Label)this.Controls["lblfield" + (i+1).ToString()];
rng.Text += lb.Text;
rng.Select();
Control ctrl = this.Controls["txtfield" + (i+1).ToString()];
if(ctrl is RichTextBox)
{
RichTextBox rb = (RichTextBox)ctrl;
rng.Text += rb.Text + Environment.NewLine;
rng.Select();
}
else if (ctrl is TextBox)
{
TextBox rb = (TextBox)ctrl;
rng.Text += rb.Text + Environment.NewLine;
rng.Select();
}
}
The Text property of a RichTextBox just returns plain text. Use the Rtf property to return rtf-formatted text.
Unfortunately, Word does not have a method for inserting RTF text. However you can paste RTF-text from the clipboard
Clipboard.SetText(rb.Rtf, TextDataFormat.Rtf);
rng.Paste()
You want to get the rich text format of your control, not just the plain text.
Replace rb.Text with rb.Rtf.
From MSDN:
The Text property does not return any information about the formatting applied to the contents of the RichTextBox. To get the rich text formatting (RTF) codes, use the Rtf property.
Additionally, if you want to save the rich text format to a file, that's built in:
rb.SaveFile(yourFilePath);
With running look over your say I can suggest which I coded correctly.
Save your coded rich text box with save file method as .rtf or .doc and then open in the microsoft word.
Will not fail.
with regards.

Categories