如何将长文本拆分成多个/页面以适合RichTextBox?

时间:2018-04-20 13:08:16

标签: c# winforms richtextbox

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

问题是WinForm不支持多个页面。

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

目前我正在使用RichTextBox检查字符串是否适合富文本框,例如:

RichTextBox

它不能很好地工作,因为我认为上面的功能不准确。

我想知道是否有一种简单的方法可以做到这一点?感谢。

2 个答案:

答案 0 :(得分:1)

我提出的解决问题的方法是将源文档的文本拆分为多个子字符串(Pages),例如每个子字符串都可以放在RichTextBox客户区域中,而不是产卵/需要滚动条。

因此,第一项任务是计算必须拆分给定文件的Chuncks / Pages的数量。

TextRenderer Class方法是常用的工具 在执行计算时,必须指示类包装文本(如RichTextBox控件所示),排除任何填充并将字符串放入TextBox类型控件编辑区域。

TextFormatFlags标志将是:

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

下一个任务是计算RichTextBox控件的客户区域中适合的字母/符号数,以便不需要滚动条。

Winforms RichTextBox控件不提供任何特定工具,但非特定工具足以执行此计算。

  

作为注释,Lines[] property(源自TextBoxBase)   仅报告原始文本行拆分(用作行   (),而不是内部自动换行生成的行。

但是,TextBoxBase GetFirstCharIndexFromLine()GetLineFromCharIndex()可以组合使用以达到相同的效果:
知道ClientArea中可以容纳多少行,下一行中的第一个字符将比ClientArea中最后一个可见行的最后一个字符多一个字符(空格未被包装)。
然后,只要有足够的行来填充ClientArea,就重复此过程。最后一个 Page 将包含[Total Lines] / [Lines per Page]

的提醒

该程序结果的直观表示:

enter image description here

示例代码,用于执行计算大小和分割源文档文本的基本任务。用于创建示例图像的完整源代码:(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();

    //Number of shown lines
    int FirstCharOfLastShownLine = richTextBox1.GetCharIndexFromPosition(new Point(0, richTextBox1.ClientSize.Height));
    int ShownLines = richTextBox1.GetLineFromCharIndex(FirstCharOfLastShownLine);
    int TotalLines = richTextBox1.GetLineFromCharIndex(richTextBox1.Text.Length - 1);

    for (int p = 0; p < NumberOfPages; p++)
    {
        int FirstLineOfPage = (p * ShownLines);
        int FirstCharOfPage = richTextBox1.GetFirstCharIndexFromLine(FirstLineOfPage);

        int FirstLineOfNextPage = (p + 1) * ShownLines;
        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();

答案 1 :(得分:0)

我不确定,我没有测试代码,但我希望它可以帮助你,至少会给你一个想法。

将字体大小pt转换为px

Float points = 72; // each point in pixels 
Float fontSize = 12; // font size
Float dpi = 96; // find screen dpi (96 is very common I know)
Float px = fontsize * dpi / points; // each lines need px (exp: 16)

查找文本中的行数(exp:200行)

var lineCount = File.ReadAllLines(@"C:\file.txt").Length;
var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
    while (reader.ReadLine() != null)
    {
        lineCount++;
    }
}

我们在第1步和第2步找到每行的行数和需要的像素数,因此我们可以找到用于在相关行中标记文本的分隔符位置

Float totalTextPixels = lineCount * px;
Float textFieldHeight = 200; // for example
Float eachSplitLine = totalTextPixels / textFieldHeight;

再次循环线

var lineCount = File.ReadAllLines(@"C:\file.txt").Length;
var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
    while (reader.ReadLine() != null)
    { 
        lineCount++;
        if(lineCount == eachSplitLine){
            // Put a deliminiter here (I don't know how)
            // for example | (pipe)
            lineCount = 0;
        }
    }
}

并使用|

拆分文字

我知道它不健全且教授。解决方案,这只是一个想法......

祝你好日子。