Teknik Makale

Yüklü Bir PDF'ye Delphi'de AcroForm Alanları Ekleme

Elinizde üçüncü taraf bir fatura şablonu ya da yıllar önce, artık hiçbir yerde bulunamayan bir yazılımla üretilmiş arşivlenmiş bir sözleşme var ve gereksinim bunu etkileşimli hale getirmek: köşeye bir imza kutusu yerleştirmek, birkaç metin alanı eklemek, düz bir kontrol listesini gerçek onay kutularına dönüştürmek. Zorluk şu ki bu PDF'yi sıfırdan oluşturmuyorsunuz. Dosya zaten var, sayfaları ve içerik akışları ve sizin denetlemediğiniz yazı tipleri zaten mevcut ve bu nesne grafiğinin üzerine belgeyi yeniden oluşturmadan AcroForm widget'ları eklemeniz gerekiyor. Bu, yeni bir belgede form oluşturma probleminden farklıdır ve insanı en çok şaşırtan kısım, sonucu bir görüntüleyicide açana kadar görünmez kalır; siz yazdığınız alanlar sayfada hiçbir yerde görünmez

HotPDF, Delphi ve C++Builder için yerel bir VCL PDF bileşenidir ve v2.247.0 sürümünden itibaren tam olarak bunun için ayrılmış bir yöntem ailesi sunar: yüklü bir belge üzerinde doğrudan altı standart alan türünün tamamını oluşturmak LoadFromFile. Bu makale, bu yöntemlerin ne yaptığını, oluşturdukları ISO 32000-1 sözlüğünü ve tüm işlemin sessizce boş görünümlü bir dosya üretmesine neden olan tek bayrağı ele alır

Yüklü Belgede Alan Oluşturma Neden Ayrı Bir Kod Yoludur

Sıfırdan bir PDF oluşturduğunuzda HotPDF tüm nesne modeline sahiptir. Her sayfa yazılabilir THPDFPage sarmalayıcıdır ve bir metin alanını AddTextField üzerinden eklemek, yeni widget'ı sayfanın açıklama nesnesine, sayfa nesnesine ve formun alan koleksiyonuna bağlar, ardından belgenin yazı tipi kaynaklarından bir görünüm akışı üretir. Görünüm akışı, widget'ın görünen yüzüdür; kutu, kenarlık ve varsa varsayılan metin, görüntüleyicinin aynen işlediği PDF çizim işleçleri olarak boyanır

Yüklü bir belge size bunlardan hiçbirini vermez. Sayfalar ham sözlükler olarak gelir; widget asmak için yazılabilir THPDFPage sarmalayıcı yoktur ve daha da önemlisi, görünüm akışlarını boyayacak bir yazı tipi kaynağı hattı hazır beklemez. Bu yüzden yüklü yol farklı bir rota izler. Alan sözlüklerini doğrudan ayrıştırılmış nesne grafiğinin üzerine yazar ve sayfaları sayfa nesnesi yerine sıfır tabanlı indeksle adresler. Alan türleri ve bayrak bitleri sıfırdan oluşturma yoluyla birebir aynıdır; yani bir Text alanı her iki durumda da Text alanıdır. Değişen şey alttaki altyapı ve, kritik olarak, widget yüzeyinin nasıl çizildiğidir

Burada /NeedAppearances bayrağı isteğe bağlı değildir

Bu, işinizin görünüp görünmeyeceğine karar veren tek gerçektir. Çünkü yüklü yol görünüm akışları üretmez, yeni eklenen bir widget görüntüleyiciye hiçbir /AP girişi olmadan gelir: yüzeyi tanımlanmamış bir alan. Görünümü olmayan ve onu oluşturması için talimat verilmemiş bir widget'ı işlemeye çalışan birçok görüntüleyici hiçbir şey çizmez. Alan dosyanın içindedir, yapısal olarak geçerlidir, bir form doldurma aracıyla erişilebilir ve insan için tamamen görünmezdir

Kaçış yolu ISO 32000-1 §12.7.3 içinde tanımlanır: AcroForm sözlüğü bir /NeedAppearances boolean değeri taşır ve bu değer true olduğunda, uyumlu bir okuyucu eksik görünüm akışlarını her alanın /DA (varsayılan görünüm) dizesinden ve değerinden kendisi oluşturmak zorundadır. HotPDF bunu sizin için ayarlar. Yüklü bir belgeye ilk kez herhangi bir alan eklediğinizde, EnsureLoadedAcroForm çalışır: katalogda hiç /AcroForm yoksa onu oluşturur, eğer hiç /Fields dizisi yoksa onu oluşturur ve /NeedAppearances true. Bunu doğrudan çağırmazsınız, ama varlığını bilmek davranışı açıklar. Ayrıca açıkça söylemeye değer bir dağıtım uyarısını da açıklar: birkaç sade veya uyumlu olmayan görüntüleyici /NeedAppearances /NeedAppearances'ı yok sayar ve yine de hiçbir şey göstermez. Ana akım okuyucular için bayrak işini yapar, ancak hedef kitleniz alışılmadık bir gömülü işleyici kullanıyorsa, söz vermeden önce orada test edin

Altı Alan Türünü Eklemek

Her yöntem aynı yapıyı izler. Sıfır tabanlı sayfa indeksini, PDF kullanıcı alanı koordinatlarında widget dikdörtgeninin dört köşesini, alan adını ve türün gerektirdiği ek argümanları verirsiniz. Dikdörtgen X1, Y1, X2, Y2 PDF'nin orijini sayfanın sol altındayken tanımlanır, bu yüzden daha büyük Y değerleri daha yukarıda yer alır; bu, dosya biçiminin koordinat kuralıdır, ekranın sol üst kuralı değil, ve bunu ters çevirmek, bayrağı unutmanın ardından gelen en yaygın ikinci hatadır. Her çağrı yeni alanın sıfır tabanlı indeksini döndürür ya da -1 sayfa indeksi aralık dışındaysa veya sayfa nesnesi çözülemediyse

var
  Pdf: THotPDF;
  Idx: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('contract.pdf') <= 0 then Exit;

    // Text field: name, initial value, max length (0 = unlimited)
    Idx := Pdf.AddLoadedTextField(0, 72, 680, 320, 700, 'FullName', '', 0);

    // CheckBox: export value, initial checked state
    Pdf.AddLoadedCheckBox(0, 72, 640, 90, 658, 'AgreeTerms', 'Yes', False);

    // Signature field: just a name and a rectangle
    Pdf.AddLoadedSignatureField(0, 360, 72, 540, 132, 'ApproverSig');

    if Idx >= 0 then
      Pdf.SaveLoadedDocument('contract-interactive.pdf');
  finally
    Pdf.Free;
  end;
end;

Text alanının üçüncü ve dördüncü dize argümanları alan adı ve ilk /V değeridir; tamsayı /MaxLen, yalnızca sıfırdan büyük olduğunda yazılır. HotPDF her düzenlenebilir alana /Helv 12 Tf 0 0 0 rg varsayılan görünüm dizesi verir; bu, bir /NeedAppearances-uyumlu görüntüleyicinin değeri yazdırırken başvurduğu yazı tipini ve rengi seçmek için okuduğu dizedir. Onay kutusu bir dışa aktarma değeri, kutu işaretlendiğinde formun gönderdiği dize ve başlangıç durumu için bir boolean alır; içerde eşleşen /V, /AS ve /DV ad girişlerini yazar, böylece açma/kapama durumu dosya açılır açılmaz tutarlı olur. Boş bir dışa aktarma değeri Yes olarak varsayılır, onay kutusunun geleneksel "açık" adı

Seçim Alanları ve /Ff Bit Bayrakları

ComboBox ve ListBox, ikisi de seçim alanıdır, alan türü /Ch ISO 32000-1 §12.7.4'te. Açılır menü ile kaydırmalı liste arasındaki fark, alan bayrakları tamsayısındaki /Ff: 18. bit, Combo bayrağı, değer $40000. HotPDF bu biti AddLoadedComboBox için ayarlar ve AddLoadedListBox için boş bırakır; aksi halde ikisi aynıdır ve ikisi de seçimlerini /Opt girişine yazılan açık uçlu bir dize dizisi olarak alır

// Dropdown (Combo flag set internally) with an initial selection
Pdf.AddLoadedComboBox(0, 72, 600, 300, 620, 'Country', 'Canada',
  ['United States', 'Canada', 'Mexico']);

// Scrolling list, no initial value
Pdf.AddLoadedListBox(0, 72, 520, 300, 590, 'Priority', '',
  ['Low', 'Normal', 'High']);

// Push button with a caption drawn through /MK
Pdf.AddLoadedPushButton(0, 360, 600, 480, 626, 'SubmitBtn', 'Submit');

Seçenek listesiyle ilgili iki not var. HotPDF her /Opt girişini düz bir dize olarak yazar; dışa aktarma değeri ile görüntülenen etiket aynı metindir. ISO 32000-1 §12.7.4.4 ayrıca gönderilen değerin kullanıcının okuduğundan farklı olması gerektiğinde iki öğeli [export display] biçimine de izin verir; yüklü oluşturma yöntemleri daha basit tek dize biçimini kullanır, bu yüzden dışa aktarma ve görüntüleme değerleri farklı olsun istiyorsanız bunları sonuçtaki sözlükte kendiniz ayarlarsınız. Ayrıca alanın geçerli seçimi olarak verdiğiniz değer, sunduğunuz seçeneklerden biri olmalıdır, çünkü görüntüleyici bunu listeyle eşleştirir

PushButton, bayrak güdümlü başka bir durumdur: alan türü /Btn ile 17. bit, PushButton bayrağı, değer $10000. Bu bit, tıklanabilir bir düğmeyi onay kutusundan ayırır; onay kutusu da bir /Btn alanıdır ama bu bit olmadan. Geçirdiğiniz başlık, görünüm özellikleri sözlüğüne /MK olarak normal başlık /CA şeklinde yazılır. Kapsam konusunda dürüst olmak gerekirse: düğme etiketi ve dikdörtgeniyle oluşturulur, ancak yüklü oluşturma yöntemi bir eylem eklemez; yani tek başına doğru görünen ama tıklandığında hiçbir şey yapmayan bir düğmedir. Submit, Reset veya JavaScript eylemlerini bağlamak ayrı bir konudur; sıfırdan authoring tarafı için alan ve eylem iş akışı Delphi'de AcroForm alanları ve eylemleri oluşturma içinde ele alınır, bu da yüklü yolun bilinçli olarak dışarıda bıraktığı şeyler için doğru karşılaştırma noktasıdır

Her Alanın Paylaştığı Sözlük

Altı yöntemin altında, widget açıklamasını oluşturan ve onu iki yerde kaydeden tek bir ortak kurucu vardır. Şunu yazar /Type /Annot ve /Subtype /Widget, /Rect dört koordinatınızdan gelen /F 4 yazdırma bitini ayarladığı için alanın kağıtta da ekranda da görünmesini sağlayan açıklama bayrakları /T, alan adı /FT, alan türü /Ff, bayraklar /P, sayfa nesnesine geri başvuru. Ardından yeni alanı AcroForm'un /Fields dizisine ve o sayfanın /Annots dizisine ekler, dolaylı başvuruları yol boyunca çözümler, böylece widget'ı sahipsiz bırakmak yerine gerçek dizileri genişletir

Bu ikili kayıt önemlidir çünkü iki listeden yalnızca birinde yaşayan bir widget, ince bir şekilde bozulur. /Fields içinde bulunan ama sayfanın /Annots dışında kalan bir alan form tarafından bilinir ama hiç boyanmaz; tersi boyanır ama form mantığına bilinmez. HotPDF her eklemede ikisini de eşit tutar, bu da aksi halde spesifikasyona karşı elle tam doğru yapmanız gereken türden bir muhasebedir

Birkaç Dürüst Sınırlama

Bunun üzerine bir iş akışı kurmadan önce beklentileri netleştirin. Düzleştirip yeniden üretme davranışı, görüntüleyicinin /NeedAppearances, Acrobat'ı, modern tarayıcı PDF motorlarını ve yaygın masaüstü okuyucuları kapsar, ancak sahadaki her işleyici için kesin bir garanti değildir. Alanları her yerde aynı biçimde işlemeyi amaçlıyorsanız, bayrağı yok sayan görüntüleyiciler dahil, görünüm akışı alanındasınız ve sizin için /AP çizen sıfırdan oluşturma yolu daha uygundur. İmza alanı da benzer şekilde, imzalanmaya hazır boş bir imza widget'ı olarak oluşturulur; alanı yerleştirmek, kriptografik bir imza uygulamakla aynı şey değildir

Mevcut olana eklemek yerine orada olanı değiştirmek için ilgili işlem form düzleştirmedir; burada etkileşimli alanları statik sayfa içeriğine geri gömer, böylece değerler kalıcı ve düzenlenemez olur. XFA içeren formların nasıl ele alındığı da dahil bu ileri geri dönüş Delphi'de XFA ve AcroForm alanlarını düzleştirme içinde ele alınır. Alan eklemek ve alan düzleştirmek aynı yaşam döngüsünün iki ucudur: bu makale, etkileşimi olmayan bir belgeye etkileşim kazandırmanın yoludur; düzleştirme ise form görevini tamamladığında onu geri almanın yoludur

Burada gösterilen yüklü-belge form API'si standart HotPDF Component paketinin bir parçası olarak Delphi ve C++Builder için sunulur; alan bayraklarının, görünüm işleme yönetiminin ve AcroForm modelinin geri kalanının tam başvuru kaynağıyla birlikte gelir