【问题标题】:How to load headers and footers present in .rtf file using c#?如何使用 C# 加载 .rtf 文件中的页眉和页脚?
【发布时间】:2018-07-05 17:39:48
【问题描述】:

我使用 richtextbox.loadfile(filepath,RichTextBoxStreamType.RichText); 将 .rtf 文件加载到我的文本编辑器中; 但它没有加载 .rtf 文件中存在的页眉和页脚,而且我无法静态创建页眉和页脚,因为每个其他 .rtf 文件的页眉中的数据都在变化,所以,我如何加载带有页眉和的 .rtf 文件页脚

【问题讨论】:

  • 是只显示还是修改保存? Specs
  • 只显示
  • 需要注意的是,文档中的每个部分都可以有自己的页眉和页脚。通过修改 rtf 代码,应该可以将页眉/页脚数据作为纯文本插入;不同的目的地可能是一个问题。页眉或页脚可以显示在所有页面或所有左/右页面等上。要使其显示正确,需要扫描文本以查找分页符,也可能需要扫描溢出页面。相当的命令。也许页眉和页脚的两个单独的 RTB 比弄乱 rtf 本身更简单。您将解析出标题并将其文本转储到 RTB 中。..
  • 我想再深入一点 a) 制定一个通用的解决方案并不容易 b) RTB 没有页面的概念,所以它不能处理页眉/页脚,它总是依赖在分页符上..
  • 是的,所以我安装了 devExpress 试用版。通过使用富文本控件,它现在正在加载包含标题的文件。但是还是没搞懂怎么在richTextBox中加载

标签: c# richtextbox rtf


【解决方案1】:
  • 坏消息是这是不可能的。

RichTextBox 没有页面的概念;但页眉和页脚依赖于页面

查看rtff specs,我们发现:他们可以在..

  • 每一页
  • 左右每一页
  • 或仅在第一页。

但是没有页面,显示这八种类型中的任何一种都没有意义。

  • 好消息是,去掉页眉和页脚并将它们分别放在单独的 rtb 中并不难。

让我们先看看Rtf;在这里,我们看到 rtb 已经去掉了它实际上可以显示的所有不需要的东西。所以页眉和页脚的 rtf 甚至不再存在了。

我们直接从文件中加载原始数据:

string rawRtf = File.ReadAllText(rtfPath);

接下来我们解析卷曲。比预期的要简单得多;我使用TreeView 来展示它们,但任何树节点结构都可以......:

treeView1.Nodes.Clear();
TreeNode cn = new TreeNode("rtf tree"); // a root node
cn = cn.Nodes.Add("");                  // first node
for (int i = 1; i < rawRtf.Length; i++)
{
    char p = rawRtf.Text[i - 1];
    char c = rawRtf.Text[i];

    // always watch for escaped curlies (but ignoring escaped blackslashes)
    // either closing or opening else real character:
    if (c=='}' && p != '\\') cn = cn.Parent;
    else if (c== '{' && p != '\\') cn = cn.Nodes.Add("");
    else cn.Text += c;
}
 treeView1.Nodes.Add(cn);

让我们看看结果:

加载的文档有一个带有真实文本的页眉和页脚;两者都有一组嵌入的卷曲。还有只有换行符的页眉和页脚;我们将忽略这些。

现在我们要从树中挑选所有结果。我们重新组装所有页眉/页脚节点,恢复卷曲。为此,我们使用一个函数递归地收集它们。

我们在节点文本的开头寻找这些control words

List<string> hdrftrWords = new List<string>(){
                @"\header ", @"\headerl", @"\headerr", @"\headerf",
                @"\footer ", @"\footerl", @"\footerr", @"\footerf"  };

收集它们很简单:

List<Tuple<string, TreeNode>>  hdrftrRtf = new List<Tuple<string, TreeNode>> ();

foreach (var hf in hdrftrWords)
{
    TreeNode node = treeView1.Nodes[0];
    // there may be more, but we'll only use the 1st..
    List<TreeNode> h1 = new List<TreeNode>();
    h1 = FindNodesByString(node, hf, h1);
    if (h1.Count > 0) hdrftrRtf.Add(new Tuple<string, TreeNode>(hf, h1[0]));
}

这里我们使用了一个小的递归函数来查找以字符串开头的节点:

List<TreeNode> FindNodesByString(TreeNode tn , string text, List<TreeNode> hits)
{
    if (tn.Text.StartsWith(text)) hits.Add(tn);
    foreach (TreeNode n in tn.Nodes) FindNodesByString(n, text, hits);
    return hits;
}

这确实是我们去除页眉和页脚所需的全部内容。

结果列表包含Item1 中的rtf 控制字和Item2 中的节点。

RichTextBoxes 中显示它们是最棘手的部分..:

foreach (var rtf in hdrftrRtf)
{
    var rtb = new RichTextBox();
    rtb.SelectedText = "";
    int i = rtb.Rtf.Length - 9;
    string r = "";
    r = JoinNodeTexts(rtf.Item2, "{", "}", ref r);
    r = r.Replace(rtf.Item1, "");
    rtb.Rtf = rtb.Rtf.Insert(i, r);
    rtb.Width = flowLayoutPanel1.ClientSize.Width - 10;
    if (rtb.Text.Trim().Length > 0) flowLayoutPanel1.Controls.Add(rtb);
}

这是一个加入所有节点文本的函数..:

string JoinNodeTexts(TreeNode tn, string prefix, string postfix, ref string joined)
{
    joined += prefix + tn.Text + postfix;
    foreach (TreeNode n in tn.Nodes) JoinNodeTexts(n, prefix, postfix, ref joined);
    return joined;
}

我们删除了控制字,因为我们不想让 rtb 认为它毕竟必须处理页眉或页脚。我也跳过空的页眉/页脚条目。 (\par被剪掉了..)

创建一个 rtb 控件后,我们通过添加一个空字符串来欺骗它工作;然后我们在末尾插入原始页眉和页脚减去一个跳过正常结尾的幻数,即跳过换行符,结束卷曲,然后是一些..

结果被添加到FlowLayoutPanel 进行测试。随意简单地复制 Text 并将其粘贴到实际 RTB 的开头或结尾。

由于我用一个基本上是空的 rtb 作弊,我们丢失了树顶部的原始字体和颜色表。如果页眉/页脚也应该显示这些,则还必须从树中解析出这些表..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多