如何将长文本拆分为多个 pieces/pages 以适应 RichTextBox?
How to split a long text into multiple pieces/pages to fit into a RichTextBox?
在开发 WinForm
应用程序时,我想将一个长文本(只有字符,没有图像,没有特殊格式)拆分成多个部分(页面),以便将它们放入 RichTextBox
.
问题是RichTextBox
不支持多页。
我必须编写自己的算法(某种 DP 编程)来拆分文本。
目前我正在使用TextRenderer.MeasureText()
来检查一个字符串是否适合富文本框,例如:
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);
}
效果不是很好,因为我觉得上面的函数不准确。
我想知道是否有简单的方法来做到这一点?谢谢。
我不确定,我没有测试代码,但我希望它可以帮助你,至少会给你一个想法。
将字体大小 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;
}
}
}
并用 |
拆分您的文本
我知道它不稳健,教授。解决方案,这只是一个想法...
祝你生活愉快。
提出的问题,按照我的解释,是将源文档的文本拆分为多个子字符串(Pages),例如每个子字符串可以放入一个 RichTextBox
客户区, 没有 spawning/requiring 滚动条。
因此,第一个任务是计算给定文档必须拆分成的Chuncks/Pages个数。
TextRenderer Class 方法是常用的工具。
在执行计算时,必须指示 class 换行文本(如 RichTextBox 控件所做的那样),排除任何填充并使字符串适合 TextBox 类型控件的编辑区域。
主要 TextFormatFlags 标志将是:
TextFormatFlags.WordBreak | TextFormatFlags.NoPadding | TextFormatFlags.TextBoxControl;
下一个任务是计算有多少 letters/symbols 适合 RichTextBox 控件的工作区,这样就不需要滚动条了。
Winforms
RichTextBox
控件不提供任何特定工具,但非特定工具足以执行此计算。
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.
但是,TextBoxBase GetFirstCharIndexFromLine() and GetLineFromCharIndex() 可以组合使用以获得相同的结果:
知道 ClientArea 可以容纳多少行,下一行的第一个字符将比 ClientArea 中最后一个可见行的最后一个字符多一个字符(空格不换行)。
然后,在有足够的行填充 ClientArea 时重复此过程。最后页将包含[Total Lines] / [Lines per Page]
的提醒。
此过程结果的可视化表示:
执行计算大小和拆分源文档文本的基本任务的示例代码。用于创建示例图像的完整源代码:(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();
在开发 WinForm
应用程序时,我想将一个长文本(只有字符,没有图像,没有特殊格式)拆分成多个部分(页面),以便将它们放入 RichTextBox
.
问题是RichTextBox
不支持多页。
我必须编写自己的算法(某种 DP 编程)来拆分文本。
目前我正在使用TextRenderer.MeasureText()
来检查一个字符串是否适合富文本框,例如:
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);
}
效果不是很好,因为我觉得上面的函数不准确。
我想知道是否有简单的方法来做到这一点?谢谢。
我不确定,我没有测试代码,但我希望它可以帮助你,至少会给你一个想法。
将字体大小 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;
}
}
}
并用 |
拆分您的文本我知道它不稳健,教授。解决方案,这只是一个想法...
祝你生活愉快。
提出的问题,按照我的解释,是将源文档的文本拆分为多个子字符串(Pages),例如每个子字符串可以放入一个 RichTextBox
客户区, 没有 spawning/requiring 滚动条。
因此,第一个任务是计算给定文档必须拆分成的Chuncks/Pages个数。
TextRenderer Class 方法是常用的工具。
在执行计算时,必须指示 class 换行文本(如 RichTextBox 控件所做的那样),排除任何填充并使字符串适合 TextBox 类型控件的编辑区域。
主要 TextFormatFlags 标志将是:
TextFormatFlags.WordBreak | TextFormatFlags.NoPadding | TextFormatFlags.TextBoxControl;
下一个任务是计算有多少 letters/symbols 适合 RichTextBox 控件的工作区,这样就不需要滚动条了。
Winforms
RichTextBox
控件不提供任何特定工具,但非特定工具足以执行此计算。
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.
但是,TextBoxBase GetFirstCharIndexFromLine() and GetLineFromCharIndex() 可以组合使用以获得相同的结果:
知道 ClientArea 可以容纳多少行,下一行的第一个字符将比 ClientArea 中最后一个可见行的最后一个字符多一个字符(空格不换行)。
然后,在有足够的行填充 ClientArea 时重复此过程。最后页将包含[Total Lines] / [Lines per Page]
的提醒。
此过程结果的可视化表示:
执行计算大小和拆分源文档文本的基本任务的示例代码。用于创建示例图像的完整源代码:(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();