Reputation: 3
I have a small application that is keeping track of the copies that have been made by the user.
I then want to be able to output the copy history on an RTF textbox.
copyDisplay.Clear();
string toDisplay = myEntries.getAllEntriesFormated();
copyDisplay.Rtf = toDisplay;
These are the calls I make.
getAllentriesFormated()
loops a list adding what the user has copied.
So you can end up with a string with the following format
"RTF Text
Normal Text"
The problem is that it will display the RTF Text but it will throw an exception because I'm giving it a string that is formatted with both RTF Text and Normal Text.
So, my question is, how can I get both to display at the same time? I can use
copyDisplay.Text = toDisplay
but it displays the text for encoding the RTF Text.
Thanks in advance!
Upvotes: 0
Views: 531
Reputation: 116669
Rather than making a concatenated string with both plain text and RTF, then trying to tease out which portions are which, why not return a list of strings, then append each to the RichTextBox
, testing to see whether each string is RTF or plain text? If you're concerned about the rich text box flashing and redrawing repeatedly as text is appended, you can adapt the solution from How do you prevent a RichTextBox from refreshing its display? to prevent that:
public static class RichTextBoxExtensions
{
public static void SetTextOrRtf(this RichTextBox richTextBox, IEnumerable<string> texts)
{
if (richTextBox == null || texts == null)
throw new ArgumentNullException();
using (richTextBox.BeginUpdate())
{
bool first = true;
richTextBox.Clear();
foreach (var text in texts)
{
if (text == null)
continue;
if (first)
first = false;
else
richTextBox.AppendText("\n");
richTextBox.Select(richTextBox.TextLength, 0);
if (text.IsRtf())
{
richTextBox.SelectedRtf = text;
}
else
{
richTextBox.SelectedText = text;
}
}
richTextBox.SelectionStart = richTextBox.Text.Length;
richTextBox.ScrollToCaret();
}
}
public static bool IsRtf(this string text)
{
// Adapted from http://stackoverflow.com/questions/22502924/how-to-determine-text-format-in-c-sharp
if (text == null)
return false;
const string rtfPrefix = @"{\rtf1";
int start = 0;
for (; start < text.Length && Char.IsWhiteSpace(text[start]); start++)
;
return string.Compare(text, start, rtfPrefix, 0, rtfPrefix.Length, StringComparison.Ordinal) == 0;
}
private const int WM_USER = 0x0400;
private const int EM_SETEVENTMASK = (WM_USER + 69);
private const int WM_SETREDRAW = 0x0b;
class ResetEventMask : IDisposable
{
readonly IntPtr oldEventMask;
RichTextBox richTextBox;
public ResetEventMask(RichTextBox richTextBox, IntPtr oldEventMask)
{
this.richTextBox = richTextBox;
this.oldEventMask = oldEventMask;
}
#region IDisposable Members
public void Dispose()
{
var richTextBox = Interlocked.Exchange(ref this.richTextBox, null);
if (richTextBox != null && !richTextBox.IsDisposed)
{
SendMessage(richTextBox.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
SendMessage(richTextBox.Handle, EM_SETEVENTMASK, IntPtr.Zero, oldEventMask);
}
}
#endregion
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
public static IDisposable BeginUpdate(this RichTextBox richTextBox)
{
if (richTextBox == null)
throw new ArgumentNullException();
// Adapted from http://stackoverflow.com/questions/192413/how-do-you-prevent-a-richtextbox-from-refreshing-its-display
SendMessage(richTextBox.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);
var oldEventMask = (IntPtr)SendMessage(richTextBox.Handle, EM_SETEVENTMASK, IntPtr.Zero, IntPtr.Zero);
return new ResetEventMask(richTextBox, oldEventMask);
}
}
Then call it like:
IEnumerable<string> toDisplay = myEntries.getAllEntriesInList();
copyDisplay.SetTextOrRtf(toDisplay);
Upvotes: 1