VisualSignature.vb
'' 完毕:
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Pdf.AcroForms
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing
Imports System.Security.Cryptography.X509Certificates

'' 此示例演示了如何使用 .pfx 文件创建 PDF 并对其进行签名,
'' 使用 SignatureField 和签名图像。
'' 然后,该示例将签名的文件加载回另一个 GcPdfDocument 实例
'' 并验证签名。
'' 这个示例与 SignDoc 相同,但添加了代表签名的图像。
Public Class VisualSignature
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim page = doc.NewPage()
        Dim tf = New TextFormat() With {.Font = StandardFonts.Times, .FontSize = 14}
        page.Graphics.DrawString("你好世界!" +
            "下面由 DsPdfWeb VisualSignature 示例签名。",
            tf, New PointF(72, 72))

        '' 初始化测试证书:
        Dim pfxPath = Path.Combine("Resources", "Misc", "DsPdfTest.pfx")
        Dim cert = New X509Certificate2(File.ReadAllBytes(pfxPath), "qq",
                X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.Exportable)
        Dim sp = New SignatureProperties() With
        {
            .SignatureBuilder = New Pkcs7SignatureBuilder() With {
                .CertificateChain = New X509Certificate2() {cert}
            },
            .Location = "DsPdfWeb Demo Browser",
            .SignerName = "DsPdfWeb"
        }

        '' 添加代表签名的图像:
        sp.SignatureAppearance.Image = GCDRAW.Image.FromFile(Path.Combine("Resources", "ImagesBis", "signature.png"))
        sp.SignatureAppearance.CaptionImageRelation = GrapeCity.Documents.Pdf.Annotations.CaptionImageRelation.ImageOnly

        '' 初始化一个签名字段来保存签名:
        Dim sf = New SignatureField()
        sf.Widget.Rect = New RectangleF(72, 72 * 2, 72 * 4, 36)
        sf.Widget.Page = page
        sf.Widget.BackColor = Color.LightSeaGreen
        sf.Widget.DefaultAppearance.Font = StandardFonts.Helvetica
        sf.Widget.ButtonAppearance.Caption = $"Signer: {sp.SignerName}{vbCrLf}Location: {sp.Location}"
        '' 将签名字段添加到文档中:
        doc.AcroForm.Fields.Add(sf)
        '' 连接签名字段和签名属性:
        sp.SignatureField = sf

        '' 签署并保存文档:
        '' 笔记:
        '' - 签名和保存是一个原子操作,两者不能分开。
        '' - 传递给 Sign() 方法的流必须可读。
        doc.Sign(sp, stream)

        '' 倒回流以读取刚刚创建的文档
        '' 进入另一个 GcPdfDocument 并验证签名:
        stream.Seek(0, SeekOrigin.Begin)
        Dim doc2 = New GcPdfDocument()
        doc2.Load(stream)
        Dim sf2 = CType(doc2.AcroForm.Fields(0), SignatureField)
        If Not sf2.Value.VerifySignatureValue() Then
            Throw New Exception("Failed to verify the signature")
        End If

        '' 完成(生成并签名的文档已保存到“流”)。
        Return doc.Pages.Count
    End Function
End Class