如何将长文本拆分为多个片段/页面以适合 RichTextBox? [英] How to split a long text into multiple pieces/pages to fit into a RichTextBox?

查看:61
本文介绍了如何将长文本拆分为多个片段/页面以适合 RichTextBox?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在处理 WinForm 应用程序时,我想将长文本(只有字符,没有图像,没有特殊格式)分成多个部分(页面),以便将它们放入一个RichTextBox.

问题在于 RichTextBox 不支持多页.

我必须编写自己的算法(某种 DP 编程)来拆分文本.

目前我正在使用 TextRenderer.MeasureText() 来检查字符串是否适合富文本框,例如:

bool canfit(String str){大小 rbx_size = 新大小(rbx.Width, rbx.Height);大小 sz = TextRenderer.MeasureText(str, rbx.font, rbx_size, TextFormatFlags.WordBreak | TextFormatFlags.GlyOverhangPadding)返回 (sz.Height < rbx_size.Height);}

效果不是很好,因为我觉得上面的函数不准确.

我想知道是否有一种简单的方法来做到这一点?谢谢.

解决方案

建议的问题,按照我的解释,是将源文档的文本拆分为多个子字符串(页面),例如每个子字符串可以放入 RichTextBox 客户区,而无需生成/需要滚动条.

因此,第一个任务是计算必须将给定文档拆分成的 Chuncks/Pages 数.

执行计算大小和拆分源文档文本的基本任务的示例代码.用于创建示例图像的完整源代码:(PasteBin - RTB Reader)

string Document = "[SomeDocumentText]";列表<字符串>Pages = new List();TextFormatFlags flags = TextFormatFlags.Top |TextFormatFlags.Left |TextFormatFlags.WordBreak |TextFormatFlags.NoPadding |TextFormatFlags.TextBoxControl;大小 textSize = TextRenderer.MeasureText(Document,richTextBox1.Font,richTextBox1.ClientSize,flags);int numberOfPages = textSize.Height/richTextBox1.ClientSize.Height;如果(textSize.Height >richTextBox1.Height){richTextBox1.Text = 文档;richTextBox1.Update();int firstCharOfLastShownLine = richTextBox1.GetCharIndexFromPosition(new Point(0, richTextBox1.ClientSize.Height));int visibleLines = richTextBox1.GetLineFromCharIndex(firstCharOfLastShownLine);int totalLines = richTextBox1.GetLineFromCharIndex(richTextBox1.Text.Length - 1);for (int p = 0; p  totalLines) ?totalLines : firstLineOfNextPage;int lastCharOfPage = (firstLineOfNextPage < totalLines)?richTextBox1.GetFirstCharIndexFromLine(firstLineOfNextPage) - 1:richTextBox1.Text.Length;Pages.Add(richTextBox1.Text.Substring(firstCharOfPage, lastCharOfPage - firstCharOfPage));}}别的 {Pages.Add(文档);}richTextBox1.Text = Pages.First();

While working on a WinForm application, I would like to split a long text (only characters, no images, no special format) into multiple pieces (pages), in order to fit them into a RichTextBox.

The problem is that RichTextBox doesn't support multiple pages.

I have to write my own algorithm (some kind of DP programming) to split the text.

Currently I am using TextRenderer.MeasureText() to check whether a string can fit into the rich textbox, for example:

bool canfit(String str)
{
    Size rbx_size = new Size(rbx.Width, rbx.Height);
    Size sz = TextRenderer.MeasureText(str, rbx.font, rbx_size, TextFormatFlags.WordBreak | TextFormatFlags.GlyOverhangPadding)
    return (sz.Height < rbx_size.Height);
}

It doesn't work very well, because I think the function above is not accurate.

I am wondering if there is an easy way to do it? Thanks.

解决方案

The proposed problem, the way I've interpreted it, is to split the text of a source document in a number of substring (Pages), such as each substring can fit in a RichTextBox client area, without spawning/requiring the scrollbars.

Thus, the first task is to calculate the number of Chuncks/Pages into which a given Document has to be split.

The TextRenderer Class methods are the usual tools.
The class must be instructed, while performing the calculation, to wrap the text (as the RichTextBox control will), exclude any padding and fit the string in a TextBox type control edit area.

The main TextFormatFlags flags will then be:

TextFormatFlags.WordBreak | TextFormatFlags.NoPadding | TextFormatFlags.TextBoxControl;

The next task is to calculate how many letters/symbols will fit in the client area of a RichTextBox control, so that no scroll bars are needed.

The Winforms RichTextBox control doesn't offer any specific tool, but the non-specific ones are enough to perform this calculation.

As a note, the [Lines[] property][3] (derived from TextBoxBase) reports only the original text line splitting (intended as line feeds), not the lines generated by the internal word-wrapping.

However, the TextBoxBase GetFirstCharIndexFromLine() and GetLineFromCharIndex() can be used in combination to achieve the same result:
Knowing how many lines can fit in the ClientArea, the first character in the next line will be one character more than the last character of the last visible line in the ClientArea (spaces are not wrapped).
Then, repeat this procedure while there are enough lines to fill the ClientArea. The last Page will contain the reminder of [Total Lines] / [Lines per Page].

A visual representation of the results of this procedure:

Sample code that performs the basic task of calculating the size and splitting the text of a source document. The complete source code used to create sample image: (PasteBin - RTB Reader)

string Document = "[SomeDocumentText]";
List<string> Pages = new List<string>();
TextFormatFlags flags = TextFormatFlags.Top | TextFormatFlags.Left | TextFormatFlags.WordBreak | 
                        TextFormatFlags.NoPadding | TextFormatFlags.TextBoxControl;

Size textSize = TextRenderer.MeasureText(Document, richTextBox1.Font, richTextBox1.ClientSize, flags);
int numberOfPages = textSize.Height / richTextBox1.ClientSize.Height;

if (textSize.Height > richTextBox1.Height) {
    richTextBox1.Text = Document;
    richTextBox1.Update();

    int firstCharOfLastShownLine = richTextBox1.GetCharIndexFromPosition(new Point(0, richTextBox1.ClientSize.Height));
    int visibleLines = richTextBox1.GetLineFromCharIndex(firstCharOfLastShownLine);
    int totalLines = richTextBox1.GetLineFromCharIndex(richTextBox1.Text.Length - 1);

    for (int p = 0; p < numberOfPages; p++) {
        int firstLineOfPage = (p * visibleLines);
        int firstCharOfPage = richTextBox1.GetFirstCharIndexFromLine(firstLineOfPage);

        int firstLineOfNextPage = (p + 1) * visibleLines;
        firstLineOfNextPage = (firstLineOfNextPage > totalLines) ? totalLines : firstLineOfNextPage;
        int lastCharOfPage = (firstLineOfNextPage < totalLines)
                           ? richTextBox1.GetFirstCharIndexFromLine(firstLineOfNextPage) - 1
                           : richTextBox1.Text.Length;
        Pages.Add(richTextBox1.Text.Substring(firstCharOfPage, lastCharOfPage - firstCharOfPage));
    }
}
else {
    Pages.Add(Document);
}
richTextBox1.Text = Pages.First();

这篇关于如何将长文本拆分为多个片段/页面以适合 RichTextBox?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆