Сбросить RTF в RichTextBox?

Я пытаюсь "сбросить" форматирование в моем RichTextBox (WinForms, а не WPF). Ранее я использовал

richTextBox.Text = richTextBox.Text;

однако, это, кажется, внезапно подвело меня. Теперь независимо от того, что я установил richTextBox.Text to, он сохраняет некоторые из форматирования rtf.

Я пробовал

richTextBox.Rtf = richTextBox.Text;

однако, это жалуется на неправильный формат. Должен быть лучший способ сделать это. (Конечно, выбрав всю вещь, затем сбросив задний цвет, передний цвет, и шрифт работает, но это приводит к мерцанию, поскольку вся вещь выбрана, а затем отменена, плюс она медленнее и требует намного больше кода. Кто-нибудь знает?

изменить: Я получил это на работу:

string tempTxt = richTextBox.Text;
richTextBox.Clear();
richTextBox.Text = tempTxt;

но там должен быть лучший способ?

редактирование 2: Чтобы быть ясным, я хочу удалить все форматирование, сохраняя текст. Похоже, что код в первом редактировании будет отправлен, если у кого-то еще нет более эффективного/лучшего кодирования путь.

Edit 3:

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

не работает, потому что он по-прежнему не очищает все форматирование. Причина, по которой мне не нравится метод в первом редактировании выше, это делает текстовое поле "flash", когда оно очищает его, а затем повторно вводит текст. Кажется, что должен быть просто richTextBox.Метод ResetFormatting () или какой-то способ доступа к той же функциональности, что и метод Clear () ясно (без каламбура), выполняет какой-то сброс форматирования в дополнение к просто очистка всего текста.

подведем итоги:

есть ли способ (и если да, то какой) сбросить форматирование текста в RichTextBox без очистки текста, как в примере выше (потому что это вызывает нежелательное мигание)?

10 ответов


к сожалению, я сделал все возможное, чтобы уменьшить это только до требуемого кода. Он все еще большой, но он будет работать. Api RichTextBox в .Net очень ограничен, чтобы сделать все, что вам почти нужно, чтобы погрузиться в библиотеку Win32. Я построил целую библиотеку вокруг этой вещи, чтобы я мог переключать полужирный шрифт и определять, действительно ли полужирный установлен в выборе.

использование:

RichTextBox te = ...;
te.ClearAllFormatting(new Font("Microsoft Sans Serif", 8.25f));

тонн код:

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
}

больше спросите вы?

Я использую большую часть этого через небольшой вспомогательный класс, который обертывает это для всех стилей и изменения шрифта. Таким образом, вы можете изменить размер шрифта и не изменить имя шрифта, и т. д.

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

я использовал

var t = richTextBox1.Text;
richTextBox1.Text = t; 

EDIT::

обязательно вставьте комментарий о том, почему вы делаете то, что делаете. Для неосознанного это выглядит нелепо.


просто используешь:

richTextBox1.Clear();

... Должно сработать. Работать на меня.


Я вижу, что есть много ответов, но я думаю, что есть более простой и удобный подход, как расширение, чтобы очистить все форматирование:

в моем случае мне нужно было очистить форматирование и оставить пустой 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();
}

тогда простое решение:

string backUp = this.richTextBox1.Text;
ClearRichTextBox();
this.richTextBox1.Text = backUp;

или просто удалить this.richTextBox1.Clear(); строка в функции clear. (это, вероятно, также будет работать, но я не даю никаких гарантий, так как я тестировал это только на просто при потере связи потеряете. Поэтому может быть, что любая другая строка должна быть добавлена для удаления другого форматирования.)

когда текст не должен быть очищен, не забудьте сохранить предыдущую позицию / выбор и обновить состояние после деформации данных.


другой способ, который я нашел (и тот, который я переключился на использование, поскольку он не мигает), - это захватить начальную строку rtf перед применением любого форматирования:

string initialRtf = richTextBox.Rtf;

тогда, когда я хочу сбросить форматирование, я могу просто сделать:

richTextBox.Rtf = initialRtf;

однако это не совсем идеально, потому что для этого требуется, чтобы текст оставался неизменным и таким. Ну, по крайней мере, это немного лучше, чем метод, описанный в вопросе.


" причина, по которой мне не нравится метод в первом редактировании выше, это делает текстовое поле "flash", когда оно очищает его, а затем повторно вводит текст."

вы должны иметь возможность реализовать методы SuspendLayout() и ResumeLayout ().

string tempTxt = richTextBox.Text;
rtbIncludes.SuspendLayout();
richTextBox.Clear();
richTextBox.Text = tempTxt;
rtbIncludes.ResumeLayout();

SuspendLayout () и ResumeLayout () остановят рисование элемента управления во время управления данными. Если операция не займет много времени, вы сможете очистить текст и назначить неформатированный текст назад, не появляясь на экране.

Если это займет слишком много времени, элемент управления будет отображаться как черный прямоугольник до ResumeLayout() вызывается.


на некоторое время, я использовал этот код в своей программе. Он устанавливает RTF RichTextBox напрямую, поэтому должен быть намного быстрее, чем установка стилей обычным способом. Он принимает строку (основной текст) и, возможно, также принимает цветовой массив, массив размера шрифта (int) и массив веса шрифта (bool), каждый из которых представляет каждый цвет, размер или вес шрифта для каждого символа в строке.

кроме того, вы можете просто сохранить размер по умолчанию, вес, курсивные номера, заданные заголовок.

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

}

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

надеюсь, что он работает


работает нормально ..

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