winforms 快速彩色文本框:如何添加大文本-类似于StringBuilder,但使用样式-并且不构建撤消历史记录

hzbexzde  于 2023-03-09  发布在  其他
关注(0)|答案(1)|浏览(98)

FastColoredTextBox(FCTB)* 确实 * 提供了类似于StringBuilder的方法,例如
public virtual void AppendText(字符串文本,样式样式)
和类似的方法。但是,它将这些方法中的每一个都视为用户输入:每个动作被添加到撤消历史。
我是通过编程来构建文本的,它是数据字段和文本,沿着所有的格式和样式,而且它会变大。最后我会丢弃撤消历史(或者将控件设置为只读)。这会浪费大量的内存和计算时间。控件需要几秒钟才能使用。
那么,有没有办法在把我的文本传递给FCTB之前构建它呢?

ghhkc1vu

ghhkc1vu1#

创建TextSource派生类:

public class TextBuilder : TextSource
{
    public Line CurrentLine { get; private set; }

    public TextBuilder(FastColoredTextBox t) : base(t)
    {
        NewLine();
    }

    public void Append(string text, StyleIndex style = StyleIndex.None)
    {
        for (int i = 0; i < text.Length; i++)
        {
            char c = text[i];
            if (c == '\r' && i < text.Length - 1 && text[i + 1] == '\n') continue;
            if (c == '\r' || c == '\n') { NewLine(); continue; }
            CurrentLine.Add(new Char(c, style));
        }
    }

    public void AppendLine(string text, StyleIndex style = StyleIndex.None)
    {
        Append(text, style);
        NewLine();
    }

    public void AppendLine() => NewLine();

    void NewLine()
    {
        CurrentLine = CreateLine();
        lines.Add(CurrentLine);
    }

    public override void Initialized()
    {
        // Solution similar to CustomTextSourceSample.cs (not more than necessary)
        // (an alternative is OnTextChanged(0, lines.Count - 1) which invokes TextChanged but there may be side effects)

        if (CurrentTB.WordWrap)
        {
            OnRecalcWordWrap(new TextChangedEventArgs(0, lines.Count - 1));
        }

        CurrentTB.Invalidate();
    }
}

将此虚方法添加到TextSource类:

/// <summary>
/// Called when CurrentTB has initialized this text source.
/// </summary>
public virtual void Initialized()
{
}

在FCTB类中,将此行添加到InitTextSource方法中:

while (LineInfos.Count < ts.Count)
    LineInfos.Add(new LineInfo(-1));

ts.Initialized(); // Add this line

为方便起见,请更改Char构造函数:

public Char(char c, StyleIndex s = StyleIndex.None)
{
    this.c = c;
    style = s;
}

使用如下:

var b = new TextBuilder(fctb);
b.Styles[0] = new MarkerStyle(Brushes.LightBlue);
b.Append("text", StyleIndex.Style0);
fctb.TextSource = b;

如果你不想重新编译FCTB,你可以只添加TextBuilder类,并在赋值TextSource之后调用b.OnTextChanged(0, b.Count - 1),但是你可能还是要调整FCTB,并在文本构建器中添加内容。

相关问题