简体   繁体   English

在RichTextBox中重置RTF?

[英]Reset RTF in RichTextBox?

I'm trying to "reset" the formatting in my RichTextBox (WinForms, not WPF). 我正在尝试“重置”我的RichTextBox格式(WinForms,而不是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. 现在无论我将richTextBox.Text设置richTextBox.Text ,它都会保留一些rtf格式。

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. 编辑2:要清楚,我希望在保留文本的同时删除所有格式。 It looks like the code in the first edit will ship, unless anyone else has a more efficient/better coding way. 看起来第一次编辑中的代码将会发布,除非其他人有更高效/更好的编码方式。

Edit 3: 编辑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. 看起来应该只是一个richTextBox.ResetFormatting()方法,或者某种方式来访问相同的功能,因为Clear()方法清楚(没有双关语)除了简单地清除所有文本之外还会进行某种格式化重置。

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)? 是否有一种方法(如果是这样,是什么)重置RichTextBox中文本的格式而不清除上面示例中的文本(因为这会产生不希望的闪烁)?

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. .Net中的RichTextBox api是非常有限的,可以做任何你几乎要进入Win32库的东西。 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.

关于什么

richTextBox.Text = richTextBox.Text.ToString();

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. 对于不知不觉,它看起来很荒谬。

Just using: 只是使用:

richTextBox1.Clear();

... Should do the trick. ......应该做的伎俩。 Works for me. 适合我。

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. 它直接设置RichTextBox的RTF,因此应该比通常的方式设置样式快得多。 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. 它接受一个字符串(主文本),并且可选地还采用Color数组,字体大小数组(int)和font-weight数组(bool),每个数组代表每个字符的每个颜色,大小或字体权重。字符串。

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();

}

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: 在我的情况下,我需要清除格式并留下一个空的RichTextBox ,因此我做了这个函数:

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(); 或者只是删除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. 当文本不清除时,记得在格式化数据后存储先前的位置/选择和刷新状态。

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: 我发现的另一种方式(以及我已经切换到使用的方式,因为它不闪存)是在应用任何格式之前获取初始rtf字符串:

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. 好吧,至少它比问题中详述的方法好一点。

"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. 您应该能够实现SuspendLayout()和ResumeLayout()方法。

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. 在操作数据时,SuspendLayout()和ResumeLayout()将停止控件的绘制。 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. 如果确实花了太长时间,控件将显示为黑色矩形,直到调用ResumeLayout()。

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

hope it works 希望它有效

works fine .. 工作正常 ..

var TempString = richTextBox1.Text;
richTextBox1.Rtf = string.Empty;
richTextBox1.Text = TempString ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM