PageHeaders.cs
// 完毕:
using System;
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Drawing;

namespace DsPdfWeb.Demos.Basics
{
    // 演示生成左/居中/右对齐页眉和页脚的简单方法。
    public class PageHeaders
    {
        // 正在生成的文档:
        private GcPdfDocument _doc;

        // 绘制页眉或页脚的一部分的实用方法。
        // 参数:
        // - 文本:该部分的文本。
        // - tf:要使用的文本格式。
        // - pageIdx:页面索引。
        // - header:如果这是页眉,则为 true;如果是页脚,则为 false。
        // - horzAlign:水平对齐(左/中/右)。
        private void RenderHeader(string text, TextFormat tf, int pageIdx, bool header, TextAlignment horzAlign)
        {
            var page = _doc.Pages[pageIdx];
            var tl = new TextLayout(page.Graphics.Resolution);
            tl.MaxWidth = page.Size.Width;
            tl.MaxHeight = page.Size.Height;
            // 1" 边距,根据需要调整:
            tl.MarginLeft = tl.MarginRight = tl.Resolution;
            // 顶部/底部标题上方 1/3" 间距,根据需要调整:
            tl.MarginTop = tl.MarginBottom = tl.Resolution / 3;
            // 垂直对齐:
            tl.ParagraphAlignment = header ? ParagraphAlignment.Near : ParagraphAlignment.Far;
            // 水平对齐:
            tl.TextAlignment = horzAlign;
            tl.Append(text, tf);
            // 注意:如果页眉或页脚的某些部分是静态的,我们可以缓存相应的 TextLayout
            // 对象并通过在每个页面上绘制缓存的 TextLayout 来节省一些周期,而不需要任何其他内容:
            tl.PerformLayout(true);
            // 在 (0,0) 处绘制标题(标题由边距和对齐方式定位):
            page.Graphics.DrawTextLayout(tl, PointF.Empty);
        }

        // 主程序。
        public int CreatePDF(Stream stream)
        {
            _doc = new GcPdfDocument();
            var page = _doc.NewPage();
            // 添加关于翻转横向的注释:
            var noteRect = Common.Util.AddNote(
                "我们在此示例中翻转页面方向只是为了表明这些页眉可以适应不断变化的页面大小。",
                page);
            // 准备一个包含一些长文本的 TextLayout 并打印它(详细信息请参阅PaginatedText):
            var tl = page.Graphics.CreateTextLayout();
            tl.DefaultFormat.Font = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            tl.MaxWidth = _doc.PageSize.Width;
            tl.MaxHeight = _doc.PageSize.Height;
            tl.MarginAll = tl.Resolution;
            tl.MarginTop = noteRect.Bottom + 18;
            // 添加示例文本:
            tl.Append(Common.Util.LoremIpsum(20));
            // 计算字形并执行布局(另请参阅下面循环中的 PerformLayout 调用):
            tl.PerformLayout(true);
            // 在循环中,分割并渲染文本:
            while (true)
            {
                var splitResult = tl.Split(null, out TextLayout rest);
                page.Graphics.DrawTextLayout(tl, PointF.Empty);
                if (splitResult != SplitResult.Split)
                    break;
                tl = rest;
                tl.MarginTop = tl.Resolution;
                page = _doc.Pages.Add();
                // 为了示例,切换页面方向:
                page.Landscape = !_doc.Pages[_doc.Pages.Count - 2].Landscape;
                // 更新布局大小以反映新的页面方向:
                tl.MaxWidth = page.Size.Width;
                tl.MaxHeight = page.Size.Height;
                // 因为我们改变了布局尺寸,所以我们必须再次进行布局 -
                // 但无需重新计算字形即可做到这一点:
                tl.PerformLayout(false);
            }
            // 在单独的循环中渲染标题(以便我们可以提供“Page X of Y”标题):
            var tf = new TextFormat() { Font = StandardFonts.Helvetica, FontSize = 10, ForeColor = Color.Gray };
            var now = Common.Util.TimeNow().ToString("u");
            for (int pageIdx = 0; pageIdx < _doc.Pages.Count; ++pageIdx)
            {
                RenderHeader(now, tf, pageIdx, true, TextAlignment.Leading);
                RenderHeader("Easy Page Headers Sample", tf, pageIdx, true, TextAlignment.Center);
                RenderHeader($"Page {pageIdx + 1} of {_doc.Pages.Count}", tf, pageIdx, true, TextAlignment.Trailing);
                RenderHeader("Page footer - left", tf, pageIdx, false, TextAlignment.Leading);
                RenderHeader("DsPdf", tf, pageIdx, false, TextAlignment.Center);
                RenderHeader("Page footer - right", tf, pageIdx, false, TextAlignment.Trailing);
            }
            // 完毕:
            _doc.Save(stream);
            return _doc.Pages.Count;
        }
    }
}