views:

1606

answers:

6

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)?

A: 

Just using:

richTextBox1.Clear();

... Should do the trick. Works for me.

baeltazor
For me that clears all the text -- I need the text to still be there, without the formatting. I'm currently using .Clear() in conjunction with a temporary string, as seen in the edit above.
NickAldwin
A: 

What about

richTextBox.Text = richTextBox.Text.ToString();
Mike B
thank you so much!
NickAldwin
You are most welcome, I was happy to actually see a question I could answer!
Mike B
Ack, we've done some more testing, and this doesn't quite work for us. It seems Clear() does something that this does not. Sorry!
NickAldwin
-1 why would Text.ToString() be any different than Text which the OP already tried?
csharptest.net
A: 

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.

NickAldwin
A: 

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.

Cheeso
Wait, so does the use of "var" make it think you're giving it different text? Because just richTextBox.Text = richTextBox.Text or = richTextBox.Text.ToString() or using a string doesn't work because internally it checks to see if the strings are different before going any further.
NickAldwin
I don't know. I just know it works for me.
Cheeso
+5  A: 

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.
csharptest.net
...wow. That is awesome! Thank you. I'll test this as soon as I can. Have you released this code under a license, or can we just freely incorporate it into our code?
NickAldwin
Anything on stackoverflow is licensed by the creative commons license found here: http://creativecommons.org/licenses/by-sa/2.5/legalcode
csharptest.net
BTW, I accept the Up vote and accepted answer as as payment in full :)
csharptest.net
So if I interpret the license correctly, I cannot use this code in a commercial application?
NickAldwin
You can also check the meta site for a better answer, or post a question if you don't find one: http://meta.stackoverflow.com/
csharptest.net
This seems to work well, except for one problem: it seems to disable the ability to use the code richTextBox.SelectionFont = new Font(richTextBox.SelectionFont, FontStyle.Underline);to underline the selected text. Was this an intended feature? Is there a way around it?
NickAldwin
I also tried using the RichTextStyle class to underline...it also failed.
NickAldwin
I'm going to mark this as the answer, as it definitely works well. However, it looks like I won't be able to use it because underlining is not working. (Bold works fine...?)
NickAldwin
Ah, I figured it out. The line "fmt.bUnderlineType = 0;" should read "fmt.bUnderlineType = 1;". This will tell it to use normal underlining, while not actually underlining anything. Setting it to zero said to not do anything even when I told it to underline. Well, now that that's fixed, I'm happy to say this code works perfectly. Thank you SO MUCH!
NickAldwin
Thanks for letting me know about the underline thing. Apparently I never tried that, DOH!
csharptest.net
FYI: This is not resetting "paragraph" settings -- bullets/numbering, left/right/indent offsets, before/after spacing and single/double/etc. line spacing.
wqw
A: 

RichTextBox rtbTemp = new RichTextBox(); rtbTemp.Text = rtb.Text; rtb.Rtf = rtbTemp.Rtf;

hope it works

Itay