FormSubmitXml.vb
'' 完毕:
Imports System.Drawing
Imports System.IO
Imports System.Linq
Imports System.Xml
Imports System.Text
Imports System.Collections.Generic
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Pdf.AcroForms
Imports GrapeCity.Documents.Pdf.Actions
Imports GrapeCity.Documents.Pdf.Annotations
Imports GrapeCity.Documents.Text

'' 注意:此示例从 GcDocs.Pdf v3 开始已过时。请参阅新的FormDataSubmit
'' 样本以获得更好的解决方案。
'' 
'' 此示例创建一个可以提交到服务器的 AcroForm PDF。
'' 它依赖服务器将提交的数据放入XML中,
'' 将该 XML 导入到包含类似表单的 PDF 中,
'' 并将包含加载数据的表单发送回客户端。
'' 请注意,生成的 PDF 包含已填写的表单字段
'' 显示在客户端浏览器的默认 PDF 查看器中。
'' 代码与FormSubmit类似。
Public Class FormSubmitXml
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim page = doc.NewPage()

        Dim rc = Util.AddNote("填写表单中的字段,然后单击“提交”将其发送回服务器。" +
            "", page)

        Dim g = page.Graphics
        Dim tf = New TextFormat() With {.Font = StandardFonts.Times, .FontSize = 14}
        Dim ip = New PointF(72, rc.Bottom + 36)
        Dim fldOffset = 72 * 2 + 46
        Dim fldHeight = tf.FontSize * 1.2F
        Dim dY = 32

        '' 文本域:
        g.DrawString("First name:", tf, ip)
        Dim fldFirstName = New TextField() With {.Name = "FirstName", .Value = "John"}
        fldFirstName.Widget.Page = page
        fldFirstName.Widget.Rect = New RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight)
        fldFirstName.Widget.DefaultAppearance.Font = tf.Font
        fldFirstName.Widget.DefaultAppearance.FontSize = tf.FontSize
        doc.AcroForm.Fields.Add(fldFirstName)
        ip.Y += dY

        '' 文本域:
        g.DrawString("Last name:", tf, ip)
        Dim fldLastName = New TextField() With {.Name = "LastName", .Value = "Smith"}
        fldLastName.Widget.Page = page
        fldLastName.Widget.Rect = New RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight)
        fldLastName.Widget.DefaultAppearance.Font = tf.Font
        fldLastName.Widget.DefaultAppearance.FontSize = tf.FontSize
        doc.AcroForm.Fields.Add(fldLastName)
        ip.Y += dY

        '' 复选框:
        g.DrawString("Subscribe to Mailing List:", tf, ip)
        Dim fldCheckbox = New CheckBoxField() With {.Name = "Subscribe", .Checked = True}
        fldCheckbox.Widget.Page = page
        fldCheckbox.Widget.Rect = New RectangleF(ip.X + fldOffset, ip.Y, fldHeight, fldHeight)
        doc.AcroForm.Fields.Add(fldCheckbox)
        ip.Y += dY

        '' 多行文本框:
        g.DrawString("Additional information:", tf, ip)
        Dim fldAdditionalInfo = New TextField() With {.Name = "AdditionalInfo", .Multiline = True}
        fldAdditionalInfo.Widget.Page = page
        fldAdditionalInfo.Widget.Rect = New RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight * 2)
        fldAdditionalInfo.Widget.DefaultAppearance.Font = tf.Font
        fldAdditionalInfo.Widget.DefaultAppearance.FontSize = tf.FontSize
        doc.AcroForm.Fields.Add(fldAdditionalInfo)
        ip.Y += dY * 2

        '' 提交表单按钮:
        Dim btnSubmit = New PushButtonField()
        btnSubmit.Widget.Rect = New RectangleF(ip.X + fldOffset, ip.Y, 72, fldHeight)
        btnSubmit.Widget.ButtonAppearance.Caption = "Submit"
        btnSubmit.Widget.Highlighting = HighlightingMode.Invert
        btnSubmit.Widget.Page = page

        '' 提交网址:
        btnSubmit.Widget.Activate = New ActionSubmitForm("/Samples/HandleFormSubmitXml")
        doc.AcroForm.Fields.Add(btnSubmit)

        '' 重置表单按钮:
        Dim btnReset = New PushButtonField()
        btnReset.Widget.Rect = New RectangleF(ip.X + fldOffset + 72 * 1.5F, ip.Y, 72, fldHeight)
        btnReset.Widget.ButtonAppearance.Caption = "Reset"
        btnReset.Widget.Highlighting = HighlightingMode.Invert
        btnReset.Widget.Page = page
        btnReset.Widget.Activate = New ActionResetForm()
        doc.AcroForm.Fields.Add(btnReset)
        ip.Y += dY

        '' 完毕:
        doc.Save(stream)
        Return doc.Pages.Count
    End Function

    '' 注意:下面的代码由 Web 示例浏览器控制器在表单时使用
    '' 提交此示例准备的内容,它不是由 CreatePDF() 方法直接调用的。

    '' 创建一个 GcPdfDocument,将 AcroForm PDF 加载到其中,并用数据填充它
    '' 使用 GcPdfDocument.ImportFormDataFromXML() 方法。
    '' 
    '' 当此样本准备表单时,样本控制器将调用此方法
    '' 由用户提交。样本控制器解析客户端响应并构建
    '' “values”集合用提交的字段值填充它,然后调用
    '' 此方法用于准备 XML,将其导入到新创建的 PDF 中,然后返回
    '' 将生成的 PDF 发送至控制器,控制器将其发送回客户端。
    Public Shared Function ImportFormData(ByVal values As List(Of FieldExportEntry)) As Stream
        Dim pdf = New GcPdfDocument()
        Using fs = New FileStream(Path.Combine("Resources", "PDFs", "ImportFormXML.pdf"), FileMode.Open, FileAccess.Read)
            pdf.Load(fs)
            Using ms = New MemoryStream()
                SaveFieldsToXML(values, ms)
                ms.Seek(0, SeekOrigin.Begin)
                pdf.ImportFormDataFromXML(ms)
            End Using
            Dim outMs = New MemoryStream()
            pdf.Save(outMs)
            outMs.Seek(0, SeekOrigin.Begin)
            Return outMs
        End Using
    End Function

    '' 表示要导出到 XML 的表单字段及其值。
    Public Class FieldExportEntry
        Public Property Name As String
        Public Property Values As List(Of String)
        '' Note: this sample does Not support child fields:
        '' public List<FieldTreeNode> Children { get set }
    End Class

    '' 将字段及其值保存到流中。
    '' 
    '' 该方法与GcPdfDocument.ExportFormDataToXML()类似,具有以下内容
    '' 重要限制:
    '' - 它不支持子字段(field.Children集合);
    '' - 它不处理名称不是有效 XML 名称的字段 (xfdf:original)。
    Public Shared Sub SaveFieldsToXML(ByVal values As List(Of FieldExportEntry), ByVal stream As Stream)
        Dim xws = New XmlWriterSettings() With
            {
                .Indent = True,
                .CloseOutput = False,
                .Encoding = Encoding.UTF8
            }
        Using xw = XmlWriter.Create(stream, xws)
            xw.WriteStartElement("fields")
            xw.WriteAttributeString("xmlns", "xfdf", Nothing, "http:''ns.adobe.com/xfdf-transition/")
            For Each ftn In values
                xw.WriteStartElement(ftn.Name)
                For Each v In ftn.Values
                    xw.WriteStartElement("value")
                    '' 注意:数组中的值由客户端 PDF 查看器形成,
                    '' 它将“on”复选框值表示为“true”,而 ImportFormDataFromXML
                    '' 期望“on”值表示为“Yes”(这就是 ExportFormDataToXML
                    '' 作品,类似于 Acrobat)。这是一个快速而肮脏的技巧,仅供
                    '' 由于这个样本:
                    If v = "true" Then
                        xw.WriteString("Yes")
                    Else
                        xw.WriteString(v)
                    End If
                    xw.WriteEndElement()
                Next
                xw.WriteEndElement()
            Next
            xw.WriteEndElement()
        End Using
    End Sub
End Class