Reputation: 11754
I'm trying to "reset" the formatting in my RichTextBox (WinForms, not WPF). I was previously using
richTextBox.Text = richTextBox.Text;
However, that seems to have suddenly failed me. Now no matter what I set richTextBox.Text
to, it retains some of the rtf formatting.
I've tried
richTextBox.Rtf = richTextBox.Text;
However, that complains about an incorrect format. There's gotta be a better way to do this. (Of course, selecting the entire thing, then resetting the back color, fore color, and font works, but that results in a flicker as the entire thing is selected then deselected, plus it's slower and requires a lot more code.) Anyone have any idea?
Edit: I've gotten this to work:
string tempTxt = richTextBox.Text;
richTextBox.Clear();
richTextBox.Text = tempTxt;
But there has to be a better way, right?
Edit 2: To be clear, I wish to remove all formatting while retaining the text. It looks like the code in the first edit will ship, unless anyone else has a more efficient/better coding way.
Edit 3:
richTextBox.Text = richTextBox.Text.ToString();
doesn't seem to work because it still doesn't clear all the formatting. The reason I don't like the method in the first Edit above is it makes the text box "flash" when it clears it then re-inputs the text. It seems like there should simply be a richTextBox.ResetFormatting() method, or some way to access the same functionality, as the Clear() method clearly (no pun intended) does some sort of formatting reset in addition to simply clearing all the text.
To summarize:
Is there a way (and if so, what is it) to reset the formatting of the text in a RichTextBox without clearing the text as in the example above (because that produces undesirable flashing)?
Upvotes: 20
Views: 22682
Reputation: 459
works fine ..
var TempString = richTextBox1.Text;
richTextBox1.Rtf = string.Empty;
richTextBox1.Text = TempString ;
Upvotes: -1
Reputation: 1120
I see that there are many answers, but I think that there is more simple and easy approach as the extension to clear all the formatting:
In my case I needed clear the formatting and leave an empty RichTextBox
, therefore I made this function:
private void ClearRichTextBox()
{
this.richTextBox1.ForeColor = Color.Empty;
this.richTextBox1.BackColor = Color.Empty;
this.richTextBox1.SelectAll();
this.richTextBox1.SelectionColor = Color.Empty;
this.richTextBox1.SelectionBackColor = Color.Empty;
this.richTextBox1.SelectionFont = this.richTextBox1.Font;
this.richTextBox1.Clear();
}
Then the easy solution is:
string backUp = this.richTextBox1.Text;
ClearRichTextBox();
this.richTextBox1.Text = backUp;
Or simply remove the this.richTextBox1.Clear();
line in the clear function. (This will probably also work but I give no guarantee since I tested this only on simple formattings. Therefore it can be, that any other line should be added to remove a different formatting.)
When the text should be not cleared remember to store previous position/selection and refresh state after deformatting of data.
Upvotes: 1
Reputation: 3648
For a while, I've been using this code in my own program. It sets the RTF of the RichTextBox directly, so should be much faster than setting styles the usual way. It takes in a string (the main text), and optionally also takes a Color array, font size array (int), and font-weight array (bool), each which represents every colour, size or font-weight for every character in the string.
Alternatively, you can simply keep the default size, weight, italic numbers given by the header.
public string text2RTF(string text, Color[] color = null, bool[] bold = null, int[] size = null,
string font = "Microsoft Sans Serif", double defaultFontSize = 16,
bool defaultFontBold = false, bool defaultFontItalic = false, char align = 'l')
{
StringBuilder rtf = new StringBuilder();
rtf.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang2057{\fonttbl{\f0\fnil\fcharset0 ");
rtf.Append(font);
rtf.Append(@";}}{\colortbl ;");
if (color != null)
{
rtf.Append("\\red" + (color[0].R).ToString() + "\\green" + (color[0].G).ToString() + "\\blue" + (color[0].B).ToString() + ";");
for (int i = 1; i < text.Length; i++)
{
if ((color[i].R != color[i - 1].R || color[i].G != color[i - 1].G || color[i].B != color[i - 1].B))
{
rtf.Append("\\red" + (color[i].R).ToString() + "\\green" + (color[i].G).ToString() + "\\blue" + (color[i].B).ToString() + ";");
}
}
}
rtf.Append("}\n\\viewkind4\\uc1\\pard");
if (defaultFontBold == true) rtf.Append("\\b");
if (defaultFontItalic == true) rtf.Append("\\i");
if (align == 'r') rtf.Append("\\qr");
rtf.Append("\\f0\\fs" + (Math.Round(defaultFontSize)).ToString()+" ");
int startOfActualText = rtf.Length;
int count = 1;
for (int i = 0; i < text.Length; i++)
{
if (color!=null && (i == 0 || color[i].R != color[i - 1].R || color[i].G != color[i - 1].G || color[i].B != color[i - 1].B))
{
rtf.Append("\\cf"); rtf.Append(count.ToString() + " "); count++;
}
if (bold!=null && (i == 0 || bold[i] != bold[i - 1]))
{
if (bold[i] == true) rtf.Append("\\b1 ");
else rtf.Append("\\b0 ");
}
if (size!=null && (i == 0 || size[i] != size[i - 1]))
{
rtf.Append("\\fs"+size[i].ToString()+" " );
}
if (text[i] == '\\' || text[i] == '}' || text[i] == '{') rtf.Append('\\');
// GetRtfUnicodeOfChar:
string st="";
if (text[i] <= 0x7f) st = text[i].ToString();
else st = "\\u" + Convert.ToUInt32(text[i]) + "?";
rtf.Append(st);
}
rtf.Append("\n}");
rtf.Replace("\n", "\\par\n", startOfActualText, rtf.Length - startOfActualText);
return rtf.ToString();
}
Upvotes: 1
Reputation: 11
"The reason I don't like the method in the first Edit above is it makes the text box "flash" when it clears it then re-inputs the text."
You should be able to implement the SuspendLayout() and ResumeLayout() methods.
string tempTxt = richTextBox.Text;
rtbIncludes.SuspendLayout();
richTextBox.Clear();
richTextBox.Text = tempTxt;
rtbIncludes.ResumeLayout();
SuspendLayout() and ResumeLayout() will stop the control from drawing while you manipulate the data. If the operation doesn't take to long, you will be able to clear the text and assign the unformatted text back without it appearing to flash on the screen.
If it does take too long, the control will appear as a black rectangle until ResumeLayout() is called.
Upvotes: 1
Reputation: 4216
RichTextBox rtbTemp = new RichTextBox();
rtbTemp.Text = rtb.Text;
rtb.Rtf = rtbTemp.Rtf;
hope it works
Upvotes: -1
Reputation: 64248
Saddly I've done my VERY best effort to slim this down to only the required code. It's still big, but it will work. The RichTextBox api in .Net is very limited, to do anything you almost have to thunk into the Win32 library. I've built a entire library around this thing just so I can toggle bold and determine if bold is actually set across the selection.
Usage:
RichTextBox te = ...;
te.ClearAllFormatting(new Font("Microsoft Sans Serif", 8.25f));
Tons of code:
static class RichTextExtensions
{
public static void ClearAllFormatting(this RichTextBox te, Font font)
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = CFM_ALL2;
fmt.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
fmt.szFaceName = font.FontFamily.Name;
double size = font.Size;
size /= 72;//logical dpi (pixels per inch)
size *= 1440.0;//twips per inch
fmt.yHeight = (int)size;//165
fmt.yOffset = 0;
fmt.crTextColor = 0;
fmt.bCharSet = 1;// DEFAULT_CHARSET;
fmt.bPitchAndFamily = 0;// DEFAULT_PITCH;
fmt.wWeight = 400;// FW_NORMAL;
fmt.sSpacing = 0;
fmt.crBackColor = 0;
//fmt.lcid = ???
fmt.dwMask &= ~CFM_LCID;//don't know how to get this...
fmt.dwReserved = 0;
fmt.sStyle = 0;
fmt.wKerning = 0;
fmt.bUnderlineType = 0;
fmt.bAnimation = 0;
fmt.bRevAuthor = 0;
fmt.bReserved1 = 0;
SendMessage(te.Handle, EM_SETCHARFORMAT, SCF_ALL, ref fmt);
}
private const UInt32 WM_USER = 0x0400;
private const UInt32 EM_GETCHARFORMAT = (WM_USER + 58);
private const UInt32 EM_SETCHARFORMAT = (WM_USER + 68);
private const UInt32 SCF_ALL = 0x0004;
private const UInt32 SCF_SELECTION = 0x0001;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, UInt32 wParam, ref CHARFORMAT2 lParam);
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)]
struct CHARFORMAT2
{
public int cbSize;
public uint dwMask;
public uint dwEffects;
public int yHeight;
public int yOffset;
public int crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string szFaceName;
public short wWeight;
public short sSpacing;
public int crBackColor;
public int lcid;
public int dwReserved;
public short sStyle;
public short wKerning;
public byte bUnderlineType;
public byte bAnimation;
public byte bRevAuthor;
public byte bReserved1;
}
#region CFE_
// CHARFORMAT effects
const UInt32 CFE_BOLD = 0x0001;
const UInt32 CFE_ITALIC = 0x0002;
const UInt32 CFE_UNDERLINE = 0x0004;
const UInt32 CFE_STRIKEOUT = 0x0008;
const UInt32 CFE_PROTECTED = 0x0010;
const UInt32 CFE_LINK = 0x0020;
const UInt32 CFE_AUTOCOLOR = 0x40000000; // NOTE: this corresponds to
// CFM_COLOR, which controls it
// Masks and effects defined for CHARFORMAT2 -- an (*) indicates
// that the data is stored by RichEdit 2.0/3.0, but not displayed
const UInt32 CFE_SMALLCAPS = CFM_SMALLCAPS;
const UInt32 CFE_ALLCAPS = CFM_ALLCAPS;
const UInt32 CFE_HIDDEN = CFM_HIDDEN;
const UInt32 CFE_OUTLINE = CFM_OUTLINE;
const UInt32 CFE_SHADOW = CFM_SHADOW;
const UInt32 CFE_EMBOSS = CFM_EMBOSS;
const UInt32 CFE_IMPRINT = CFM_IMPRINT;
const UInt32 CFE_DISABLED = CFM_DISABLED;
const UInt32 CFE_REVISED = CFM_REVISED;
// CFE_AUTOCOLOR and CFE_AUTOBACKCOLOR correspond to CFM_COLOR and
// CFM_BACKCOLOR, respectively, which control them
const UInt32 CFE_AUTOBACKCOLOR = CFM_BACKCOLOR;
#endregion
#region CFM_
// CHARFORMAT masks
const UInt32 CFM_BOLD = 0x00000001;
const UInt32 CFM_ITALIC = 0x00000002;
const UInt32 CFM_UNDERLINE = 0x00000004;
const UInt32 CFM_STRIKEOUT = 0x00000008;
const UInt32 CFM_PROTECTED = 0x00000010;
const UInt32 CFM_LINK = 0x00000020; // Exchange hyperlink extension
const UInt32 CFM_SIZE = 0x80000000;
const UInt32 CFM_COLOR = 0x40000000;
const UInt32 CFM_FACE = 0x20000000;
const UInt32 CFM_OFFSET = 0x10000000;
const UInt32 CFM_CHARSET = 0x08000000;
const UInt32 CFM_SMALLCAPS = 0x0040; // (*)
const UInt32 CFM_ALLCAPS = 0x0080; // Displayed by 3.0
const UInt32 CFM_HIDDEN = 0x0100; // Hidden by 3.0
const UInt32 CFM_OUTLINE = 0x0200; // (*)
const UInt32 CFM_SHADOW = 0x0400; // (*)
const UInt32 CFM_EMBOSS = 0x0800; // (*)
const UInt32 CFM_IMPRINT = 0x1000; // (*)
const UInt32 CFM_DISABLED = 0x2000;
const UInt32 CFM_REVISED = 0x4000;
const UInt32 CFM_BACKCOLOR = 0x04000000;
const UInt32 CFM_LCID = 0x02000000;
const UInt32 CFM_UNDERLINETYPE = 0x00800000; // Many displayed by 3.0
const UInt32 CFM_WEIGHT = 0x00400000;
const UInt32 CFM_SPACING = 0x00200000; // Displayed by 3.0
const UInt32 CFM_KERNING = 0x00100000; // (*)
const UInt32 CFM_STYLE = 0x00080000; // (*)
const UInt32 CFM_ANIMATION = 0x00040000; // (*)
const UInt32 CFM_REVAUTHOR = 0x00008000;
const UInt32 CFE_SUBSCRIPT = 0x00010000; // Superscript and subscript are
const UInt32 CFE_SUPERSCRIPT = 0x00020000; // mutually exclusive
const UInt32 CFM_SUBSCRIPT = (CFE_SUBSCRIPT | CFE_SUPERSCRIPT);
const UInt32 CFM_SUPERSCRIPT = CFM_SUBSCRIPT;
// CHARFORMAT "ALL" masks
const UInt32 CFM_EFFECTS = (CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_COLOR |
CFM_STRIKEOUT | CFE_PROTECTED | CFM_LINK);
const UInt32 CFM_ALL = (CFM_EFFECTS | CFM_SIZE | CFM_FACE | CFM_OFFSET | CFM_CHARSET);
const UInt32 CFM_EFFECTS2 = (CFM_EFFECTS | CFM_DISABLED | CFM_SMALLCAPS | CFM_ALLCAPS
| CFM_HIDDEN | CFM_OUTLINE | CFM_SHADOW | CFM_EMBOSS
| CFM_IMPRINT | CFM_DISABLED | CFM_REVISED
| CFM_SUBSCRIPT | CFM_SUPERSCRIPT | CFM_BACKCOLOR);
const UInt32 CFM_ALL2 = (CFM_ALL | CFM_EFFECTS2 | CFM_BACKCOLOR | CFM_LCID
| CFM_UNDERLINETYPE | CFM_WEIGHT | CFM_REVAUTHOR
| CFM_SPACING | CFM_KERNING | CFM_STYLE | CFM_ANIMATION);
#endregion
}
More you ask?
I use most of this via a small utility class that wraps this for all the styles and font changes. This way you can change font-size and not change font name, etc.
class RichTextStyle
{
private readonly Control _textEdit;
private readonly CHARFORMAT2 _charFormat;
public RichTextStyle(RichTextBox te)
{
_textEdit = te;
_charFormat = new CHARFORMAT2();
_charFormat.cbSize = Marshal.SizeOf(_charFormat);
SendMessage(te.Handle, EM_GETCHARFORMAT, SCF_SELECTION, ref _charFormat);
}
private void SetEffect(UInt32 mask, UInt32 effect, bool valid)
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = mask;
fmt.dwEffects = valid ? effect : 0;
SendMessage(_textEdit.Handle, EM_SETCHARFORMAT, SCF_SELECTION, ref fmt);
}
private bool GetEffect(UInt32 mask, UInt32 effect)
{
return (0 != (_charFormat.dwMask & mask)) && (0 != (_charFormat.dwEffects & effect));
}
public bool Bold { get { return GetEffect(CFM_BOLD, CFE_BOLD); } set { SetEffect(CFM_BOLD, CFE_BOLD, value); } }
public bool Italic { get { return GetEffect(CFM_ITALIC, CFE_ITALIC); } set { SetEffect(CFM_ITALIC, CFE_ITALIC, value); } }
// ... etc ... etc ... you get the idea.
Upvotes: 28
Reputation: 192657
I have used
var t = richTextBox1.Text;
richTextBox1.Text = t;
EDIT::
be sure to insert a comment as to why you're doing what you're doing. To the unaware, it looks ridiculous.
Upvotes: 3
Reputation: 11754
Another way I've found (and the one that I have switched to using, as it doesn't flash) is to grab the initial rtf string before any formatting is applied:
string initialRtf = richTextBox.Rtf;
Then, when I want to reset the formatting, I can just do:
richTextBox.Rtf = initialRtf;
However, this isn't really perfect, because it requires that the text stay the same and such. Well, at least it's a little better than the method detailed in the question.
Upvotes: 1
Reputation: 11662
Just using:
richTextBox1.Clear();
... Should do the trick. Works for me.
Upvotes: 2