Turite trečiosios šalies sąskaitos faktūros šabloną arba archyvuotą sutartį, kurią kažkas sugeneravo prieš daugelį metų programine įranga, kurios jau niekas neberanda, ir reikalavimas paprastas: padaryti ją interaktyvią. Įmesti parašo laukelį kampe, pridėti kelis teksto laukus, paversti plokščią kontrolinį sąrašą tikrais žymimaisiais laukeliais. Kabliukas tas, kad jūs nekuriate šio PDF nuo nulio. Jis jau egzistuoja, jau turi puslapius, turinio srautus ir šriftus, kurių nekontroliuojate, o jums reikia įskiepyti AcroForm valdiklius į tą objektų grafą jo neperstatant. Tai kitokia užduotis nei formos kūrimas naujame dokumente, ir vieta, kur dauguma suklysta, lieka nematoma tol, kol neatidarote rezultato peržiūros programoje ir nematote, kad ką tik įrašytų laukų puslapyje tiesiog nėra
HotPDF yra vietinis VCL PDF komponentas, skirtas Delphi ir C++Builder, ir nuo v2.247.0 jis pateikia atskirą metodų šeimą būtent tam: visų šešių standartinių laukų tipų kūrimui tiesiai dokumente, įkeltame naudojant LoadFromFile. Šiame straipsnyje apžvelgiama, ką tie metodai daro, kokius ISO 32000-1 žodynus jie sukuria ir kokia viena vėliava lemia, ar visas darbas tyliai nevirsta tuščiai atrodančiu failu
Kodėl laukų kūrimui įkeltame dokumente reikia atskiro kodo kelio
Kai PDF kuriate nuo nulio, HotPDF valdo visą objektų modelį. Kiekvienas puslapis yra redaguojamas THPDFPage apvalkalas, o pridėjus teksto lauką per AddTextField prijungia naują valdiklį prie puslapio anotacijos objekto, puslapio objekto ir formos laukų kolekcijos, tada sugeneruoja išvaizdos srautą iš dokumento šriftų resursų. Išvaizdos srautas yra matomas valdiklio paviršius - rėmelis, kraštinė ir bet koks numatytasis tekstas, nupiešti PDF braižymo operatoriais, kuriuos peržiūros programa atvaizduoja pažodžiui
Įkeltas dokumentas šios pagalbinės infrastruktūros jums nesuteikia. Puslapiai ateina kaip žali žodynai; nėra redaguojamo THPDFPage apvalkalo, prie kurio būtų galima prikabinti valdiklį, ir dar svarbiau - nėra paruošto šriftų resursų srauto, kuris galėtų nupiešti išvaizdos srautus. Todėl įkėlimo kelias eina kitu maršrutu. Jis įrašo laukų žodynus tiesiai į išanalizuotą objektų grafą ir puslapius adresuoja nuliniu pagrindu skaičiuojamu indeksu, o ne puslapio objektu. Laukų tipai ir vėliavų bitai visiškai sutampa su keliu nuo nulio, todėl Text laukas abiem atvejais lieka Text lauku; keičiasi tik vidinė instaliacija ir, svarbiausia, tai, kaip nupiešiamas valdiklio paviršius
/NeedAppearances vėliava čia nėra pasirenkama
Būtent šis vienas faktas nusprendžia, ar jūsų darbas apskritai pasirodys. Kadangi įkėlimo kelias negeneruoja išvaizdos srautų, naujai pridėtas valdiklis peržiūros programą pasiekia be /AP įrašo: tai laukas be aprašyto paviršiaus. Daugelis peržiūros programų, paprašytos atvaizduoti valdiklį be išvaizdos ir be nurodymo ją sukurti, tiesiog nieko nenupiešia. Laukas faile yra, struktūriškai jis teisingas, formos pildymo įrankis jį gali adresuoti, tačiau žmogui jis visiškai nematomas
Išėjimas iš šios situacijos apibrėžtas ISO 32000-1 §12.7.3: AcroForm žodynas turi /NeedAppearances loginę reikšmę, ir kai ji yra true atitinkantis skaitytuvas privalo pats sukurti trūkstamus išvaizdos srautus iš kiekvieno lauko /DA (numatytosios išvaizdos) eilutės ir vertės. HotPDF tai nustato už jus. Kai pirmą kartą prie įkelto dokumento pridedate bet kokį lauką, EnsureLoadedAcroForm paleidžiamas: jei kataloge nėra /AcroForm jis jį sukuria, jei nėra /Fields masyvo, sukuria ir jį, ir priverstinai nustato /NeedAppearances true. Šio metodo jūs nekviečiate tiesiogiai, bet žinojimas, kad jis egzistuoja, paaiškina tokį elgesį. Tai taip pat paaiškina diegimo niuansą, kurį verta įvardyti aiškiai: nedidelė dalis minimalių arba specifikacijos nesilaikančių peržiūros programų ignoruoja /NeedAppearances ir vis tiek nieko nerodo. Pagrindinėse skaityklėse ši vėliava atlieka savo darbą, tačiau jei jūsų auditorija naudoja neįprastą įterptą atvaizduoklį, išbandykite ten prieš ką nors pažadėdami
Šešių laukų tipų pridėjimas
Kiekvienas metodas turi tą pačią formą. Jūs perduodate nuliniu pagrindu skaičiuojamą puslapio indeksą, keturis valdiklio stačiakampio kampus PDF vartotojo erdvės koordinatėmis, lauko pavadinimą ir papildomus argumentus, kurių reikia tam tipui. Stačiakampis yra X1, Y1, X2, Y2, o PDF pradžios taškas yra apatiniame kairiajame puslapio kampe, todėl didesnės Y reikšmės yra aukščiau; tai koordinatinių sistemų konvencija iš paties failo formato, o ne viršutinis kairysis ekrano kampas, ir supainioti tai yra antra dažniausia klaida po užmirštos vėliavos. Kiekvienas kvietimas grąžina naujo lauko nuliniu pagrindu skaičiuojamą indeksą arba -1 jei puslapio indeksas buvo už intervalo ribų arba nepavyko išspręsti puslapio objekto
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;
Trečiasis ir ketvirtasis teksto lauko eilutiniai argumentai yra lauko pavadinimas ir jo pradinė /V vertė; sveikasis skaičius yra /MaxLen, įrašomas tik tada, kai yra didesnis už nulį. HotPDF kiekvienam redaguojamam laukui suteikia numatytosios išvaizdos eilutę /Helv 12 Tf 0 0 0 rg, ir būtent ją /NeedAppearances paisanti peržiūros programa skaito spręsdama, kokiu šriftu ir spalva turi nupiešti reikšmę. Žymimasis laukelis priima eksportuojamą reikšmę, tai yra eilutę, kurią forma pateikia, kai laukelis pažymėtas, taip pat loginę reikšmę pradinei būsenai; viduje jis įrašo atitinkamus /V, /AS ir /DV vardinius įrašus, kad įjungta ir išjungta būsena būtų nuosekli vos atidarius failą. Tuščia eksportuojama reikšmė pagal nutylėjimą tampa Yes, tai įprastinis žymimojo laukelio "įjungta" pavadinimas
Pasirinkimo laukai ir /Ff bitų vėliavos
ComboBox ir ListBox abu yra pasirinkimo laukai, lauko tipas /Ch pagal ISO 32000-1 §12.7.4. Skirtumas tarp išskleidžiamojo sąrašo ir slenkamojo sąrašo yra vienas bitas laukų vėliavų sveikajame skaičiuje /Ff: 18 bitas, Combo vėliava, vertė $40000. HotPDF nustato šį bitą AddLoadedComboBox ir palieka jį išjungtą AddLoadedListBox; kitaip abu laukai yra tapatūs, ir abu priima pasirinkimus kaip atvirą eilučių masyvą, įrašomą į /Opt įrašą
// 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');
Du pastebėjimai apie pasirinkčių sąrašą. HotPDF kiekvieną /Opt įrašą rašo kaip paprastą eilutę, kur eksportuojama reikšmė ir rodoma etiketė yra tas pats tekstas. ISO 32000-1 §12.7.4.4 taip pat leidžia dviejų elementų [export display] formą, kai reikia, kad pateikiama reikšmė skirtųsi nuo to, ką mato naudotojas; įkeltų dokumentų kūrimo metodai naudoja paprastesnę vienos eilutės formą, todėl jei jums reikia skirtingų eksportuojamų ir rodomų reikšmių, turėsite jas nustatyti gautame žodyne patys. O reikšmė, kurią perduodate kaip dabartinį lauko pasirinkimą, turėtų būti viena iš jūsų pateiktų parinkčių, nes peržiūros programa ją sulygina su sąrašu
Push button yra kitas vėliava valdomas atvejis: lauko tipas /Btn su 17 bitu, PushButton vėliava, kurios vertė $10000. Būtent šis bitas atskiria paspaudžiamą mygtuką nuo žymimojo laukelio, kuris taip pat yra /Btn laukas, tik be jo. Jūsų perduota antraštė įrašoma į išvaizdos charakteristikų žodyną /MK kaip įprastinė antraštė /CA. Verta sąžiningai apibrėžti šio metodo ribas: mygtukas sukuriamas su etikete ir stačiakampiu, tačiau įkelto dokumento kūrimo metodas prie jo neprijungia jokio veiksmo, todėl vienas jis yra mygtukas, kuris atrodo teisingai, bet paspaustas nieko nedaro. Submit, reset arba JavaScript veiksmų prijungimas yra atskira tema; kuriant dokumentą nuo nulio, lauko ir veiksmo darbo eiga aptariama straipsnyje AcroForm laukų ir veiksmų kūrimas Delphi aplinkoje, ir tai yra tinkamas palyginimo taškas, parodantis, ko įkėlimo kelias sąmoningai neapima
Žodynas, kurį bendrina kiekvienas laukas
Po visais šešiais metodais slypi vienas bendras kūrėjas, kuris sukonstruoja valdiklio anotaciją ir užregistruoja ją dviejose vietose. Jis įrašo /Type /Annot ir /Subtype /Widget, /Rect masyvą iš jūsų keturių koordinačių, anotacijos vėliavas /F 4, kurios nustato Print bitą, kad laukas būtų matomas ir spausdinant, ir ekrane, lauko pavadinimą /T, lauko tipą /FT, vėliavas /Ff, ir /P atgalinę nuorodą į puslapio objektą. Tada jis prideda naują lauką prie AcroForm /Fields masyvo ir prie to puslapio /Annots masyvo, pakeliui išspręsdamas netiesiogines nuorodas, kad būtų išplėsti tikrieji masyvai, o valdiklis neliktų našlaitis
Tas dvigubas registravimas yra svarbus, nes valdiklis, esantis tik viename iš dviejų sąrašų, yra sugadintas subtiliu būdu. Laukas, esantis /Fields bet nesantis puslapio /Annots, formai yra žinomas, tačiau niekada nenupiešiamas; atvirkštinis variantas būna nupieštas, bet nežinomas formos logikai. HotPDF kiekvieno pridėjimo metu palaiko abu sąrašus sinchronizuotus, ir tai yra ta apskaita, kurią kitu atveju pagal specifikaciją turėtumėte idealiai atlikti rankiniu būdu
Kelios sąžiningos ribos
Prieš kurdami darbo eigą pagal šį mechanizmą, teisingai nusistatykite lūkesčius. Suliejimo ir regeneravimo elgesys priklauso nuo to, ar peržiūros programa paiso /NeedAppearances, o tai galioja Acrobat, šiuolaikiniams naršyklių PDF varikliams ir įprastoms stalinių kompiuterių skaityklėms, tačiau nėra absoliuti garantija kiekvienam rinkoje pasitaikančiam atvaizduokliui. Jei privalote sukurti failą, kurio laukai visur būtų atvaizduojami vienodai, įskaitant peržiūros programas, kurios šią vėliavą ignoruoja, tuomet jau kalbame apie išvaizdos srautus, ir kelias nuo nulio, kuris jums nupiešia /AP, yra tinkamesnis pasirinkimas. Panašiai ir parašo laukas sukuriamas kaip tuščias pasirašymui paruoštas parašo valdiklis; lauko įterpimas nėra tas pats, kas pritaikyti kriptografinį parašą
Kai reikia keisti tai, kas jau egzistuoja, o ne pridėti naujų laukų, susijusi operacija yra formos suliejimas, kai interaktyvūs laukai įkepami atgal į statinį puslapio turinį, kad reikšmės taptų nuolatinės ir neredaguojamos; šis ciklas, įskaitant tai, kaip tvarkomos XFA turinčios formos, aptariamas straipsnyje XFA ir AcroForm laukų suliejimas Delphi aplinkoje. Laukų pridėjimas ir laukų suliejimas yra du to paties gyvavimo ciklo galai: šiame straipsnyje paaiškinama, kaip dokumentui, kuris jų neturėjo, suteikti interaktyvumą, o suliejimas parodo, kaip jį vėl pašalinti, kai forma jau atliko savo paskirtį
Čia parodytas įkeltų dokumentų formų API tiekiamas kaip standartinio HotPDF Component paketo, skirto Delphi ir C++Builder, dalis, kartu su visa laukų vėliavų, išvaizdos tvarkymo ir likusio AcroForm modelio nuorodine medžiaga