Pdf File Writer 中文应用(PDF文件编写器C#类库)

  该文由小居工作室原创(QQ:2482052910)翻译并提供解答支持,原文地址:Pdf File Writer 中文应用(PDF文件编写器C#类库):http://www.cnblogs.com/wjs5943283/p/6528853.html

 首先 Pdf File Writer  是一个很好用的PDF文件生成工具,由于作者对中文编码不熟悉,涉及到中文字体的输出会发生异常,经过本人多次测试,仿宋、黑体字体的中文还比较好,不容易发生异常。宋体测试很多次都没有成功,包括咨询了作者本人也没有得到满意的答案:

    

  这一篇主要是对 PDF-File-Writer的使用进行中文翻译,在各位使用的过程中有什么问题,可以联系我。我已经在生产环境中使用。

     原文地址:https://www.codeproject.com/Articles/570682/PDF-File-Writer-Csharp-Class-Library-Version?msg=5362362#xx5362362xx

     下面为全文翻译:

                PDF文件编写器C#类库   

              (版本1.19.1增强版)

  • 下载PDF文件的示例 - 258 KB => 01  
  • 下载C#类库(DLL) - 50.5 KB =>  02
  • 下载演示项目(包括DLL) - 546.5 KB  => 03
  • 下载源 - 860.4 KB  => 04

    已全部打包到百度云盘:链接:http://pan.baidu.com/s/1nvFKDvj 密码:apj0  

  示例生成的PDF文件:

 

 

1.介绍

PDF文件编写器C#类库PdfFileWriter允许您直接从.net应用程序创建PDF文件。库免除了您的PDF文件结构的细节。要使用库,您需要添加对附加PdfFileWriter.dll的类库文件的using PdfFileWriter引用,在使用库的每个源文件中添加一个语句,并包含PdfFileWriter.dll与您的分发。有关更多详细信息,请转到2.23安装或者,您可以在应用程序中包含库的源代码,并避免分发单独的数据链接库文件。最低开发要求是.NET Framework 4.0(Visual Studio  2013,在vs2012中使用也很正常)。

 版本1.19.0修改说明

  • 文档链接允许PDF文档用户单击链接并跳转到文档的另一部分。添加文档链接分为两部分。目标定义为位置标记。位置标记必须具有唯一的名称,范围(LocalDestNamedDest)和位置(页面和位置)。第二部分是链接位置。这两个部分可以按任何顺序定义。他们被绑在一起的名字。名称区分大小写。许多链接可以指向同一位置标记。
  • 命名目标是PDF文档中的目标。它们使用位置标记以与文档链接相同的方式定义。范围必须设置为NamedDest。当诸如Adobe Acrobat的PDF阅读器打开PDF文档时,它可以在查看窗口中显示目标时打开文档。有关详细信息,请参见第2.22节“ 文档链接”和“命名目标”
  • PdfFileWriter的以下功能已修改:Web链接,视频显示,音频播放,保存或查看嵌入文件。在库的以前版本中,Web链接由DrawText方法TextBoxPdfTable类支持。从1.19.0开始,相同的支持可用于记录链接,视频,音频和嵌入文件。
  • 对于代码示例,请查看OtherExample.ca和OtherExample.pdf。特别注意目录页和页码7。
  • 版本1.19.1 Fix:AddLocationMarker修复具有小数分隔符而不是句点的区域。

    从1.18.0 / 1.19.0之前的PdfFileWriter库升级
    字体资源创建修改自:

// 原创建字体方式:
FontResource = new PdfFont(Document, FontName, FontStyle, EmbeddedFont);
// 新的创建方式:
FontResource = PdfFont.CreatePdfFont(Document, FontName, FontStyle, EmbeddedFont);

    换句话说,一个全局性的“查找和替换”从new PdfFontPdfFont.CreatePdfFont会做的工作。

    已命名目标已修改:

//
Document.AddNamedDestination(DestName, Page, FitArg, SideArg);
//
Page.AddLocationMarker(LocMarkerName, Scope, FitArg, SideArg);

  PDF文件编写器C#类库支持以下PDF文档的功能:

    图形:绘制线条,矩形,多边形,贝塞尔曲线,前景和背景颜色,图案和阴影。第2.1节坐标系。
    图像:绘图光栅(位图)图像和矢量(图元文件)图像。第2.4节。图像支持。
    文本:在列中绘制文本行和文本。第2.3节语言支持。
    条形码:支持条形码128,条形码39,条形码交错2,条形码EAN13和条形码UPC-A。第2.5节条码支持。
    QR码:支持二维码。第2.8节QR码支持。
    加密:支持AES-128加密。第2.6节加密支持。
    Web链接:Web链接交互支持。第2.7节Web链接支持。
    书签:支持文档大纲。第2.9节书签支持。
    命名目标:支持使Acrobat在特定页面打开PDF文档。第2.22节文档链接和命名目的地。
    图表:支持Microsoft Charting。第2.10图表支持。
    打印到PDF:从PrintDocument过程创建PDF文档。2.11节PrintDocument支持。
    显示数据表。第2.12节数据表支持
    播放视频文件。2.13节播放视频文件
    播放声音文件。2.14节播放声音文件
    附加数据文件。第2.15节附加数据文件
    重新排序页面。第2.16节重新排序页面
    PDF文档输出到文件或流。第2.17节PDF文档输出。
    PDF文档信息字典。PDF阅读器在文档属性的“说明”选项卡中显示此信息。信息包括:标题,作者,主题,关键字,创建的日期和时间,修改的日期和时间,生成文件的应用程序,PDF生成器。第2.18节文档信息字典。
    内存控制:将已完成页面的内容信息写入输出文件,并使用垃圾回收器释放未使用的内存。第2.19节。内存控制。
    绘制由System.Windows.Media.PathGeometry类定义的图形。输入参数可以是文本字符串或PathGeometry类。第2.20节Windows Presentation Foundation WPF
透明度或不透明度现在可用于绘制形状,线条,文本和图像。您的应用程序可以为所有图形和文本设置颜色的Alpha组件。第2.21节透明度,不透明度,Alpha颜色分量和混合
混合。新库支持PDF颜色混合方案。混合定义如何处理在先前项目上绘制的新项目的颜色。第2.21节透明度,不透明度,Alpha颜色分量和混合

 

  创建PDF是一个六个步骤的过程。

    步骤1:创建一个文档对象PdfDocument。
    步骤2:创建资源对象,如字体或图像(ie PdfFont 或PdfImage)。
    步骤3:创建页面对象PdfPage。
    步骤4:创建内容对象PdfContents。
    步骤5:向内容对象添加文本和图形(使用PdfContents方法)。
    对其他页面重复步骤3,4和5
    步骤6:通过调用CreateFile方法创建您的PDF文档文件PdfDocument。

  步骤5是您的大部分编程工作将花费的地方。通过调用PdfContents类的方法来渲染图形和文本来实现添加内容。内容类具有丰富的集(大约100种)用于向文档中添加文本和图形的方法。

PdfDocument实现IDisposable接口释放非托管资源。创建PDF文件后CreateFile调用该方法Document.Dispose()。然而,为了确保资源的释放,你应该用一个语句或一个block./p> 包装PdfDocument创建和最终CreateFileusingtry/catch

  本文附带的演示程序是开发用于调试库的测试程序。在TestPdfFileWriter有主屏幕上的六个按钮。五个按钮生成PDF文件的示例,一个按钮显示计算机上可用的所有字体。第一个按钮“文章示例”创建显示在本文顶部的PDF文件。第3节。

  如前所述,PdfFileWriterC#类库使您免受PDF文件结构的复杂性。然而,良好的了解PDF文件总是一个优势。Adobe PDF文件规范文档可从Adobe网站获得:“PDF参考,第六版,Adobe便携式文档格式版本1.7,2006年11月”。这是一个令人恐惧的1310页的文件。我强烈建议阅读第4章图形以及文本第5章的第5.2和5.3节。

如果你想分析这个项目创建的PDF文件,或者如果你想了解一般的PDF文件结构,你可以使用我的上一篇文章“PDF文件分析器与C#解析类”附带的演示程序。本文简要介绍了PDF规范。

  

2. PDF文件编写器库一般说明  

2.1 坐标系和测量单位

  PDF坐标系原点在页面的左下角X轴指向右边Y轴指向向上的方向。

PDF计量单位是点。一英寸有72点。PDF文件编辑器允许您选择自己的计量单位。表示位置,宽度或高度的所有方法参数必须在您的度量单位中。有两个例外:字体大小和分辨率。字体大小始终为点。分辨率始终为每英寸像素数。PDF文件编写器将所有输入参数转换为点。所有内部测量值和计算均采用双精度。在创建PDF文件的最后一步,将值转换为文本字符串。转换精度为六位数。使用的转换公式为: 

//  Double类型
if(Math.Abs(Value) < 0.0001) Value = 0.0;
String Result = ((Single) Value).ToString();

2.2  小数分隔符

  诸如Adobe Acrobat之类的PDF阅读器期望实数具有小数,以使用句点作为小数分隔符。一些世界地区使用其他小数分隔符,如逗号。由于PDF File Writer库的版本1.1将使用句点作为小数分隔符,而不考虑计算机的区域设置。

2.3  语言支持,字体和字符集

  PDF文件编写器库支持您计算机上安装的大多数字体。唯一的例外是设备字体。支持的字体遵循OpenType字体规范。有关详细信息,请参阅Microsoft字体 - OpenType规范要绘制的文本存储在由Unicode字符组成的字符串中。该库将接受除控制代码0到31和128到159之外的任何字符(0到65536)。每个字符都将转换为字形。字形在页面上从左到右以与存储在字符串中的顺序相同的顺序绘制。实际上,所有字体文件只支持所有可能的Unicode字符的一个子集。换句话说,您必须选择支持项目语言的字体或要尝试显示的符号。如果输入字符串包含不受支持的字形,PDF阅读器将显示“未定义字形”。通常它是一个小矩形。本文附带的测试程序有一个“字体族”按钮。如果单击它,您可以在计算机上查看所有可用的字体,并在每个字体中查看所有可用字符。如果项目的语言是从左到右的语言,每个字符被翻译成一个字形,并且字形在字体中定义,结果应该是你期望的。如果结果不是您期望的结果,以下是一些额外的注释:

  Unicode控制字符。Unicode控制字符用于控制文本的解释或显示,但这些字符本身没有视觉或空间表示。PDF文件编写器不识别这些字符。库假定每个字符都是显示字符。它们将显示为未定义字符。

从右到左语言。通常,文本字符串中的字符的顺序是人们读取它们的顺序。由于库从左到右绘制,文本将被向后写。ReverseString方法颠倒字符顺序。如果文本只有从右到左的字符,这将解决问题。如果文本是从右到左,从左到右,数字和一些字符如括号()[] <> {混合,它不会产生所需的结果。另一个限制是TextBox类不能打断长到右文本到行。

     在某些语言中,两个或多个字符的序列被组合在一起以显示一个字形。您的软件可以识别这些序列并将其替换为正确的字形。

虚线圆。如果你看看Glyph Metrics屏幕的Glyph列,你可以看到一些glyphs有一个小的虚线圆圈(即字符代码2364和2367)。这些字符是字符序列的一部分。不显示虚线圆圈。如果前进宽度为零,边界框在Y轴的左侧,则此字形将为drawen ok。它将显示在上一个字符的顶部。如果前进宽度不为零,则此字形应显示在上一个字符之前。你的软件可以通过颠倒这两个字符来实现。

2.4  图像支持

  在PDF文档中显示图像由PdfImage类和PdfImageControl类处理。图像源可以是图像文件或.NET Image派生类或用于黑白图像的布尔数组。图像以Jpeg格式保存到PDF文件,索引位图,灰色位图或黑白位图。位图格式是无损压缩。PdfImageControl控制保存图像的过程。彩色图片应以Jpeg格式保存。要控制图像数据大小,您可以降低分辨率或更改图像质量。彩色图像可以以灰色阴影保存。数据大小减少了三个,但你失去了颜色。如果图像是以图表中的编程方式创建的,并且颜色数小于256,则图像可以保存为索引位图。每个颜色由与3个字节相比的一个字节(或更少)表示。这可以导致非常重要的文件大小减少。ChartExample.pdf文件从642KB减少到72KB。如果图像是黑白的,如在PdfPrintDocument图像的文本,图像可以保存为BWImage。在PrintExample.pdf的情况下,Jpeg文件是1795KB,黑白版本是66KB。

  dfFileWriter库中的其他三个类使用PdfImage支持。类是:PdfChart,PdfQRCode和PdfPrintDocument。

  图片是PDF资源。创建映像资源时,软件会将映像数据直接加载到PDF输出文件中。换句话说,图像数据不驻留在存储器中,允许大量的图像而不减少程序存储器空间。PdfImage类有三个构造函数。

//从文件中加载图片
PdfImage Image = new PdfImage(PdfDocument Document, String ImageFileName, PdfImageControl ImageControl);

// 从内存中加载图片(Image,Bitmap)
PdfImage Image = new PdfImage(PdfDocument Document, Image MemoryImage, PdfImageControl ImageControl);

// 加载二进制
PdfImage Image = new PdfImage(PdfDocument Document, Boolean[,] BWImage, PdfImageControl ImageControl);

    参数是: 

  • DocumentPdfDocumentPDF文档对象。
  • ImageFileName:图像文件是可以加载到.NET Image派生类的任何文件图像派生类是Bitmap光栅图像或Metafile矢量图像的图像。如果输入文件名,扩展名为.emf或.wmf,则将文件加载到文件中Metafile,否则文件将加载到Bitmap
  • MemoryImage:是位图或由应用程序在内存中创建的元文件。
  • BWImage:是一个布尔二维数组。False表示黑色,true表示白色。PdfQRCode类使用此格式来表示QR图像。
  • ImageControl:是一个可选参数,用于保存图像创建属性。

  PdfImageControl具有以下属性。所有属性都是可选的。

  • SaveAs:图片另存为JpegIndexedImageGrayImageBWImage
  • CropRect:裁剪矩形是定义要裁剪的图像区域的矩形。注意:矩形坐标是.net标准。原点在左上角,Y轴朝下。裁剪矩形可以Rectangle在这种情况下,尺寸以像素为单位。裁剪矩形必须包含在图像中。
  • CropPercent:如上所示裁剪矩形,但尺寸以图像宽度和高度的百分比表示。
  • Resolution:图像分辨率设置图像分辨率,前提是它小于源图像的分辨率。分辨率以每英寸像素为单位指定。减小的分辨率意味着较小的PDF文件。
  • ImageQuality:它是一个在0到100范围内的整数,表示质量差到最佳质量的图像,或DefaultQuality(-1)表示以默认质量保存图像。较低的图像质量意味着较小的PDF文件。如果图像质量未定义,则将其视为默认质量。.net框架工作默认保存方法使用的质量因子为75.此编号不由Microsoft记录。它是通过实验和互联网搜索计算的。
  • GrayToBWCutoff:将位图转换为黑白是两步过程。第一种是标准颜色到灰色阴影。如果灰度阴影低于截止,则第二个将像素设置为黑色,如果灰度低于截止,则将像素设置为白色。有效值为1到99。
  • ReverseBW:在灰色或BW图像中,如果此属性为true,则颜色反转。

  其他方法PdfImage

  该ImageSize方法返回具有适合给定区域的正确宽高比的最大矩形。

    SizeD ImageSize(Double Width, Double Height);

     该ImageSizePosition方法返回具有适合给定区域的正确宽高比的最大矩形,并基于ContentAlignment枚举对其进行定位。

  ImageSizePos ImageSizePosition(Double Width, Double Height, ContentAlignment Alignment);

  最后将图像绘制成内容使用DrawImage方法。如果您希望图像保持正确的宽高比使用ImageSizeImageSizePosition计算宽度和高度。如果宽度和高度的比率与图像不同,则图像将看起来在一个方向上拉伸。

  Contents.DrawImage(Image, PosX, PosY, Width, Height);

应当指出的是,除了PdfImagePdfQRCodePdfChartPrintPdfDocument产生PDF文档中PDF图像

2.5  条形码支持

  下面的代码说明了如何在PDF文档中包含UPC-A条形码。

// 创建对象
BarcodeEAN13 Barcode = new BarcodeEAN13("123456789010");

// 绘制条形码
Contents.DrawBarcode(PosX, PosY, BarWidth, BarcodeHeight, Barcode, Font, FontSize);

  在这种情况下,类是具有12位数字输入字符串的BarcodeEAN13。结果是UPC-A条形码。

  PDF文件编写器库包括基类Barcode 对于每个支持的条形码,需要一个派生类。类库包括四个子类:Barcode128Barcode39 BarcodeInterleaved2of5 BarcodeEAN13BarcodeEAN13生产EAN-13条码,如果输入字符串为13位数字和UPC-A如果输入字符串为12位。具有13位数字和前导零的输入字符串被认为是UPC-A。

  该DrawBarcode方法具有多个重载。您可以指定条形码左下角的位置,窄条的宽度,条形码的高度以及导出的条形码类别。有可选参数:对齐(左,中,右)颜色和字体以显示文本。条形码周围的安静区域是您的责任。可选文本显示在条形码下方。如果你选择的颜色不是黑色,你应该确保背景的对比是显着的。用法示例中给出3.7绘制条形码ArticleExample.csOtherExample.cs

  如果要为另一个条形码创建派生类,请使用三个包含的类的源代码作为示例。

2.6  加密支持

  PDF文件编写器库支持AES 128和标准128(RC4)加密。有关详细信息,请参阅PDF参考第六版(1.7版)第3.5节加密。PDF文件编写器支持两种类型的加密过滤器,AES-128和128.标准128是RC4加密。它被认为不安全。对于新项目不使用它。它不支持公钥密码编码收件人列表。

  要加密PDF文档,请调用类中SetEncryption定义的四种方法之一PdfDocument

  1.设置不带参数的加密。

  PDF文件编写器库将使用AES-128加密来加密PDF文档。PDF阅读器将打开文档,而无需请求密码。权限标志设置为允许所有。

   Document.SetEncryption();

  2.使用一个参数设置加密。

  PDF文件编写器库将使用AES-128加密来加密PDF文档。参数是权限。权限标志定义如下。你可以或者一起获得多个权限。PDF参考手册有完整的权限描述。PDF阅读器将打开文档,而无需请求密码。

 Document.SetEncryption(Permission Permissions);

  3.使用两个参数设置加密。

      PDF文件编写器库将使用AES-128加密来加密PDF文档。两个参数是用户密码和权限。PDF阅读器将使用用户密码打开文档。权限将根​​据参数设置。

  Document.SetEncryption(String UserPassword, Permission Permissions);

  4.使用四个参数设置加密。

  PDF文件编写器库将使用EncryptionType.Aes128加密或EncryptionType.Standard128加密来加密PDF文档。四个参数是用户密码,所有者密码,权限和加密类型。如果用户密码为空,将采用默认密码。如果所有者密码为null,则软件会生成随机数密码。Standard128加密被认为不安全。它不应该用于新项目。

  诸如Acrobat的PDF阅读器将接受用户或所有者密码。如果使用所有者密码打开文档,PDF阅读器将打开它,并将所有权限设置为允许操作。

  Document.SetEncryption(String UserPassword, String OwnerPassword, Permission Permissions, EncryptionType Type);

  权限标志如下:

//全描述引用1.7版本表3.20
public enum Permission
    {
    None = 0,
    LowQalityPrint = 4,    // bit 3
    ModifyContents = 8,    // bit 4
    ExtractContents = 0x10,    // bit 5
    Annotation = 0x20,    // bit 6
    Interactive = 0x100,    // bit 9
    Accessibility = 0x200,    // bit 10
    AssembleDoc = 0x400,    // bit 11
    Print = 0x804,        // bit 12 + bit 3
    All = 0xf3c,        // bits 3, 4, 5, 6, 9, 10, 11, 12
    }

2.7   Web链接支持

  PDF文件编写器库提供对Web链接的支持。此功能是PDF参考手册第8节交互功能中描述的PDF交互功能之一。它是注释和动作的组合。注释将Web链接与页面上的区域相关联。当用户点击该区域时,PDF阅读器将激活导航到期望的网页的默认web浏览器。

  注释区域是由相对于页面左下角的绝对坐标定义的矩形区域。添加类的Web链接调用AddWebLink方法PdfPage

 Page.AddWebLink(Double LeftPos, Double BottomPos, Double RightPos, Double TopPos, String WebLink);

  注释不是页面内容的一部分。为了让PDF文档的读者知道在哪里点击,您需要在页面上的相同区域中显示相应的文本或图形。换句话说,你需要调用两个方法。AddWebLink与网页和与内容相关联的第二方法相关联的方法。第二种方法可以是图形对象,例如图像或矩形或文本。因为AddWebLink需要相对于页面左下角的坐标,所以图形对象的坐标必须相同。换句话说,不要使用平移,缩放或旋转。如果你这样做,你需要确保这两个区域将重合。

  PDF文件编写器有几种PdfContents支持文本注释的方法。

  使用相关的网络链接绘制一行文本。文本将左对齐,带下划线和蓝色。文本位置相对于页面的左下角。

PdfContents.DrawWebLink(PdfPage Page, PdfFont Font, Double FontSize,
    Double TextAbsPosX, Double TextAbsPosY, String Text, String WebLink);

  使用相关的网络链接绘制一行文本。文本位置相对于页面的左下角。

PdfContents.DrawWebLink(PdfPage Page, PdfFont Font, Double FontSize, Double TextAbsPosX, Double TextAbsPosY,
    TextJustify Justify, DrawStyle DrawStyle, Color TextColor, String Text, String WebLink);

  在其中绘制Web链接TextBox是一个两步过程。首先,使用类的一种AddText方法将文本和Web链接字符串添加到框中TextBox第二个你绘制的TextBox页面内容使用的DrawText方法之一PdfContents

添加网络链接TextBox文本将显示为下划线和蓝色。 

TextBox.AddText(PdfFont Font, Double FontSize, String Text, String WebLink);

  添加网络链接TextBox文本属性由DrawStyle定义FontColor

TextBox.AddText(PdfFont Font, Double FontSize, DrawStyle DrawStyle, Color FontColor, String Text, String WebLink);

  第二步绘制文本到内容。此方法假设没有额外的行或段落间距。请注意,如果你调用DrawTextPdfPage参数上TextBoxWebLink信息,ApplicationException将被抛出。

//PosYTop 可以引用上一个元素的PointY位置

PdfContents.DrawText(Double PosX, ref Double PosYTop, Double PosYBottom, Int32 LineNo, TextBox Box, PdfPage Page);

  此方法允许您定义额外的行或段落间距。请注意,如果你调用DrawTextPdfPage参数上TextBoxWebLink信息,ApplicationException将被抛出。

PdfContents.DrawText(Double PosX, ref Double PosYTop, Double PosYBottom, Int32 LineNo,
    Double LineExtraSpace, Double ParagraphExtraSpace, Boolean FitTextToWidth, TextBox Box, PdfPage Page);

    有关编码示例,请参阅3.4 Draw Frame,ArticleExample.cs和OtherExample.cs源代码。

2.8  QR码支持

  从V1.7开始,PDF文件编写器库提供对QR码的支持。该程序支持三个字符集:数字,字母数字和8位字节。程序不支持汉字字符。QR码是图像资源。库将QR代码内容转换为图像。要在文档中显示QR码,需要定义一个资源对象,并将此对象添加到页面的内容。程序自动选择最佳字符集和最佳矩阵大小。用户必须提供数据字符串和所需的纠错级别。错误校正级别是:L低(7%),M中(15%),Q中中高(25%),H高(30%)。字符集定义为:数字数据(数字0-9)。字母数字(数字0-9,大写字母AZ和九个其他字符空格$%* + - 。/:),8位字节数据。程序将扫描数据串输入并选择最有效的字符集。如果您的数据可以分成只有数字或只是字母数字字符的段,您可以创建一个QR码对象与数据字符串数组。

  使用单个数据字符串创建QR代码对象。

PdfQRCode QRCode = new PdfQRCode(PdfDocument Document, String DataString, ErrorCorrection ErrorCorrection);

  或者,使用数据字符串数组创建QR Code对象。如果要将数据字符串分成不同字符集的部分,请使用此形式。

PdfQRCode QRCode = new PdfQRCode(PdfDocument Document, String[] DataString, ErrorCorrection ErrorCorrection);

  默认情况下,创建的图像将具有每个QR码模块4×4像素和图像周围16个像素的安静空间。要覆盖默认使用:

QRCode.SetModuleSize(Int32 ModuleSize, Int32 QuietZone);

  绘制QR码调用DrawQRCode方法PdfContentsQRCode是一个正方形。宽度和高度相同。

Contents.DrawQRCode(PdfQRCode QRCode, Double OrigX, Double OrigY, Double Width);

  有关编码示例,请参阅3.7绘制条形码,ArticleExample.cs和OtherExample.cs源代码。

2.9  书签支持

  书签在PDF规范(第8.2.2节“文档大纲”)中描述如下:“PDF文档可以可选地在屏幕上显示文档大纲,允许用户以交互方式从文档的一个部分导航到另一个部分。的树结构层次结构的大纲项(有时称为书签),其作为内容的可视表以向用户显示文档的结构。用户可以通过用鼠标点击它们来交互地打开和关闭单个项。

OtherExample.cs源代码具有书签示例。在一个位置有三个层次的层次结构。您可以在OtherExample.pdf文件中查看结果。

向应用程序添加书签的第一步是:

// 文档创建书签
PdfBookmark BookmarkRoot = Document.GetBookmarksRoot();

  此步骤激活文档中的书签,并返回根节点。

  添加书签类似于向窗体中添加控件。第一级书签被添加到根。后续级别将添加到现有书签。至少,您必须定义页面上的标题,页面,垂直位置以及打开的条目标志。page是要去的页面的PdfPage对象。YPos是相对于页面左下角的垂直位置。如果较低级别的书签是可见的,则打开条目标志为真,如果较低级别的书签被隐藏,则为假。默认情况下,第一级始终可见。

// 书签实例
PdfBookmark FirstLevel_1 = BookmarkRoot.AddBookmark("Chapter 1", Page, YPos, false);
    PdfBookmark SecondLevel_11 = FirstLevel_1.AddBookmark("Section 1.1", Page, YPos, false);
    PdfBookmark SecondLevel_12 = FirstLevel_1.AddBookmark("Section 1.2", Page, YPos, false);
        PdfBookmark ThirdLevel_121 = SecondLevel_12.AddBookmark("Section 1.2.1", Page, YPos, false);
        PdfBookmark ThirdLevel_122 = SecondLevel_12.AddBookmark("Section 1.2.2", Page, YPos, false);
    PdfBookmark SecondLevel_13 = FirstLevel_1.AddBookmark("Section 1.3", Page, YPos, false);
PdfBookmark FirstLevel_2 = BookmarkRoot.AddBookmark("Chapter 2", Page, YPos, false);
    PdfBookmark SecondLevel_21 = FirstLevel_2.AddBookmark("Section 2.1", Page, YPos, false);
    PdfBookmark SecondLevel_22 = FirstLevel_2.AddBookmark("Section 2.2", Page, YPos, false);

  AddBookmark()方法有四个重载变体:

// 基本的
public PdfBookmark AddBookmark
    (
    String        Title,        // bookmark title
    PdfPage        Page,        // bookmark page
    Double        YPos,        // bookmark vertical position relative to bottom left corner of the page
    Boolean        OpenEntries    // true is display children. false hide children
    )

//标题颜色和样式
public PdfBookmark AddBookmark
    (
    String        Title,        // bookmark title
    PdfPage        Page,        // bookmark page
    Double        YPos,        // bookmark vertical position relative to bottom left corner of the page
    Color        Paint,        // bookmark color. Coloe.Empty is display title in default color
    TextStyle        TextStyle,    // bookmark text style: normal, bold, italic, bold-italic
    Boolean        OpenEntries    // true is display children. false hide children
    )

// PointX和缩放
public PdfBookmark AddBookmark
    (
    String        Title,        // bookmark title
    PdfPage        Page,        // bookmark page
    Double        XPos,        // bookmark horizontal position relative to bottom left corner of the page
    Double        YPos,        // bookmark vertical position relative to bottom left corner of the page
    Double        Zoom,        // Zoom factor. 1.0 is 100%. 0.0 is ignore zoom.
    Boolean        OpenEntries    // true is display children. false hide children
    )

// 完整
public PdfBookmark AddBookmark
    (
    String        Title,        // bookmark title
    PdfPage        Page,        // bookmark page
    Double        XPos,        // bookmark horizontal position relative to bottom left corner of the page
    Double        YPos,        // bookmark vertical position relative to bottom left corner of the page
    Double        Zoom,        // Zoom factor. 1.0 is 100%. 0.0 is ignore zoom.
    Color        Paint,        // bookmark color. Coloe.Empty is display title in default color
    TextStyle        TextStyle,    // bookmark text style: normal, bold, italic, bold-italic
    Boolean        OpenEntries    // true is display children. false hide children
    )

  PdfBookmark类暴露一个方法GetChild您可以通过调用GetChild一个或多个整数参数来获取任何书签每个参数是级别中子位置的零基本参数。例如GetChild(2)第一级的第三项。GetChild(2, 3)是第三个第一级项目的第四个第二级项目。

2.10。图表支持

  PDF规范没有特定的图表支持。PDF文件编写器库通过允许开发人员创建Microsoft Charting对象并将此对象作为图像绘制到PDF文件中来提供图表支持。有关Microsoft图表控件注释MSDN库文档Visual Studio 2012图表控件的详细信息。图表名称空间的文档在“ 数据可视化图表命名空间”中提供。附上ChartExample.cs有四个图表的例子。如果您打算使用图表,您需要添加System.Windows.Forms.Visualization对您的项目的引用。在每个源模块使用Chart你需要引用System.Windows.Forms.DataVisualization.Charting命名空间。

  将图表添加到PDF文档是四个步骤的过程。

  • 创建图表对象。
  • 创建PdfChart对象。
  • 构建图表。
  • 绘制PdfChart到PdfContents。

  创建图表的推荐方法是使用PdfChart对象的静态方法

//  参数:文档对象,宽,高,分辨率
Chart MyChart = PdfChart.CreateChart(PdfDocument Document, Double Width, Double Height, Double Resolution);

  你可以Chart自己实例化类。

Chart MyChart = new Chart();
MyChart.RenderingDpiY = 300;    // example of 300 pixels per inch
MyChart.Width = 1950;        // example of 6.5 inches in pixels    
Mychart.Height = 1350;        // example of 4.6 inches in pixels

  接下来PdfChartChart上面创建一个或者,您可以覆盖分辨率。

// resolution is optional. It will override the resolution set above.
PdfChart MyPdfChart = new PdfChart(PdfDocument Document, Chart MyChart, Double Resolution);

  接下来,您构建您的图表。ChartExample.cs有四个例子。构建图表的文档超出了本文的范围。互联网上有很多例子。

  PdfChart有一种CreateFont方法来简化字体的创建。它将基于图表的分辨率计算字体大小。

// FontSizeUnit is an enumeration
// Available units: pixel, point, UserUnit, Inch, cm, mm
Font CreateFont(String FontFamilyName, FontStyle Style, Double FontSize, FontSizeUnit Unit);

  最后一步是绘制图表。

// Draw the chart at OrigX, OrigY in user units
// The width and height of the chart are taken from the Chart object.
// They are calculated from the size in pixels and resolution of the chart.
public void PdfContents.DrawChart(PdfChart MyPdfChart, Double OrigX, Double OrigY);

// Draw the chart at OrigX, OrigY with Width and Height as specified, all in user units.
// NOTE: Width and Height should be selected to agree with the aspect ratio of the chart object.
public void PdfContents.DrawChart(PdfChart MyPdfChart, Double OrigX, Double OrigY, Double Width, Double Height);

  本PdfChart类提供了一些可选的方法来控制图像的定位。

  该ImageSize方法返回具有适合给定区域的正确宽高比的最大矩形。

SizeD ImageSize(Double Width, Double Height);

  该ImageSizePosition方法返回具有适合给定区域的正确宽高比的最大矩形,并基于ContentAlignment枚举对其进行定位。

ImageSizePos ImageSizePosition(Double Width, Double Height, ContentAlignment Alignment);

2.11  打印文档支持

  打印文档支持允许您以打印到打印机和生成PDF文档的相同方式打印报告。这种产生PDF文件的方法和PdfContents用于产生PDF文件的方法之间的区别在于栅格图形与矢量图形之间的差异。打印文档支持每页创建一个jpeg图像。PrintExample.cs有创建三页文档的示例。

  通常每个页面是页面的完整图像。如果您的页面是Letter 尺寸,分辨率为每英寸300像素,每个像素为3个字节,页面的位图将是25.245MB长。PrintPdfDocument具有CropRect可以显着减小位图的大小的方法假设使用一英寸边距,位图的活动大小将减少到15.795 MB。减少37.4%。

// main program
// Create empty document
Document = new PdfDocument(PaperType.Letter, false, UnitOfMeasure.Inch);

// create PrintPdfDocument producing an image with 300 pixels per inch 创建一个300像素每英寸的PrintPdfDocument
 PdfImageControl ImageControl = new PdfImageControl();
ImageControl.Resolution
= 300.0;
PrintPdfDocument Print
= new PrintPdfDocument(Document, ImageControl);

// PrintPage in the delegate method PrintPageEventHandler
// This method will print one page at a time to PrintDocument
Print.PrintPage += PrintPage;
// set margins in user units (Left, top, right, bottom) 边距设置
// note the margins order are per .net standard and not PDF standard
Print.SetMargins(1.0, 1.0, 1.0, 1.0);
// crop the page image result to reduce PDF file size //缩小尺寸
// the crop rectangle is per .net standard.

// The origin is top left. 原点在左上方
Print.CropRect = new RectangleF(0.95F, 0.95F, 6.6F, 9.1F);

// initiate the printing process (calling the PrintPage method)启动打印进程
// after the document is printed, add each page as an image to PDF file.在打印完文档之后,将每个页面作为一个图像添加到PDF文件中。

Print.AddPagesToPdfDocument();
// dispose of the PrintDocument object

Print.Dispose();

// create the PDF file
Document.CreateFile(FileName);

  PrintPage方法的示例

// Print each page of the document to PrintDocument class打印文档的每一页的PrintDocument类
// You can use standard PrintDocument.PrintPage(...) method.
// NOTE: The graphics origin is top left and Y axis is pointing down.图形原点是左上角,Y轴指向下方
// In other words this is not PdfContents printing.换句话说,这不是PdfContents的打印
 public void PrintPage(object sender, PrintPageEventArgs e) { 

// graphics object short cut Graphics G = e.Graphics;

// Set everything to high quality
G.SmoothingMode = SmoothingMode.HighQuality;
G.InterpolationMode
= InterpolationMode.HighQualityBicubic;
G.PixelOffsetMode
= PixelOffsetMode.HighQuality;
G.CompositingQuality
= CompositingQuality.HighQuality;
// print area within margins
Rectangle PrintArea = e.MarginBounds;

// draw rectangle around print area

G.DrawRectangle(Pens.DarkBlue, PrintArea);
// line height
Int32 LineHeight = DefaultFont.Height + 8;
Rectangle TextRect
= new Rectangle(PrintArea.X + 4, PrintArea.Y + 4, PrintArea.Width - 8, LineHeight);

// display page bounds
// DefaultFont is defined somewhere else
String text = String.Format("Page Bounds: Left {0}, Top {1}, Right {2}, Bottom {3}", e.PageBounds.Left, e.PageBounds.Top, e.PageBounds.Right, e.PageBounds.Bottom);
G.DrawString(text, DefaultFont, Brushes.Black, TextRect); TextRect.Y
+= LineHeight;

// display print area
text = String.Format("Page Margins: Left {0}, Top {1}, Right {2}, Bottom {3}",
PrintArea.Left, PrintArea.Top, PrintArea.Right, PrintArea.Bottom);
G.DrawString(text, DefaultFont, Brushes.Black, TextRect); TextRect.Y
+= LineHeight;
// print some lines

for(Int32 LineNo = 1; ; LineNo++)
{
text
= String.Format("Page {0}, Line {1}", PageNo, LineNo);
G.DrawString(text, DefaultFont, Brushes.Black, TextRect);
TextRect.Y
+= LineHeight;
if(TextRect.Bottom > PrintArea.Bottom)
break;
}

// move on to next page
PageNo++;
e.HasMorePages
= PageNo <= 3;

return; }

2.12  数据表(table)支持

  数据表类允许您在PDF文档中显示数据表。PdfTable是控制一个表的显示的主类。表由标题行和数据行组成。每行被划分为单元格。PdfTableCell控制一个标题单元或一个数据单元的显示。如果使用头,它将显示在表的顶部。可选地,它将显示在每个附加页面的顶部。要在单元格中显示数据,请将数据加载到的Value属性中PdfTableCell 数据可以是:文本字符串,基本数值,布尔,字符TextBox,图像,QR码或条形码。独立于数据,您可以加载文档链接,网络链接,视频,音频或嵌入文件的单元格。单击单元格区域内的任何位置将使PDF阅读器激活文档链接,网络链接,视频,音频或嵌入式文件数据的显示由PdfTableStyle 类控制。PdfTable类包含默认单元格样式和默认标题样式。您可以覆盖其中的私有样式的默认样式PdfTableCell要显示表,请创建一个PdfTable对象。接下来,您将初始化表,标题单元格,数据单元格和样式对象。最后,设置一个循环并加载一行的单元格值,然后绘制此行。此循环继续,直到显示所有数据。下面您将看到生成表所需的步骤顺序。

  调用DrawRow方法时,软件计算所需的行高。行高是最高单元格的高度。如果表中有足够的空间,将绘制该行。当底部的可用空间太小时,将调用新页面,并且可选标题和当前行显示在表格的顶部。如果所需的行高度过大,将不适合全空表,则会引发异常。为了适应长多行字符串,或TextBoxes软件可以灵活地处理这些情况。多行字符串由PdfTable转换为a TextBoxPdfTableStyle类有一个TextBoxPageBreakLines属性。如果此属性设置为零(默认值),则将TextBox其视为其他数据值。TextBox高度必须适合页面。如果TextBoxPageBreakLines设置为正整数,系统将计算单元格的高度作为TextBox高度或高度的前几行指定TextBoxPageBreakLines系统将绘制具有适合页面的行数的行。将创建一个新页面,并绘制其余的线条。换句话说,long的第一行块TextBox将至少是TextBoxPageBreakLines长的。TableExample.cs源包含长TextBox单元格的示例

  创建PdfTable对象。

// create table
PdfTable Table = new PdfTable(Page, Contents, Font, FontSize);

  page是当前的PdfPage。内容是当前的PdfContents。Font是表默认字体。FontSize是以点为单位的默认字体大小。

  在页面上定义表的区域。

// table's area on the page
Table.TableArea = new PdfRectangle(Left, Bottom, Right, Top);

// first page starting vertical position
Table.RowTopPosition = StartingTopPosition;

  四个参数是表格相对于左下角和用户单位的四边。如果在第一页上,表顶部位置不在设置RowTopPosition为开始顶部位置的页面的顶部。在后续页面上,表格将始终从顶部开始。如果TableArea未指定,库将其设置为默认页面大小减少1英寸边距。

  将表宽度划分为列。

// divide table area width into columns
StockTable.SetColumnWidth(Width1, Width2, Width3, ...);

  参数的数量是列数。表格宽度减去总边界线将与这些参数成比例。

  一旦使用SetColumnWidth方法设置列的数量,库将创建两个PdfTableCell数组。一个用于标题单元的数组和一个用于数据单元的数组。

  数据表的行和列可以用边框线分隔。边框线属性由PdfTableBorder定义PdfTableBorderStyle有四个水平边框线:TopBorderBottomBorderHeaderHorBorder标题行和第一个数据行之间以及CellHorBorder数据行之间。有两组垂直边框线:HeaderVertBorder用于标题行CellVertBorder中的垂直边框线的数组,以及用于表的数据部分中的列之间的垂直边框线的数组。数组大小是列数加一。数组元素零是表的左边框。数组元素列是表的右边框。所有其他元素是分隔列的行。这些行中的每一行可以单独定义。有一些方法可以一次定义所有边界线,或定义每个单独的边界线。

  定义所有边框线的方法:

// clear all border lines
Table.Borders.ClearAllBorders();

// set all border lines to default values (no need to call)
// All frame lines are one point (1/72") wide
// All grid lines are 0.2 of one point wide
// All borders are black
Table.Borders.SetDefaultBorders();

// set all borders to same width and black color
Table.Borders.SetAllBorders(Double Width);

// set all borders to same width and a specified color
Table.Borders.SetAllBorders(Double Width, Color LineColor);

// set all borders to one width and all grid lines to another width all lines are black
Table.Borders.SetAllBorders(Double FrameWidth, Double GridWidth);

// set all borders to one width and color and all grid lines to another width and color
Table.Borders.SetAllBorders(Double FrameWidth, Color FrameColor, Double GridWidth, Color GridColor);

// set all frame borders to same width and black color and clear all grid lines
Table.Borders.SetFrame(Double Width);

// set all frame borders to same width and a specified color and clear all grid lines
Table.Borders.SetFrame(Double Width, Color LineColor);

  可以清除或设置每个水平边界线。示例是顶部边框线:

// clear border
Table.Borders.ClearTopBorder();

// set border with default color set to black
// Zero width means one pixel of the output device.
Table.Borders.SetTopBorder(Double LineWidth);

// set border
Table.Borders.SetTopBorder(Double LineWidth, Color LineColor);

  可以清除或设置每个垂直边界线。示例是单元格的垂直边框线:

// clear border
Table.Borders.ClearCellVertBorder(Int32 Index);

// set border with default color set to black
Table.Borders.SetCellVertBorder(Int32 Index, Double LineWidth);

// set border
Table.Borders.SetCellVertBorder(Int32 Index, Double LineWidth, Color LineColor);

  设置其他可选的表属性。下面的示例中给出的值是默认值。

// header on each page
HeaderOnEachPage = true;

// minimum row height
MinRowHeight = 0.0;

  表信息每次处理一行。每行由单元格组成。每列一个单元格。单元格信息的显示由PdfTableStyle类控制。有大约20个样式属性。对于完整的列表视图的源代码或帮助文件。这些样式中的一些特定于要显示的信息的类型。这里是一个例子

// make some changes to default header style
Table.DefaultHeaderStyle.Alignment = ContentAlignment.BottomRight;

// create private style for header first column
Table.Header[0].Style = Table.HeaderStyle;
Table.Header[0].Style.Alignment = ContentAlignment.MiddleLeft;

// load header value
Table.Header[0].Value = "Date";

// make some changes to default cell style
Table.DefaultCellStyle.Alignment = ContentAlignment.MiddleRight;
Table.DefaultCellStyle.Format = "#,##0.00";

// create private style for date column
Table.Cell[0].Style = StockTable.CellStyle;
Table.Cell[0].Style.Alignment = ContentAlignment.MiddleLeft;
Table.Cell[0].Style.Format = null;

  初始化完成后,显示数据。下面的例子是从TableExample.cs这是一张股票价格表。有6列。

// open stock daily price
StreamReader Reader = new StreamReader("SP500.csv");

// ignore header
Reader.ReadLine();

// read all daily prices
for(;;)
    {
    String TextLine = Reader.ReadLine();
    if(TextLine == null) break;

    String[] Fld = TextLine.Split(new Char[] {','});

    Table.Cell[ColDate].Value = Fld[ColDate];
    Table.Cell[ColOpen].Value = Double.Parse(Fld[ColOpen], NFI.PeriodDecSep);
    Table.Cell[ColHigh].Value = Double.Parse(Fld[ColHigh], NFI.PeriodDecSep);
    Table.Cell[ColLow].Value = Double.Parse(Fld[ColLow], NFI.PeriodDecSep);
    Table.Cell[ColClose].Value = Double.Parse(Fld[ColClose], NFI.PeriodDecSep);
    Table.Cell[ColVolume].Value = Int32.Parse(Fld[ColVolume]);
    StockTable.DrawRow();
    }

StockTable.Close();

  该DrawRow(NewPage)方法具有可选参数Boolean NewPage = false默认值为false如果希望下一行打印在下一页的顶部,请将参数设置为true

  交互功能示例。

// set cell number 6 with web link
BookList.Cell[6].WebLink = WebLinkString;

// another way to set weblink
BookList.Cell[6].AnnotAction = new AnnotWebLink(WebLinkString);

// set cell with document link to chapter 3
BookList.Cell[6].AnnotAction = new AnnotLinkAction("Chapter3");

// play video
PdfDisplayMedia Omega = new PdfDisplayMedia(PdfEmbeddedFile.CreateEmbeddedFile(Document, "Omega.mp4"));
BookList.Cell[6].AnnotAction = new AnnotDisplayMedia(Omega);

// play audio
PdfDisplayMedia RingSound = new PdfDisplayMedia(PdfEmbeddedFile.CreateEmbeddedFile(Document, "Ring01.wav"));
BookList.Cell[6].AnnotAction = new AnnotDisplayMedia(RingSound);

// allow user to save or view embedded file
PdfEmbeddedFile EmbeddedFile = PdfEmbeddedFile.CreateEmbeddedFile(Document, "BookList.txt");
BookList.Cell[6].AnnotAction = new AnnotFileAttachment(EmbeddedFile, FileAttachIcon.NoIcon);

  对于数据表的源代码,更多的例子看看ArticleExample.csTableExample.cs有关类的更多详细信息PdfTable请查看帮助文件。PdfTableCellPdfTableStylePdfTableBorderPdfFileWriter.chm

2.13  播放视频文件

  该PdfFileWriter支持嵌入PDF文档中的视频文件。播放视频文件的完整示例在第7页OtherExample.cs 添加视频文件需要使用三个类。

    首先,您需要将视频文件嵌入到PDF文档中。

    第二,你需要定义如何播放视频。PdfDisplayMedia 类有许多方法来控制视频显示。请参考类的源代码和文档帮助文件。例如:RepeatCountScaleMedia 如果要在浮动窗口中播放视频,您必须使  用SetMediaWindow方法。

    第三,您需要在PDF页面上定义用户必须单击以激活视频的区域。如果要在注释区域可见时激活视频,请使用ActivateActionWhenPageIsVisible

// define annotation rectangle that has the same aspect ratio as the video
PdfRectangle AnnotRect = ImageSizePos.ImageArea(480, 360,
AreaLeft, AreaBottom, AreaRight - AreaLeft, AreaTop - AreaBottom, ContentAlignment.MiddleCenter);

// create display media object
PdfDisplayMedia DisplayMedia = new PdfDisplayMedia(PdfEmbeddedFile.CreateEmbeddedFile(Document, "LooneyTunes.mp4"));

// create annotation object
PdfAnnotation Annotation = Page.AddScreenAction(AnnotRect, DisplayMedia);

// activate the video when the page becomes visible
// Annotation.ActivateActionWhenPageIsVisible(true);

// define X Object to paint the annotation area when the video is not playing
PdfXObject AnnotArea = AnnotationArea(AnnotRect.Width, AnnotRect.Height, Color.Lavender, Color.Indigo, "Click here to play the video");
Annotation.Appearance(AnnotArea);

  浮动窗口视频显示

// create display media object
PdfDisplayMedia DisplayMedia = new PdfDisplayMedia(PdfEmbeddedFile.CreateEmbeddedFile(Document, "Omega.mp4"));

// activate display controls
DisplayMedia.DisplayControls(true);

// repeat video indefinitly
DisplayMedia.RepeatCount(0);

// display in floating window
DisplayMedia.SetMediaWindow(MediaWindow.Floating, 640, 360, WindowPosition.Center,
    WindowTitleBar.TitleBarWithCloseButton, WindowResize.KeepAspectRatio, "Floating Window Example");

Double LineSpacing = ArialNormal.LineSpacing(12.0);
Double TextPosX = PosX + 0.5 * AreaWidth;
Double TextPosY = PosY + 0.5 * AreaHeight + LineSpacing;
Double TextWidth = Contents.DrawText(ArialNormal, 12.0, TextPosX, TextPosY, TextJustify.Center, "Click this text to play video");
TextPosY -= LineSpacing;
Contents.DrawText(ArialNormal, 12.0, TextPosX, TextPosY, TextJustify.Center, "in floating window");

// create annotation object
PdfRectangle AnnotRect = new PdfRectangle(TextPosX - 0.5 * TextWidth, TextPosY - ArialNormal.DescentPlusLeading(12.0),
    TextPosX + 0.5 * TextWidth, TextPosY + ArialNormal.AscentPlusLeading(12.0) + LineSpacing);
Page.AddScreenAction(AnnotRect, DisplayMedia);

 2.14  播放声音文件

  该PdfFileWriter支持嵌入PDF文档中的声音文件。播放声音文件的完整示例在第7页中给出OtherExample.cs嵌入声音文件与视频文件基本相同。唯一明显的区别是没有什么可以显示。

// create embedded media file
PdfDisplayMedia DisplayMedia = new PdfDisplayMedia(PdfEmbeddedFile.CreateEmbeddedFile(Document, "Ring01.wav"));
DisplayMedia.SetMediaWindow(MediaWindow.Hidden);
AnnotDisplayMedia RingSound = new AnnotDisplayMedia(DisplayMedia);

// display text area to activate the sound
Double LineSpacing = ArialNormal.LineSpacing(12.0);
Double TextPosX = PosX + 0.5 * AreaWidth;
Double TextPosY = PosY + 0.5 * AreaHeight + LineSpacing;
Contents.DrawTextWithAnnotation(Page, ArialNormal, 12.0, TextPosX, TextPosY, TextJustify.Center,
  DrawStyle.Normal, Color.Red, "Click this text to play", RingSound);
TextPosY -= LineSpacing;
Contents.DrawTextWithAnnotation(Page, ArialNormal, 12.0, TextPosX, TextPosY, TextJustify.Center,
  DrawStyle.Normal, Color.Red, "Ringing sound", RingSound);

2.15  附加数据文件

  在PdfFileWriter支持PDF文档中嵌入数据文件。嵌入文件的完整示例在第7页中给出OtherExample.cs用户可以保存文件或显示文件。

// create embedded media file
PdfEmbeddedFile EmbeddedFile = PdfEmbeddedFile.CreateEmbeddedFile(Document, "BookList.txt");
AnnotFileAttachment FileIcon = new AnnotFileAttachment(EmbeddedFile, FileAttachIcon.Paperclip);

// display text area to activate the file attachment
Double LineSpacing = ArialNormal.LineSpacing(12.0);
Double TextPosX = PosX + 0.5 * AreaWidth;
Double TextPosY = PosY + 0.5 * AreaHeight + LineSpacing;
Contents.DrawText(ArialNormal, 12.0, TextPosX, TextPosY, TextJustify.Center, "Right click on the paper clip");
TextPosY -= LineSpacing;
Double TextWidth = Contents.DrawText(ArialNormal, 12.0, TextPosX, TextPosY, TextJustify.Center, "to open or save the attached file");

// annotation
Double IconPosX = TextPosX + 0.5 * TextWidth + 0.1;
Double IconPosY = TextPosY;
PdfRectangle AnnotRect = new PdfRectangle(IconPosX, IconPosY, IconPosX + 0.15, IconPosY + 0.4);
Page.AddFileAttachment(AnnotRect, EmbeddedFile, FileAttachIcon.Paperclip);
TextPosY -= 2 * LineSpacing;
AnnotFileAttachment FileText = new AnnotFileAttachment(EmbeddedFile, FileAttachIcon.NoIcon);
Contents.DrawTextWithAnnotation(Page, ArialNormal, 12.0, TextPosX, TextPosY, TextJustify.Center,
  DrawStyle.Underline, Color.Red, "File attachment (right click)", FileText);

2.16  重新排序页面

  在PdfFileWriter追加新的网页页面列表的末尾。如果要将页面从当前位置移动到新位置,请使用以下方法。

Document.MovePage(Int32 SourceIndex, Int32 DestinationIndex);

2.17  PDF文档输出

  PdfFileWriter创建PDF文档。主类PdfDocument构造函数给你两个选择来保存文档。第一种选择是将PDF文件保存到磁盘文件。在这种情况下,你提供了一个文件名。在文件创建结束时调用PdfDocument.CreateFile。

  此方法将PDF写入文件并关闭文件。

// create main class
PdfDocument Document = new PdfDocument(PaperType.Letter, false, UnitOfMeasure.Inch, FileName);

// terminate
Document.CreateFile();

  第二个选择是流。您创建一个流,内存流或文件流,并将该流作为参数传递给PdfDocument构造函数。执行CreateFile方法后,您的流包含PDF文档。根据应用程序,从流中提取文档。您必须在应用程序中关闭流。

// create memory stream
MemoryStream PdfStream = new MemoryStream();

// create main class
PdfDocument Document = new PdfDocument(PaperType.Letter, false, UnitOfMeasure.Inch, PdfStream);

// terminate
Document.CreateFile();

// save the memory stream to a file
FileStream FS = new FileStream(FileName, FileMode.Create);
PdfStream.WriteTo(FS);
PdfStream.Close();
FS.Close();

2.18  文档信息字典

  PDF文档信息字典由PDF阅读器在文档属性的“说明”选项卡中显示。信息包括:标题,作者,主题,关键字,创建的日期和时间,修改的日期和时间,生成文件的应用程序,PDF生成器。

  在应用程序中包含文档信息的步骤如下:

PdfInfo Info = new PdfInfo(Document);
Info.Title("Article Example");
Info.Author("Uzi Granot Granotech Limited");
Info.Keywords("PDF, .NET, C#, Library, Document Creator");
Info.Subject("PDF File Writer C# Class Library (Version 1.15.0)");

  PdfInfo对象被创建,四个额外的字段被添加到词典中。您可以在代码中覆盖所有这些。

// set creation and modify dates
DateTime LocalTime = DateTime.Now;
Info.CreationDate(LocalTime);
Info.ModDate(LocalTime);

// set creator and producer
Info.Creator("PdfFileWriter C# Class Library Version " + PdfDocument.RevisionNumber);
Info.Producer("PdfFileWriter C# Class Library Version " + PdfDocument.RevisionNumber);

2.19  内存控制

  在构建文档时,PDF文件编写器会累积创建PDF文件所需的所有信息。信息保存在内存中,除了图像和嵌入文件。图像和嵌入文件在声明时会自动写入输出文件。对于非常大的文档,使用的内存不断增长。库提供方法(CommitToPdfFile)将内容信息写入输出文件,并调用垃圾收集器释放未使用的内存。GC.Collect方法需要时间来执行。如果执行时间是问题,请GCCollect每几页设置一次参数。换句话说,CommitToPdfFile必须针对每个页面运行,但每几页清理一次。执行提交后,不能添加其他信息。PdfTable 当下一行不能容纳在当前页面的底部时自动启动新页面。PdfTable班有两个成员CommitToPdfFile,并CommitGCCollectFreq同时表被构建以控制内存的使用情况。PdfChart类生成从.NET类图的图像。DrawChart方法PdfContents将执行提交。或者,您可以调用的CommitToPdfFile方法PdfChart

// PdfContents, PdfXObject and PdfTilingPattern
// Commit the contents to output file.
// Once committed, this PdfContents cannot be used.
// The argument is GCCollect
Contents.CommitToPdfFile(true); 

2.20  Windows Presentation Foundation WPF

  绘制WPF图形是一个四个步骤的过程。

  • 步骤1:创建DrawWPFPath对象。输入参数是路径和Y轴方向。
  • 步骤2:可选择通过调用七种SetBrush方法之一或调用UseCurrentBrush方法添加画笔
  • 步骤3:可选择通过调用两种SetPen方法之一或调用UseCurrentPen方法添加笔
  • 步骤4:通过调用绘制图形对象PdfContents.DrawWPFPath

  如果System.Windows.Media引用不可用(即您的应用程序是Windows窗体),则需要向应用程序添加PresentationCoreWindowsBase程序集。

  Example8 OtherExample.cs和Example8f 中给出了使用WPF图形类绘制的编程示例

  如果未定义画笔和笔,则绘制图形将作为剪辑路径。

  下面你会发现更多的细节如何使用DrawWPFPath类WPF应用程序和其他应用程序。

  DrawWPFPath构造函数接受两个参数:路径和Y轴方向。路径是字符串或System.Windows.Media.PathGeometry文本字符串在路径标记语法中定义路径几何类在PathGeometry类中进行了描述当为WPF环境定义路径时,Y轴方向为向下。Y轴适用于PDF环境。

注意世界任何地方的程序员使用除了句点之外的数字小数分隔符。表示路径的文本字符串输入必须完全按照路径标记语法中的定义来构造。具有分数的小数必须使用周期,而不考虑世界区域。如果在x和y值之间使用可选分隔符,它必须是逗号。如果字符串是由另一个应用程序生成的,请确保使用PathGeometry.ToString(System.Globalization.CultureInfo.InvariantCulture)调用PathGeometry ToString。换句话说,Microsoft的PathGeometry.Parse方法将无法读取意大利产生的文本字符串,例如,通过PathGeometry.ToString方法,而不将IFormatProvider设置为InvariantCulture

有三种方法来为WPF应用程序定义画刷。所有这些方法将同时设置画笔不透明度。

  • System.Windows.Media.SolidColorBrush 请参阅SolidColorBrush类
  • System.Windows.Media.LinearGradientBrush请参阅LinearGradientBrush类
  • System.Windows.Media.RadialGradientBrush请参阅RadialGradientBrush类

有五种方法为所有应用程序定义画笔。所有这些方法将同时设置画笔不透明度。

  • 将画笔设置为System.Drawing.Color
  • 将画笔设置为 PdfAxialShading
  • 将画笔设置为 PdfRadialShading
  • 将画笔设置为 PdfTilingPattern
  • 将画笔设置为 UseCurrentBrush

如果你想让DrawWPFPath类将画笔设置为当前选择的画笔,调用UseCurrentBrush方法。

有一种方法为WPF应用程序定义笔。调用SetPen方法与System.Windows.Media.Pen类(请参阅 Pen)。注意,Pen.Brush属性必须是SolidColorBrush笔类包含绘制线所需的所有信息,例如颜色和宽度。

有一种方法为所有应用程序定义笔。调用SetPenSystem.Drawing.Color参数。color参数定义了alpha,红,绿和蓝色分量。要设置其他笔特性,请设置以下任何或全部属性和方法:

  • SetPenWidth
  • DashArray
  • DashPhase
  • LineCap
  • LineJoin
  • MiterLimit

如果您希望DrawWPFPath类将笔设置为当前选择的笔调用UseCurrentPen方法。

一旦DrawWPFPath类设置了绘制路径所需的所有信息,调用PdfContents.DrawWPFPath方法。DrawWPFPath类基于路径边界框和绘制矩形和对齐,计算将输入路径转换为绘图矩形所需的变换矩阵。对齐零(默认值)将拉伸路径以适合绘图区域。所有其他对齐值根据参数枚举值在绘图区域中定位路径。

public void DrawWPFPath(
    DrawWPFPath Path,   // path to be drawn
    double OriginX,     // Drawing rectangle in user units left side
    double OriginY,     // Drawing rectangle in user units bottom side
    double Width,       // Drawing rectangle in user units width
    double Height,      // Drawing rectangle in user units height
                            // path alignment within drawing rectangle
                            // Alignment=0 means the path will be stretched 
                            // in either horizontal or vertical direction
                            // to fit the drawing rectangle
    ContentAlignment Alignment = 0)

2.21  透明度,不透明度,Alpha颜色成分和混合

  默认情况下,PDF成像模型会将对象(形状,线条,文本和图像)不透明地绘制到页面上。每个新对象完全掩盖了它下面的图像。PDF有两种机制来改变这种行为不透明度和混合。图形状态字典具有用于描边(笔)和非描边(刷)操作的不透明度值。完全不透明的不透明度值为1.0,完全透明度为0.0。不透明度值对应于颜色结构的α分量,使得1.0为255,α为0。如果不透明度值为0.5,则在页面上绘制的新对象将是50%透明的。要设置不透明度,请调用SetAlphaStroking线或SetAlphaNonStroking 方法的形状的方法。混合是将页面上的颜色与正在绘制的新项目的颜色组合的过程。要设置一个bland模式调用的SetBlendMode方法PdfContents 参数是BlendMode枚举。有关详细说明,请参阅PDF规格文档的7.2.4混合模式。例如,请参见OtherExample.cs第8页。

2.22  文档链接和命名目标

  文档链接允许PDF文档用户单击链接并跳转到文档的另一部分。添加文档链接分为两部分。目标定义为位置标记。位置标记必须具有唯一的名称,范围(LocalDestNamedDest)和文档位置(页面和位置)。NamedDest 范围可用于文档链接或命名目标或两者。第二部分是链接位置。这两个部分可以按任何顺序定义。他们被绑在一起的名字。名称区分大小写。许多链接可以指向同一位置标记。

  命名目标是PDF文档中的目标。它们使用位置标记以与文档链接相同的方式定义。范围必须设置为NamedDest当诸如Adobe Acrobat的PDF阅读器打开PDF文档时,它可以在查看窗口中显示目标时打开文档。

要嵌入位置标记,调用的AddLocationMarker方法PdfPage注意:名称区分大小写。

// Add location marker to the document (PdfPage method)
public void AddLocationMarker
  (
  string          LocMarkerName, // unique destination name (case sensitive)
  LocMarkerScope  Scope,         // eigther LocalDest or NamedDest
  DestFit         FitArg,        // fit argument (see below)
  params double[] SideArg        // 0, 1 or 4 side dimension argument (see below)
  )

  添加链接位置调用PdfPage的AddLinkLocation方法。

public PdfAnnotation AddLinkAction
  (
  string LocMarkerName,    // location marker name
  PdfRectangle AnnotRect   // rectangle area on the page to activate the jump
  )

  有关命名目的地的详细信息,请参阅Adobe PDF文件规范“PDF参考,第六版,Adobe便携式文档格式版本1.7,2006年11月”第582页的表8.2。

  • DestFit.Fit (无参数):显示页面,其内容放大刚好足以适合水平和垂直窗口内的整个页面。
  • DestFit.FitH (1 arg Top):显示页面,垂直坐标顶部位于窗口的顶部边缘,并且页面的内容放大刚好足以适合窗口内页面的整个宽度。
  • DestFit.FitV (1 arg Left):显示页面,水平坐标左边位于窗口的左边缘,页面的内容放大刚好足以适合窗口内页面的整个高度。
  • DestFit.FitR (4 args Left Bottom Right Top):显示页面,其内容被放大,刚好足以适合由水平和垂直方向的窗口内的左,右,底和坐标指定的矩形。
  • DestFit.FitB (无参数):显示页面,其内容放大刚刚足以适合水平和垂直的窗口内的整个边界框。
  • DestFit.FitBH (1 arg Top):显示页面,垂直坐标顶部位于窗口的顶部边缘,页面的内容放大刚好足以适合窗口内边界框的整个宽度。
  • DestFit.FitBV (1 arg Left):显示页面,水平坐标左边位于窗口的左边缘,页面的内容放大刚好足以适合窗口内其边界框的整个高度。

  PDF阅读器的调用参数在Adobe的“打开PDF文件的参数”中定义如果PDF在台式计算机上打开,呼叫线路必须是:

  “path \ AcroRd32.exe”/ A“nameddest = ChapterXX”“path \ Document.pdf”

  如果PDF文档由网页中的链接指向,则目标将附加到链接:

  <a href="http://example.org/Document.pdf#ChapterXX">目标说明</a>

  或者:<a href="http://example.org/Document.pdf#namedsest=ChapterXX">目标说明</a>

2.23  安装

  集成PdfFileWriter到您的应用程序需要以下步骤。PdfFileWriter.dll在开发区域中安装附加文件。启动Visual C#程序并打开您的应用程序。转到解决方案资源管理器,右键单击引用,然后选择添加引用。

  选择“浏览”选项卡,并将文件系统导航到的位置PdfFileWriter.dll当您的应用程序发布时,必须包含代码> PdfFileWriter.dll。

  源代码文档作为帮助文件提供PdfFileWriter.chm 该文件由Sandcastle生成。结果看起来像Microsoft文档页。

  如果要访问PdfFileWriter项目的源代码,请PdfFileWriter在开发区域中安装项目。PdfFileWriter.dll会在PdfFileWriter\bin\Release目录中。

  使用此库将以下语句添加到所有源模块。

  using PdfFileWriter;

如果您打算使用图表,您需要添加引用:System.Windows.Forms.Visualization在每个源模块使用Chart你需要添加

  using System.Windows.Forms.DataVisualization.Charting; 

3  实例开发指南

  本节介绍PDF文件编写器C#类库到您的应用程序的集成。测试程序TestPdfFileWriter程序是对自己的应用程序的模拟。当按下“文章示例”按钮时,程序将执行ArticleExample.cs源文件中的代码上图显示了生成的PDF文件。此方法演示了如何创建一个包含一些文本和图形的页面文档。通过这个例子,你应该有一个很好的了解的过程。其他示例按钮生成各种PDF文档。总的来说,实际上这个库的每个特征都通过这些实施例来证明。

  调试复选框(如果选中)将创建一个PDF文件,可以使用文本编辑器查看,但无法加载到PDF阅读器。生成的文件未压缩,图像和字体文件将替换为文本占位符。调试复选框应仅用于调试。

  TestPdfFileWriter程序是使用Microsoft Visual C#2012开发的。它已针对Windows XP,Vista,7和8进行了测试。

 

* 3.1  文档创建概述

  下面的测试方法演示了创建PDF文件的介绍中描述的六个步骤。当您按下演示程序的“文章示例”按钮时,将执行该方法。以下小节详细描述每个步骤。

 

/// Create “article example” test PDF document
public void Test(Boolean Debug, String FileName)
{
// Step 1: Create empty document
// Arguments: page width: 8.5”, page height: 11”, Unit of measure: inches
// Return value: PdfDocument main class
Document = new PdfDocument(PaperType.Letter, false, UnitOfMeasure.Inch, FileName);

// for encryption test
// Document.SetEncryption(Permission.All & ~Permission.Print);

// Debug property
// By default it is set to false. Use it for debugging only.
// If this flag is set, PDF objects will not be compressed, font and images will be replaced
// by text place holder. You can view the file with a text editor but you cannot open it with PDF reader.
Document.Debug = Debug;

// Step 2: create resources
// define font resources
DefineFontResources();

// define tiling pattern resources
DefineTilingPatternResource();

// Step 3: Add new page
Page = new PdfPage(Document);

// Step 4:Add contents to page
Contents = new PdfContents(Page);

// Step 5: add graphics and text contents to the contents object
DrawFrameAndBackgroundWaterMark();
DrawTwoLinesOfHeading();
DrawHappyFace();
DrawBarcode();
DrawBrickPattern();
DrawImage();
DrawHeart();
DrawChart();
DrawTextBox();
DrawBookOrderForm();

// Step 6: create pdf file
// argument: PDF file name
Document.CreateFile();

// start default PDF reader and display the file
Process Proc = new Process();
Proc.StartInfo = new ProcessStartInfo(FileName);
Proc.Start();

// exit
return;
}

3.2  字体资源

  该DefineFontResources方法创建此示例中使用的所有字体资源。要查看可用于任何字体的所有字符,请按“字体家庭”按钮。选择一个族并查看为每个字符定义的字形。要查看单个字形按下视图或双击。

 

// Define Font Resources
private void DefineFontResources()
{
// Define font resources
// Arguments: PdfDocument class, font family name, font style, embed flag
// Font style (must be: Regular, Bold, Italic or Bold | Italic) All other styles are invalid.
// Embed font. If true, the font file will be embedded in the PDF file.
// If false, the font will not be embedded
String FontName1 = "Arial";
String FontName2 = "Times New Roman";

ArialNormal = PdfFont.CreatePdfFont(Document, FontName1, FontStyle.Regular, true);
ArialBold = PdfFont.CreatePdfFont(Document, FontName1, FontStyle.Bold, true);
ArialItalic = PdfFont.CreatePdfFont(Document, FontName1, FontStyle.Italic, true);
ArialBoldItalic = PdfFont.CreatePdfFont(Document, FontName1, FontStyle.Bold | FontStyle.Italic, true);
TimesNormal = PdfFont.CreatePdfFont(Document, FontName2, FontStyle.Regular, true);
Comic = PdfFont.CreatePdfFont(Document, "Comic Sans MS", FontStyle.Bold, true);
return;
}

3.3  平铺模式资源

  该DefineTilingPatternResource方法为示例区域定义背景图案资源。模式是在浅蓝色背景白色的单词“PdfFileWriter”。该模式由两行重复关键字组成。这两条线偏移半字长度。

  如果你想找到有趣的模式,在互联网上搜索公司的目录制作floor或wall tiles

//// Define Tiling Pattern Resource
private void DefineTilingPatternResource()
{
// create empty tiling pattern
WaterMark = new PdfTilingPattern(Document);

// the pattern will be PdfFileWriter layed out in brick pattern
String Mark = "PdfFileWriter";

// text width and height for Arial bold size 18 points
Double FontSize = 18.0;
Double TextWidth = ArialBold.TextWidth(FontSize, Mark);
Double TextHeight = ArialBold.LineSpacing(FontSize);

// text base line
Double BaseLine = ArialBold.DescentPlusLeading(FontSize);

// the overall pattern box (we add text height value as left and right text margin)
Double BoxWidth = TextWidth + 2 * TextHeight;
Double BoxHeight = 4 * TextHeight;
WaterMark.SetTileBox(BoxWidth, BoxHeight);

// save graphics state
WaterMark.SaveGraphicsState();

// fill the pattern box with background light blue color
WaterMark.SetColorNonStroking(Color.FromArgb(230, 244, 255));
WaterMark.DrawRectangle(0, 0, BoxWidth, BoxHeight, PaintOp.Fill);

// set fill color for water mark text to white
WaterMark.SetColorNonStroking(Color.White);

// draw PdfFileWriter at the bottom center of the box
WaterMark.DrawText(ArialBold, FontSize, BoxWidth / 2, BaseLine, TextJustify.Center, Mark);

// adjust base line upward by half height
BaseLine += BoxHeight / 2;

// draw the right half of PdfFileWriter shifted left by half width
WaterMark.DrawText(ArialBold, FontSize, 0.0, BaseLine, TextJustify.Center, Mark);

// draw the left half of PdfFileWriter shifted right by half width
WaterMark.DrawText(ArialBold, FontSize, BoxWidth, BaseLine, TextJustify.Center, Mark);

// restore graphics state
WaterMark.RestoreGraphicsState();
return;}

3.4  画与背景样式的框架

  该DrawFrameAndBackgroundWaterMark方法在具有背景水印图案的示例区域周围绘制框架。模式资源在前面的小节中定义。

 

// Draw frame around example area
private void DrawFrameAndBackgroundWaterMark()
{
// save graphics state
Contents.SaveGraphicsState();

// Draw frame around the page
// Set line width to 0.02"
Contents.SetLineWidth(0.02);

// set frame color dark blue
Contents.SetColorStroking(Color.DarkBlue);

// use water mark tiling pattern to fill the frame
Contents.SetPatternNonStroking(WaterMark);

// rectangle position: x=1.0", y=1.0", width=6.5", height=9.0"
Contents.DrawRectangle(1.0, 1.0, 6.5, 9.0, PaintOp.CloseFillStroke);

// restore graphics sate
Contents.RestoreGraphicsState();

// draw article name under the frame
// Note: the \u00a4 is character 164 that was substituted during Font resource definition
// this character is a solid circle it is normally unicode 9679 or \u25cf in the Arial family
Contents.DrawText(ArialNormal, 9.0, 1.1, 0.85, "PdfFileWriter \u25cf PDF File Writer C# Class Library \u25cf Author: Uzi Granot");

// draw web link to the article
Contents.DrawWebLink(Page, ArialNormal, 9.0, 7.4, 0.85, TextJustify.Right, DrawStyle.Underline, Color.Blue, "Click to view article",
    "http://www.codeproject.com/Articles/570682/PDF-File-Writer-Csharp-Class-Library-Version");
return;
}

3.5  画两条标题

// Draw heading
private void DrawTwoLinesOfHeading()
{
// page heading
// Arguments: Font: ArialBold, size: 36 points, Position: X = 4.25", Y = 9.5"
// Text Justify: Center (text center will be at X position)
// Stoking color: R=128, G=0, B=255 (text outline)
// Nonstroking color: R=255, G=0, B=128 (text body)
Contents.DrawText(Comic, 40.0, 4.25, 9.25, TextJustify.Center, 0.02, Color.FromArgb(128, 0, 255), Color.FromArgb(255, 0, 128), "PDF FILE WRITER");

// save graphics state
Contents.SaveGraphicsState();

// change nonstroking (fill) color to purple
Contents.SetColorNonStroking(Color.Purple);

// Draw second line of heading text
// arguments: Handwriting font, Font size 30 point, Position X=4.25", Y=9.0"
// Text Justify: Center (text center will be at X position)
Contents.DrawText(Comic, 30.0, 4.25, 8.75, TextJustify.Center, "Example");

// restore graphics sate (non stroking color will be restored to default)
Contents.RestoreGraphicsState();
return;
}

3.6  画愉快的面孔

  该DrawHappyFace方法是从线和贝塞尔曲线绘制椭圆和构造路径的示例。

 

// Draw Happy Face
private void DrawHappyFace()
{
// save graphics state
Contents.SaveGraphicsState();

// translate coordinate origin to the center of the happy face
Contents.Translate(4.25, 7.5);

// change nonstroking (fill) color to yellow
Contents.SetColorNonStroking(Color.Yellow);

// draw happy face yellow oval
Contents.DrawOval(-1.5, -1.0, 3.0, 2.0, PaintOp.Fill);

// set line width to 0.2" this is the black circle around the eye
Contents.SetLineWidth(0.2);

// eye color is white with black outline circle
Contents.SetColorNonStroking(Color.White);
Contents.SetColorStroking(Color.Black);

// draw eyes
Contents.DrawOval(-0.75, 0.0, 0.5, 0.5, PaintOp.CloseFillStroke);
Contents.DrawOval(0.25, 0.0, 0.5, 0.5, PaintOp.CloseFillStroke);

// mouth color is black
Contents.SetColorNonStroking(Color.Black);

// draw mouth by creating a path made of one line and one Bezier curve 
Contents.MoveTo(-0.6, -0.4);
Contents.LineTo(0.6, -0.4);
Contents.DrawBezier(0.0, -0.8, 0, -0.8, -0.6, -0.4);

// fill the path with black color
Contents.SetPaintOp(PaintOp.Fill);

// restore graphics sate
Contents.RestoreGraphicsState();
return;
}

3.7  绘制条形码

  该DrawBarcode方法是绘制两个条形码EAN-13和Code-128的示例

  该DrawTwoLinesOfHeading方法在页面中心绘制两个标题线。第一行是用大纲特殊效果绘制文本。

// Draw Barcode
private void DrawBarcode()
{
// save graphics state
Contents.SaveGraphicsState();

BarcodeEAN13 Barcode1 = new BarcodeEAN13("1234567890128");
Contents.DrawBarcode(1.3, 7.05, 0.012, 0.75, Barcode1, ArialNormal, 8.0);

PdfQRCode QRCode = new PdfQRCode(Document, "http://www.codeproject.com/Articles/570682/PDF-File-Writer-Csharp-Class-Library-Version", ErrorCorrection.M);
Contents.DrawQRCode(QRCode, 6.0, 6.8, 1.2);

// define a web link area coinciding with the qr code
Page.AddWebLink(6.0, 6.8, 7.2, 8.0, "http://www.codeproject.com/Articles/570682/PDF-File-Writer-Csharp-Class-Library-Version");

// restore graphics sate
Contents.RestoreGraphicsState();
return;
}

3.8  绘制与圆角的矩形和填充砖模式

  该DrawBrickPattern方法绘制具有圆角的矩形。该区域填充有砖图案。PdfTillingPattern类是一般类定义划分模式。该类有两个静态方法来创建特定模式。

  SetBrickPattern绘制砖墙图案并SetWeavePattern绘制织造图案。

 

// Draw rectangle with rounded corners and filled with brick pattern
private void DrawBrickPattern()
{
// Define brick tilling pattern resource
// Arguments: PdfDocument class, Scale factor (0.25), Stroking color (lines between bricks), Nonstroking color (brick)
// Return value: tilling pattern resource
PdfTilingPattern BrickPattern = PdfTilingPattern.SetBrickPattern(Document, 0.25, Color.LightYellow, Color.SandyBrown);

// save graphics state
Contents.SaveGraphicsState();

// set outline width 0.04"
Contents.SetLineWidth(0.04);

// set outline color to purple
Contents.SetColorStroking(Color.Purple);

// set fill pattern to brick
Contents.SetPatternNonStroking(BrickPattern);

// draw rounded rectangle filled with brick pattern
Contents.DrawRoundedRectangle(1.1, 5.0, 1.4, 1.5, 0.2, PaintOp.CloseFillStroke);

// restore graphics sate
Contents.RestoreGraphicsState();
return;
}

3.9  绘制图像并剪切它

  在Draw法师方法是绘制一图象的一个例子。PdfFileWriter存储在支持的所有图像文件的支持图纸图片Bitmap类和Metafile类。ImageFormat类定义所有图像类型。JPEG图像文件类型是PDF文件的本机图像格式。如果PdfImage使用JPEG文件调用构造函数,程序将该文件按原样复制到PDF文件中。如果你调用PdfImage任何其他类型的图像文件构造函数,程序将其转换为JPEG文件。为了保持PDF文件的大小尽可能小,确保您的图像文件分辨率不是不合理的高。

  在PdfImage类加载图像和计算可以适合用户坐标给定的图像大小和保留原始宽高比最大尺寸。在绘制图像之前,我们创建一个椭圆形剪切路径以剪切图像。

// Draw image and clip it
private void DrawImage()
{
// define local image resources
// resolution 96 pixels per inch, image quality 50%
PdfImage Image1 = new PdfImage(Document, "TestImage.jpg", 96.0, 50);

// save graphics state
Contents.SaveGraphicsState();

// translate coordinate origin to the center of the picture
Contents.Translate(2.6, 5.0);

// adjust image size and preserve aspect ratio
ImageSizePos NewSize = Image1.ImageSizePosition(1.75, 1.5, ContentAlignment.MiddleCenter);

// clipping path
Contents.DrawOval(NewSize.DeltaX, NewSize.DeltaY, NewSize.Width, NewSize.Height, PaintOp.ClipPathEor);

// draw image
Contents.DrawImage(Image1, NewSize.DeltaX, NewSize.DeltaY, NewSize.Width, NewSize.Height);

// restore graphics state
Contents.RestoreGraphicsState();
return;
}

3.10  绘制心

  该DrawHeart方法通过定义中心线的两端来显示心形。DrawHeart方法PdfContents是绘制形成路径的两个对称贝塞尔曲线的特殊情况。

// Draw heart
private void DrawHeart()
{
// save graphics state
Contents.SaveGraphicsState();

// draw heart
// The first argument are the coordinates of the centerline of the heart shape.
// The DrawHeart is a special case of DrawDoubleBezierPath method.
Contents.SetColorNonStroking(Color.HotPink);
Contents.DrawHeart(new LineD(new PointD(4.98, 5.1), new PointD(4.98, 6.0)), PaintOp.CloseFillStroke);

// restore graphics state
Contents.RestoreGraphicsState();
return;
}

3.11  绘制饼图

  该DrawChart方法是定义图表并将其绘制到PDF文档的示例。

/ Draw pie chart
private void DrawChart()
{
// save graphics state
Contents.SaveGraphicsState();

// create chart
Chart PieChart = PdfChart.CreateChart(Document, 1.8, 1.5, 300.0);

// create PdfChart object with Chart object
PdfChart PiePdfChart = new PdfChart(Document, PieChart);

// make sure we have good quality image
PieChart.AntiAliasing = AntiAliasingStyles.All;

// set colors
PieChart.BackColor = Color.FromArgb(220, 220, 255);
PieChart.Palette = ChartColorPalette.BrightPastel;

// default font
Font DefaultFont = MyPdfChart.CreateFont("Verdana", FontStyle.Regular, 0.05, FontSizeUnit.UserUnit);
Font TitleFont = MyPdfChart.CreateFont("Verdana", FontStyle.Bold, 0.07, FontSizeUnit.UserUnit);

// title (font size is 0.25 inches)
Title Title1 = new Title("Pie Chart Example", Docking.Top, TitleFont, Color.Purple);
PieChart.Titles.Add(Title1);

// legend
Legend Legend1 = new Legend();
PieChart.Legends.Add(Legend1);
Legend1.BackColor = Color.FromArgb(230, 230, 255);
Legend1.Docking = Docking.Bottom;
Legend1.Font = DefaultFont;

// chart area
ChartArea ChartArea1 = new ChartArea();
PieChart.ChartAreas.Add(ChartArea1);

// chart area background color
ChartArea1.BackColor = Color.FromArgb(255, 200, 255);

// series 1
Series Series1 = new Series();
PieChart.Series.Add(Series1);
Series1.ChartType = SeriesChartType.Pie;
Series1.Font = DefaultFont;
Series1.IsValueShownAsLabel = true;
Series1.LabelFormat = "{0} %";

// series values
Series1.Points.Add(22.0);
Series1.Points[0].LegendText = "Apple";
Series1.Points.Add(27.0);
Series1.Points[1].LegendText = "Banana";
Series1.Points.Add(33.0);
Series1.Points[2].LegendText = "Orange";
Series1.Points.Add(18.0);
Series1.Points[3].LegendText = "Grape";

Contents.DrawChart(MyPdfChart, 5.6, 5.0);

// restore graphics state
Contents.RestoreGraphicsState();
return;
}

3.12  绘制文本框

DrawTextBox方法是使用TextBox的示例TextBox类格式文本,以适应列中。可以使用字体的样式和大小的真实性来绘制文本。

// Draw example of a text box
private void DrawTextBox()
{
// save graphics state
Contents.SaveGraphicsState();

// translate origin to PosX=1.1" and PosY=1.1" this is the bottom left corner of the text box example
Contents.Translate(1.1, 1.1);

// Define constants
// Box width 3.25"
// Box height is 3.65"
// Normal font size is 9.0 points.
const Double Width = 3.15;
const Double Height = 3.65;
const Double FontSize = 9.0;

// Create text box object width 3.25"
// First line indent of 0.25"
TextBox Box = new TextBox(Width, 0.25);

// add text to the text box
Box.AddText(ArialNormal, FontSize,
    "This area is an example of displaying text that is too long to fit within a fixed width " +
    "area. The text is displayed justified to right edge. You define a text box with the required " +
    "width and first line indent. You add text to this box. The box will divide the text into " + 
    "lines. Each line is made of segments of text. For each segment, you define font, font " +
    "size, drawing style and color. After loading all the text, the program will draw the formatted text.\n");
Box.AddText(TimesNormal, FontSize + 1.0, "Example of multiple fonts: Times New Roman, ");
Box.AddText(Comic, FontSize, "Comic Sans MS, ");
Box.AddText(ArialNormal, FontSize, "Example of regular, ");
Box.AddText(ArialBold, FontSize, "bold, ");
Box.AddText(ArialItalic, FontSize, "italic, ");
Box.AddText(ArialBoldItalic, FontSize, "bold plus italic. ");
Box.AddText(ArialNormal, FontSize - 2.0, "Arial size 7, ");
Box.AddText(ArialNormal, FontSize - 1.0, "size 8, ");
Box.AddText(ArialNormal, FontSize, "size 9, ");
Box.AddText(ArialNormal, FontSize + 1.0, "size 10. ");
Box.AddText(ArialNormal, FontSize, DrawStyle.Underline, "Underline, ");
Box.AddText(ArialNormal, FontSize, DrawStyle.Strikeout, "Strikeout. ");
Box.AddText(ArialNormal, FontSize, "Subscript H");
Box.AddText(ArialNormal, FontSize, DrawStyle.Subscript, "2");
Box.AddText(ArialNormal, FontSize, "O. Superscript A");
Box.AddText(ArialNormal, FontSize, DrawStyle.Superscript, "2");
Box.AddText(ArialNormal, FontSize, "+B");
Box.AddText(ArialNormal, FontSize, DrawStyle.Superscript, "2");
Box.AddText(ArialNormal, FontSize, "=C");
Box.AddText(ArialNormal, FontSize, DrawStyle.Superscript, "2");
Box.AddText(ArialNormal, FontSize, "\n");
Box.AddText(Comic, FontSize, Color.Red, "Some color, ");
Box.AddText(Comic, FontSize, Color.Green, "green, ");
Box.AddText(Comic, FontSize, Color.Blue, "blue, ");
Box.AddText(Comic, FontSize, Color.Orange, "orange, ");
Box.AddText(Comic, FontSize, DrawStyle.Underline, Color.Purple, "and purple.\n");
Box.AddText(ArialNormal, FontSize, "Support for non-Latin letters: ");
Box.AddText(ArialNormal, FontSize, Contents.ReverseString( "עברית"));
Box.AddText(ArialNormal, FontSize, "АБВГДЕ");
Box.AddText(ArialNormal, FontSize, "αβγδεζ");

Box.AddText(ArialNormal, FontSize, "\n");

// Draw the text box
// Text left edge is at zero (note: origin was translated to 1.1") 
// The top text base line is at Height less first line ascent.
// Text drawing is limited to vertical coordinate of zero.
// First line to be drawn is line zero.
// After each line add extra 0.015".
// After each paragraph add extra 0.05"
// Stretch all lines to make smooth right edge at box width of 3.15"
// After all lines are drawn, PosY will be set to the next text line after the box's last paragraph
Double PosY = Height;
Contents.DrawText(0.0, ref PosY, 0.0, 0, 0.015, 0.05, TextBoxJustify.FitToWidth, Box);

// Create text box object width 3.25"
// No first line indent
Box = new TextBox(Width);

// Add text as before.
// No extra line spacing.
// No right edge adjustment
Box.AddText(ArialNormal, FontSize,
    "In the examples above this area the text box was set for first line indent of " +
    "0.25 inches. This paragraph has zero first line indent and no right justify.");
Contents.DrawText(0.0, ref PosY, 0.0, 0, 0.01, 0.05, TextBoxJustify.Left, Box);

// Create text box object width 2.75
// First line hanging indent of 0.5"
Box = new TextBox(Width - 0.5, -0.5);

// Add text
Box.AddText(ArialNormal, FontSize,
    "This paragraph is set to first line hanging indent of 0.5 inches. " +
    "The left margin of this paragraph is 0.5 inches.");

// Draw the text
// left edge at 0.5"
Contents.DrawText(0.5, ref PosY, 0.0, 0, 0.01, 0.05, TextBoxJustify.Left, Box);

// restore graphics state
Contents.RestoreGraphicsState();
return;
}

3.13  绘制订单表格

  该DrawBookOrderForm方法是订单输入表单或发票的示例。它是数据表支持的一个示例。它演示使用的PdfTablePdfTableCell以及PdfTableStyle类。

// Draw example of order form
private void DrawBookOrderForm()
{
// Define constants to make the code readable
const Double Left = 4.35;
const Double Top = 4.65;
const Double Bottom = 1.1;
const Double Right = 7.4;
const Double FontSize = 9.0;
const Double MarginHor = 0.04;
const Double MarginVer = 0.04;
const Double Border = 0.015;
const Double Grid = 0.01;

// column widths
Double ColWidthPrice = ArialNormal.TextWidth(FontSize, "9999.99") + 2.0 * MarginHor;
Double ColWidthQty = ArialNormal.TextWidth(FontSize, "Qty") + 2.0 * MarginHor;
Double ColWidthDesc = Right - Left - Border - 3 * Grid - 2 * ColWidthPrice - ColWidthQty;

// define table
PdfTable Table = new PdfTable(Page, Contents, ArialNormal, FontSize);
Table.TableArea = new PdfRectangle(Left, Bottom, Right, Top);
Table.SetColumnWidth(new Double[] {ColWidthDesc, ColWidthPrice, ColWidthQty, ColWidthPrice});

// define all borders
Table.Borders.SetAllBorders(FrameWidth, GridWidth);

// margin
PdfRectangle Margin = new PdfRectangle(MarginHor, MarginVer);

// default header style
Table.DefaultHeaderStyle.Margin = Margin;
Table.DefaultHeaderStyle.BackgroundColor = Color.FromArgb(255, 196, 255);
Table.DefaultHeaderStyle.Alignment = ContentAlignment.MiddleRight;

// private header style for description
Table.Header[0].Style = Table.HeaderStyle;
Table.Header[0].Style.Alignment = ContentAlignment.MiddleLeft;

// table heading
Table.Header[0].Value = "Description";
Table.Header[1].Value = "Price";
Table.Header[2].Value = "Qty";
Table.Header[3].Value = "Total";

// default style
Table.DefaultCellStyle.Margin = Margin;

// description column style
Table.Cell[0].Style = Table.CellStyle;
Table.Cell[0].Style.MultiLineText = true;

// qty column style
Table.Cell[2].Style = Table.CellStyle;
Table.Cell[2].Style.Alignment = ContentAlignment.BottomRight;

Table.DefaultCellStyle.Format = "#,##0.00";
Table.DefaultCellStyle.Alignment = ContentAlignment.BottomRight;

Contents.DrawText(ArialBold, FontSize, 0.5 * (Left + Right), Top + MarginVer + Table.DefaultCellStyle.FontDescent,
    TextJustify.Center, DrawStyle.Normal, Color.Purple, "Example of PdfTable support (new for 1.10.0)");

// reset order total
Double Total = 0;

// loop for all items in the order
// Order class is a atabase simulation for this example
foreach(Order Book in Order.OrderList)
    {
    Table.Cell[0].Value = Book.Title + ". By: " + Book.Authors;
    Table.Cell[1].Value = Book.Price;
    Table.Cell[2].Value = Book.Qty;
    Table.Cell[3].Value = Book.Total;
    Table.DrawRow();

    // accumulate total
    Total += Book.Total;
    }
Table.Close();

// save graphics state
Contents.SaveGraphicsState();

// form line width 0.01"
Contents.SetLineWidth(FrameWidth);
Contents.SetLineCap(PdfLineCap.Square);

// draw total before tax
Double[] ColumnPosition = Table.ColumnPosition;
Double TotalDesc = ColumnPosition[3] - MarginHor;
Double TotalValue = ColumnPosition[4] - MarginHor;
Double PosY = Table.RowTopPosition - 2.0 * MarginVer - Table.DefaultCellStyle.FontAscent;
Contents.DrawText(ArialNormal, FontSize, TotalDesc, PosY, TextJustify.Right, "Total before tax");
Contents.DrawText(ArialNormal, FontSize, TotalValue, PosY, TextJustify.Right, Total.ToString("#.00"));

// draw tax (Ontario Canada HST)
PosY -= Table.DefaultCellStyle.FontLineSpacing;
Contents.DrawText(ArialNormal, FontSize, TotalDesc, PosY, TextJustify.Right, "Tax (13%)");
Double Tax = Math.Round(0.13 * Total, 2, MidpointRounding.AwayFromZero);
Contents.DrawText(ArialNormal, FontSize, TotalValue, PosY, TextJustify.Right, Tax.ToString("#.00"));

// draw total line
PosY -= Table.DefaultCellStyle.FontDescent + 0.5 * MarginVer;
Contents.DrawLine(ColumnPosition[3], PosY, ColumnPosition[4], PosY);

// draw final total
PosY -= Table.DefaultCellStyle.FontAscent + 0.5 * MarginVer;
Contents.DrawText(ArialNormal, FontSize, TotalDesc, PosY, TextJustify.Right, "Total payable");
Total += Tax;
Contents.DrawText(ArialNormal, FontSize, TotalValue, PosY, TextJustify.Right, Total.ToString("#.00"));

PosY -= Table.DefaultCellStyle.FontDescent + MarginVer;
Contents.DrawLine(ColumnPosition[0], Table.RowTopPosition, ColumnPosition[0], PosY);
Contents.DrawLine(ColumnPosition[0], PosY, ColumnPosition[4], PosY);
Contents.DrawLine(ColumnPosition[4], Table.RowTopPosition, ColumnPosition[4], PosY);

// restore graphics state
Contents.RestoreGraphicsState();
return;
}

4.  参考文献

  • Adobe PDF文件规范文档可从Adobe网站获得:“PDF参考,第六版,Adobe便携式文档格式版本1.7,2006年11月”
  • 有关OpenType字体规范的信息可以在Microsoft Typography - OpenType Specification找到
  • “PDF文件分析器与C#解析类”一文中提供了与PDF Deflate压缩类匹配的解压缩类的源
  • 压缩和解压缩类的原始源代码取自Uzi Granot在CodeProject.com网站上发表的“使用C#压缩/解压缩类处理标准ZIP文件”一文。

5.  其他开源软件由这个作者

  • Android Color Selector for Programmers是Google Play上的免费应用程式。
  • Google Play应用内结算演示应用本文是Google Play应用内结算版本3的一个示例。

6.  历史

  • 2013/04/01:版本1.0原始版本。
  • 2013/04/09:版本1.1支持除句点之外的小数分隔符的国家/地区。
  • 2013/07/21:版本1.2原始版本支持的图像资源只有jpeg文件格式。版本1.2支持Bitmap类可接受的所有图像文件。请参阅ImageFormat类。程序测试与:Bmp,Gif,图标,Jpeg,Png和Tiff。参见上面的2.3节和3.8节。
  • 2014/02/07:版本1.3修正PdfContents.DrawBezierNoP2(PointD P1,PointD P3)的错误。
  • 2014/03/01:1.4版改进了对字符替换的支持。改进对图像包含的支持。一些修复与PdfXObject相关。
  • 2014/05/05:版本1.5不使用字体的条形码支持。包括四个条形码:Code-128,Code-39,UPC-A和EAN-13。参见第2.5节和第3.7节。
  • 2014/07/09:版本1.6(1)创建文件后,CreateFile方法将PdfDocument重置为初始条件。(2)PdfFont对象正确地释放非托管代码资源。
  • 2014/08/25:版本1.7支持文档加密,网络链接和QR码。
  • 2014/09/12:版本1.8支持书签。
  • 2014/10/06:版本1.9支持制图,PrintDocument和图像元文件。
  • 2014/10/12:版本1.9.1修正为ChartExample。解析除句点之外的具有小数分隔符的区域中的数字字段。
  • 2014/12/02:1.10.0版本支持数据表。添加源代码文档。增加每个文档的最大图像数量。
  • 2015/01/12:版本1.11.0支持视频,声音和附件文件。添加对Interleave 2 of 5条码的支持。
  • 2015/04/13:版本1.12.0支持重新排序页面和增强数据表边框线支持。
  • 2015/05/05:1.13.0版本PDF文档输出到流。PDF表插入分页符。图像质量增强。支持标准128(RC4)加密。
  • 2015/06/08:1.14.0版支持PDF表中的长文本块或TextBox。
  • 2015/06/09:版本1.14.1一行改为PdfTableStyle类的复制方法。
  • 2015/06/17:版本1.15.0文档信息字典。PdfImage重写。其他图像保存选项。
  • 2015/06/18:版本1.15.1从解决方案资源管理器中删除未使用的源。
  • 2015/07/27:版本1.16.0 Unicode支持。提交页面方法。
  • 2015/08/07:版本1.16.1。修正小(<0.0001)实数转换为字符串。
  • 2015/09/01:版本1.16.2。修复未定义的字符。所选字体不支持使用的字符。 
  • 2015/09/22:版本1.16.3。PdfTable构造函数使用当前页面大小来计算默认表区域矩形。当PdfTable启动新页面时,从上一页获取页面类型和方向。
  • 2015/09/30:Version 1.16.4一致使用IDisposable接口释放非托管资源。
  • 2016/01/26:版本1.17.0 WPF图形,透明度,颜色混合,椭圆弧和二次贝塞尔曲线。
  • 2016/02/29:Version 1.17.1当第一列标题是TextBox时,PdfTable将正确显示标题。
  • 2016/03/22:版本1.17.2 PdfInfo PDF文档属性将正确显示。
  • 2016/04/14:版本1.17.3修正了将非整数字体大小在将小数分隔符定义为非句点(逗号)的区域中的问题。
  • 2016/05/24:版本1.18.0命名目的地和PdfFont资源的创建。
  • 2016/06/02:版本1.18.1重新申请1.17.3修复。
  • 2016/06/13:版本1.19.0文档链接。命名目标的更改。交互功能支持TextBox和PdfTable。
  • 2016/07/27:版本1.19.1 Fix:AddLocationMarker修复了具有小数分隔符而不是句点的区域。 

7.  执照

  本文以及任何相关的源代码和文件均已获得代码项目开放许可证(CPOL)许可

8.  关于原作者

  加拿大 Uzi格兰诺   格兰 科技有限公司

 

该文由小居工作室原创(QQ:2482052910) 翻译并提供解答支持,原文地址:Pdf File Writer 中文应用(PDF文件编写器C#类库):http://www.cnblogs.com/wjs5943283/p/6528853.html

 

 

posted @ 2017-03-10 12:49  小居工作室  阅读(4448)  评论(4编辑  收藏  举报