【问题标题】:RTF Color Table looping through all colors循环遍历所有颜色的 RTF 颜色表
【发布时间】:2017-08-23 10:07:58
【问题描述】:

我有一个 RichTextBox。我在这个 RichTextBox 中添加了 RTF 格式(主要是颜色表)。当我第一次向它附加文本时,它会循环遍历颜色表的所有颜色。

*首先应用 color0,然后是 color1,然后是 color2,等等,直到颜色表中的所有颜色都已应用,或者如果正在输出的文本已经具有其中一种颜色 - 在这种情况下,它会停止此“循环”并按预期继续。例如,请参见屏幕截图。

代码如下:

    private void populateColorCodeDictionary() {
        startRTFString = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fcharset0;}}" +
        @"{\colortbl 
            ;

            \red0\green0\blue0;
            \red170\green0\blue0;
            \red0\green170\blue0;
            \red128\green128\blue0;
            \red0\green0\blue128;
            \red128\green0\blue128;
            \red0\green128\blue128;
            \red127\green127\blue127;

            \red85\green85\blue85;
            \red255\green0\blue0;
            \red0\green255\blue0;
            \red255\green255\blue0;
            \red0\green0\blue255;
            \red255\green0\blue255;
            \red0\green255\blue255;
            \red255\green255\blue255;
        }";

        colorCodeDictionary.Add("\x1b[0;30m", @"\cf1");
        colorCodeDictionary.Add("\x1b[0;31m", @"\cf2");
        colorCodeDictionary.Add("\x1b[0;32m", @"\cf3");
        colorCodeDictionary.Add("\x1b[0;33m", @"\cf4");
        colorCodeDictionary.Add("\x1b[0;34m", @"\cf5");
        colorCodeDictionary.Add("\x1b[0;35m", @"\cf6");
        colorCodeDictionary.Add("\x1b[0;36m", @"\cf7");
        colorCodeDictionary.Add("\x1b[0;37m", @"\cf8");

        colorCodeDictionary.Add("\x1b[1;30m", @"\cf9");
        colorCodeDictionary.Add("\x1b[1;31m", @"\cf10");
        colorCodeDictionary.Add("\x1b[1;32m", @"\cf11");
        colorCodeDictionary.Add("\x1b[1;33m", @"\cf12");
        colorCodeDictionary.Add("\x1b[1;34m", @"\cf13");
        colorCodeDictionary.Add("\x1b[1;35m", @"\cf14");
        colorCodeDictionary.Add("\x1b[1;36m", @"\cf15");
        colorCodeDictionary.Add("\x1b[1;37m", @"\cf16");

        /*
        \x1b[0;30m  =   cf1     =   black
        \x1b[0;31m  =   cf2     =   red
        \x1b[0;32m  =   cf3     =   green
        \x1b[0;33m  =   cf4     =   brown
        \x1b[0;34m  =   cf5     =   blue
        \x1b[0;35m  =   cf6     =   purple
        \x1b[0;36m  =   cf7     =   cyan
        \x1b[0;37m  =   cf8     =   gray

        \x1b[1;30m  =   cf9     =   darkGray
        \x1b[1;31m  =   cf10    =   light Red
        \x1b[1;32m  =   cf11    =   light green
        \x1b[1;33m  =   cf12    =   yellow
        \x1b[1;34m  =   cf13    =   light blue
        \x1b[1;35m  =   cf14    =   indigo
        \x1b[1;36m  =   cf15    =   light cyan
        \x1b[1;37m  =   cf16    =   white
        */
    }

上述方法设置变量。最有趣的部分是 startRTFString 变量。

    private void updateOutputWindow(string text) {
        string newText = string.Empty;

        if (InvokeRequired) {
            Invoke(new MethodInvoker(delegate () {
                updateOutputWindow(text);
            }));
        }
        else {
            newText = startRTFString;
            newText += rtb_outputWindow.Rtf;
            newText += replaceAnsiColorCodes(text);

            rtb_outputWindow.Rtf = newText;
        }
    }

上述方法将文本输出到 RichTextBox。

    private string replaceAnsiColorCodes(string inData) {
        string returnString = inData;

        foreach (KeyValuePair<string, string> entry in colorCodeDictionary) {
            returnString = returnString.Replace(entry.Key, entry.Value);
        }

        returnString = returnString.Replace("\r", @"\line");               //Newline
        returnString = returnString.Replace("\x1b[0;1m", "");            //Bold

        returnString = returnString.Replace("\x1b[0m", @"\cf16 ");      //Reset

        return returnString;
    }

上述方法将 ANSI 代码转换为 RTF 颜色代码。 (以及换行符和粗体。到目前为止,我已选择将粗体设置为无。)

    for (int i = 0; i < 15; i++) {
        updateOutputWindow("\x1b[0mline" + i.ToString());
    }

以上只是我在应用程序启动后立即运行的一个小循环。它用于测试目的,可以在以下屏幕截图中看到:

以上是问题的截图。如您所见,前 15 行文本都有不同的颜色。它们都应该具有相同的默认颜色(在我的情况下为白色)。“循环”完成后,它会继续按预期工作;为文本应用正确的颜色。

需要注意的是,第一行(line0)上面的行是空的。颜色表以黑色开头,所以 line0 应该是黑色,而 line1 应该是深红色。不知道为什么它不遵守自己的规则。

这是我运行的另一个测试:

    for (int i = 0; i < 15; i++) {
        updateOutputWindow("\x1b[0;34mline" + i.ToString());  //This time I changed the color to be dark blue
    }

如您所见:“循环”一直发生,直到它遇到相同的颜色,并且一直使用该颜色。

我不知道为什么会发生这种情况或导致它的原因。我的猜测是我以某种方式搞砸了 RTF“脚本”。有谁知道解决方案? (我不希望任何颜色表循环发生。我希望它输出默认颜色,除非存在颜色代码 - 在这种情况下,我希望显示该颜色。)

编辑: 我将这段代码添加到方法 updateOutputWindow MessageBox.Show(newText); 中。下面是结果截图:

从上面的屏幕截图中可以看出,RichTextBox 已经存在某种“默认 RTF 代码”。 - 这个默认代码被添加到我的“自定义 RTF 代码”之上。不过,它似乎不会干扰颜色表。 (除非这是解决手头问题的原因,在这种情况下,它肯定会干扰,但以一种非常具体的一次性方式。)

编辑 #2:如果我继续一遍又一遍地运行此方法,则不会为每次额外的运行添加 RTF 代码。它被添加一次(在最顶部),然后不再添加。我认为这是一件好事,我相信这是由于 RichTextBoxes 原生处理 RTF 代码的方式造成的。

【问题讨论】:

  • 您可以在写字板中手动编写您希望在应用程序中显示的内容,然后在纯文本编辑器中打开文档。对于换行符,请使用 Shift+Enter 而不是 Enter。我刚刚这样做了,我没有看到任何 \x1b[0 代码。
  • 我可以。但我的应用程序是一个连接到服务器的客户端。服务器不是我的,所以我无法控制它发送给我的客户的内容。很遗憾,我必须处理 ANSI 代码。
  • 看看termsharp。也许您可以根据需要按原样使用它(如果您不使用xwt,请忽略xwt 文件夹)。
  • newText += rtb_outputWindow.Rtf; 这为有效的 Rtf 加上一个新表的前缀。您不应该将表格插入 Rtf 吗?

标签: c# colors rtf


【解决方案1】:

您正在将终端代码(或称为 ANSI 代码)转换为 RTF 格式。您提供给updateOutputWindow 的文本包含\x1b[0;34m,但在updateOutputWindow 中,该终端代码没有Replace 行。你有类似的东西,但不完全一样。结果,终端代码现在是 RTF 的一部分,所以谁知道会发生什么。必须处理所有终端代码(替换或删除)。

另外,我觉得下面的代码很奇怪:

newText = startRTFString;
newText += rtb_outputWindow.Rtf;
newText += replaceAnsiColorCodes(text);

rtb_outputWindow.Rtf = newText;

似乎rtb_outputWindow.Rtf 会随着每次函数调用而增长,每次都添加新的startRTFString。我建议使用以下代码代替上面的代码(myStuff 是一个属性,例如 startRTFString):

myStuff = myStuff + replaceAnsiColorCodes(text);
rtb_outputWindow.Rtf = startRTFString + myStuff;

【讨论】:

  • 所有的ANSI代码都是通过replaceAnsiColorCodes方法删除的,所以它们都不应该在RichTextBox中。确实,发送的数据越多,RichTextBox 的内容就越长。 (我有另一个函数,它稍后会在达到某个点时删除代码行 - 以降低内存使用量。)但是,这可能不是最佳实践。
  • @Phrosen 我不是在谈论在 RTF 末尾添加东西,而是在开头。 startRTFString 在 RTF 的开头重复出现。也许这就是问题所在。
  • 我运行了另一个测试并将结果(带屏幕截图)添加到原始帖子。正如您所说,“现有的 RTF 内容”被添加到“我的 RTF 内容”中。不知道这是否是问题所在,也不知道如何解决。
  • 解决方案是跟踪您的资料,而不是在.Rtf 属性中,而是在您自己的单独属性.MyStuff 中。你向MyStuff 添加新内容,然后将Rtf 设置为startRTFString + MyStuff
  • 我不太确定我完全理解你的意思。你能给我一个例子,然后我可以尝试测试一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
相关资源
最近更新 更多