Как загрузить верхние и нижние колонтитулы, присутствующие в файле .rtf, используя c #? - PullRequest
0 голосов
/ 03 июля 2018

Я загружаю файл .rtf в свой текстовый редактор, используя richtextbox.loadfile (filepath, RichTextBoxStreamType.RichText); но он не загружает верхние и нижние колонтитулы, присутствующие в файле .rtf, а также я не могу создать заголовок и нижний колонтитул статически, потому что данные в верхнем колонтитуле меняются для всех остальных файлов .rtf, поэтому, как я могу загрузить файл .rtf с заголовками и нижние колонтитулы

1 Ответ

0 голосов
/ 04 июля 2018
  • Плохая новость в том, что это на самом деле невозможно.

RichTextBox не имеет понятия страниц; но верхние и нижние колонтитулы опираются на страницы .

Глядя на спецификации rtff , мы находим: они могут быть включены.

  • каждая страница
  • каждая левая или правая страница
  • или только на первой странице.

Но без страниц отображение любого из этих восьми типов не имеет смысла.

  • Хорошая новость заключается в том, что не так уж сложно вырезать верхние и нижние колонтитулы и помещать каждый в отдельный rtb.

Давайте начнем с рассмотрения Rtf; здесь мы видим, что rtb уже удалил все вещи, в которых он не нуждается для того, что он действительно может отобразить. Таким образом, значение верхних и нижних колонтитулов больше не существует.

Вместо этого мы загружаем необработанные данные прямо из файла:

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);

Давайте посмотрим на результат:

enter image description here

Загруженный документ имеет верхний и нижний колонтитулы с реальным текстом; оба имеют встроенный набор фигур. Есть также верхние и нижние колонтитулы с только переводом строки; мы их проигнорируем.

Теперь мы хотим выбрать все наши результаты из дерева. Мы собираем все узлы верхнего / нижнего колонтитула, восстанавливая кривые. Для этого мы используем функцию рекурсивного сбора их всех.

Мы ищем эти контрольные слова в начале текстов узлов:

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;
}

Это действительно все, что нам нужно для удаления верхних и нижних колонтитулов.

Результирующий список содержит управляющие слова rtf в Item1 и узлы в 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 ..

enter image description here

Так как я обманул практически пустой rtb, нам не хватает исходных таблиц шрифтов и цветов в верхней части дерева. Если верхние и нижние колонтитулы должны отображать их, нужно будет также проанализировать эти таблицы из дерева.

...