Richtextbox绘制RTF行

20

我想在RichTextBox中添加一条水平线作为我的文本分隔符。

我找到了一些实现线条的RTF代码示例,并尝试以这种方式使用它们:

rtbResFile.Rtf = @"{\rtf1{\pard some text.\par}{\pard \brdrb \brdrs \brdrw10 \brsp20 \par}{\pard \par}{\pard some other text.\par}}";

这种方式实现了创建一个带边框的空白段落,使其看起来像一条线。然而它并没有显示任何东西,只是一个空白段落。 即使我尝试按照包含行对象的方式进行实现,结果还是一样。

{\rtf1
{\pard some text.\par}
{\pard {\*\do\dobxcolumn\dobypara\dodhgt
        \dpline\dpxsize9200\dplinesolid\dplinew30}\par}
{\pard some other text.\par}
}

它仍然没有显示任何内容。RichTextBox支持吗?或者有其他方法可以在rtf字符串中包含水平线吗?

2个回答

17

有几种不同的方法可以在RTF中创建水平线。根据使用的控件或程序,您的效果可能会有所不同。控件和程序中的RTF实现往往会简单地忽略它们无法处理的标记。请注意,下面的代码示例是片段,不是完整的RTF文档。它们需要嵌入到有效的RTF文档中才能正常工作。

通过绘制多边形:

{\pard{\*\do
\dobxcolumn \dobypara \dodhgt7200
\dpline \dpptx0 \dppty0 \dpptx7200
\dppty0 \dpx0 \dpy0 \dpxsize7200
\dpysize0 \dplinew15
\dplinecor0 \dplinecog0 \dplinecob0 }\par}
通过插入一个带边框的空段落,然后再插入另一个没有边框的空段落:
{\pard \brdrb \brdrs \brdrw10 \brsp20 \par}
{\pard\par}

你可以通过设置段落的缩进来改变线条的大小和位置:

{\pard \li2268 \ri567
\brdrb \brdrs \brdrw10 \brsp20 \par}
{\pard\par}

我强烈推荐O'Reilly的RTF口袋指南,这本书是我获取以下信息的来源。

进一步地实验产生了下面的代码,可以在WordPad和RichTextBox控件中使用。

{\pict\wmetafile8\picw26\pich26\picwgoal20000\pichgoal15 
0100090000035000000000002700000000000400000003010800050000000b0200000000050000
000c0202000200030000001e000400000007010400040000000701040027000000410b2000cc00
010001000000000001000100000000002800000001000000010000000100010000000000000000
000000000000000000000000000000000000000000ffffff00000000ff040000002701ffff0300
00000000
}
基本上,它涉及插入一个黑点的1x1像素图像,并通过调整高度和宽度目标来根据需要拉伸它。目标测量单位为twips。Twip被定义为英寸的1/1440。这是一个可怕的技巧,但它起作用。 这里有一个示例,将最后的代码片段放入完整的有效RTF文档中,在WordPad和Windows Forms的RichTextBox控件上正确显示:
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}
{\*\generator Riched20 10.0.19041}\viewkind4\uc1 
\pard\sa200\sl276\slmult1\f0\fs22\lang9 Above\par
{\pict\wmetafile8\picw26\pich26\picwgoal20000\pichgoal15 
0100090000035000000000002700000000000400000003010800050000000b0200000000050000
000c0202000200030000001e000400000007010400040000000701040027000000410b2000cc00
010001000000000001000100000000002800000001000000010000000100010000000000000000
000000000000000000000000000000000000000000ffffff00000000ff040000002701ffff0300
00000000
}
\par
Below\par
}

你尝试在 Windows.Forms 的 RichTextBox 中实现过这个吗?我的问题是关于在 RichTextBox 中显示 rtf 行。我在我的问题中描述了与你相同的方法,但它们不起作用。如果你的方法有效,请提供一个适用于 RichTextBox 的 RTF 字符串。 - zooz
@JamieSee,这些解决方案在我的OS X TextEdit.App中无法呈现出线条,我原以为它是一个功能齐全的RTF编辑器。你们用的是哪个编辑器?有没有想法为什么我不能在我的编辑器中使用这些命令来生成一条线? - TeXnewbie
1
@TeXnewbie 这些示例是作为已有的 RTF 文档的一部分,因此需要一些额外的 RTF 包围它们,以避免显示为纯文本。此外,并非每个 RTF 编辑器都实现了所有功能,它们往往会忽略不实现的 RTF 代码,即这些示例在 Microsoft Word 中可以正常工作,但在 WordPad 中不能。 - JamieSee
2
很遗憾,我的经验是如果在WordPad中无法工作,则在RichTextBox中也无法工作。我曾经能够在WordPad或RichTextBox中创建干净的水平线的唯一方法是创建一个点的位图,然后使用适当的标记将其插入RTF以进行拉伸。请参见更新的答案。 - JamieSee
1
最后一个代码示例(带有长十六进制字符串的那个)适用于 RichtextBox Rtf。 - Patrick from NDepend team
显示剩余3条评论

5
这个函数创建了一个水平条,它只是一张图片。为了创建这张图片,我从Visio中拷贝了一条水平线到RTF文本框中,并查看了底层的RTF。因此,可以用这种方式插入任何图像。
下面的代码通过将光标移动到文本的末尾,然后设置"选定的"RTF为上述的条形图像来工作。然后取消选择该文本。
这段代码将该条设置为居中,但是通过将centreText设置为空字符串(或者直接删除代码),可以保持左对齐。
    /// <summary>
    /// Appends a horizontal bar at the end of the specified Rich Text Box
    /// </summary>
    /// <param name="rtb">Rich Text Box to which horizontal bar is to be added</param>
    private void AppendHorizontalBar(RichTextBox rtb)
    {
        // Position cursor at end of text
        rtb.Select(rtb.TextLength, 0);
        int selStart = rtb.TextLength;
        int selEnd = rtb.TextLength;

        // Textbox may transform chars, so (end-start) != text.Length
        rtb.Select(selStart, selEnd - selStart);

        // This is the RTF section to add.
        string horizontalBarRtf = @"{\pict\wmetafile8\picw12777\pich117\picwgoal7245\pichgoal60 0100090000035b00000004000800000000000400000003010800050000000b0200000000050000000c022100280e030000001e0008000000fa0200000300000000008000040000002d01000007000000fc020100000000000000040000002d010100080000002503020011001100170e110008000000fa0200000000000000000000040000002d01020007000000fc020000ffffff000000040000002d01030004000000f0010000040000002701ffff030000000000}";
        string centreText = "\\pard\\qc"; // set this to empty string to keep existing text alignment

        // Wrap to-add RTF section in RTF tag
        rtb.SelectedRtf = String.Format("{{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033\\uc1 {0} {1} \\line}}", centreText, horizontalBarRtf);

        // Leave no text selected
        rtb.SelectionLength = 0;
    }

这个工作正常..但它在richtextbox的中心添加了一行,而不是整个长度。 - Deepak Raj
@DeepakRaj - 请查看 centreText 声明处的注释。只需将其设置为空字符串即可保持现有文本对齐方式。另外,关于图片,您可以用任何图片替换上面的图片;为此,请将图像粘贴到“富文本”框中,然后查看 RTF 代码以确定图像的序列化版本,并在 horizontalBarRtf 的声明中替换该部分。 - CJBS
这一行是打错了吗?rtb.Select(txtActivityLog.TextLength, 0); - Walter Stabosz
@WalterStabosz 不是,它使用“Select”方法将光标定位在所有文本的末尾,选择0个字符。 - CJBS
@CJBS 我应该更清楚一些,txtActivityLog 是什么?它在你的代码中没有出现过。 - Walter Stabosz
1
@WalterStabosz 啊 - 我现在看到问题了。我创建了一个函数(用于StackOverflow),基于我在其他地方编写的代码,但没有替换所有变量。我现在已经纠正了它。感谢您指出这一点。 - CJBS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接