Действие AcroForm е речник, прикрепен към изпълним модул, който казва на зрителя какво да прави, когато нещо се случи с този изпълним елемент. Щракнете върху бутон и визуализаторът прочита своя речник на действията: действие URI отваря уеб адрес, действие на JavaScript изпълнява скрипт, действие SubmitForm публикува събраните стойности на полето в крайна точка, действие ResetForm ги изчиства обратно до стойностите по подразбиране. Действието е данни, а не поведение, изпечено във файла. ISO 32000-1 §12.6 определя формата на речника; зрителят доставя двигателя, който го интерпретира. Това разделяне има значение, защото действие, написано перфектно в PDF, все още не прави нищо, ако читателят от другата страна няма двигател за него, и много скръб от AcroForm се проследява обратно към тази празнина, а не към неправилно оформено поле
Допълнителни примери с код
procedure BuildClaimForm(Pdf: THotPDF);
begin
// Page 1: applicant block
Pdf.CurrentPage.AddTextField('applicant.name', '', Rect(50, 700, 300, 722));
Pdf.CurrentPage.AddTextField('applicant.email', '', Rect(50, 660, 300, 682));
Pdf.CurrentPage.AddCheckBox('consent', 'Y', Rect(50, 620, 70, 640), False);
Pdf.CurrentPage.AddRadioButton('coverage', 'basic', Rect(50, 580, 70, 600), True);
Pdf.CurrentPage.AddRadioButton('coverage', 'full', Rect(90, 580, 110, 600), False);
Pdf.CurrentPage.AddComboBox('plan', 'Standard',
['Basic', 'Standard', 'Premium'], Rect(50, 540, 200, 565));
Pdf.AddPage; // CurrentPage now points at page 2
Pdf.CurrentPage.AddListBox('riders', 'None',
['None', 'Flood', 'Earthquake'], Rect(50, 500, 200, 600));
end;// Open a help page in the system browser
Pdf.CurrentPage.AddPushButtonWithAction('btnHelp', 'Help',
'https://www.example.com/claims-help', Rect(320, 700, 420, 730), baURI);
// Run viewer-side JavaScript
Pdf.CurrentPage.AddPushButtonWithAction('btnRecalc', 'Recalculate',
'app.alert("Totals updated.");', Rect(320, 660, 420, 690), baJavaScript);
// Submit as XFDF and keep empty fields in the payload
Pdf.CurrentPage.AddPushButtonWithSubmitAction('btnSubmit', 'Submit claim',
'https://api.example.com/claims', Rect(320, 620, 420, 650),
[sffXFDF, sffIncludeNoValueFields]);// Reject committed values that are not plausible email addresses
Pdf.AttachFieldKeyStrokeAction('applicant.email',
'if (event.willCommit && !/^[\w.-]+@[\w.-]+\.\w+$/.test(event.value)) event.rc = false;');
// Display US phone numbers as (NNN) NNN-NNNN
Pdf.AttachFieldFormatAction('applicant.phone',
'event.value = event.value.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3");');
// Refuse applicants under 18 at commit time
Pdf.AttachFieldValidateAction('applicant.age',
'if (parseInt(event.value) < 18) event.rc = false;');Бележки от производствен преглед
Тази допълнителна секция превръща темата от кратка демонстрация в работен контролен списък. При реална интеграция първо уточнете какъв файл влиза в процеса, кой компонент го създава или чете, какъв изход очаква потребителят и кои стойности трябва да останат непроменени между Delphi, C++Builder и външните инструменти
Проверявайте поведението с малки документи, с повредени входове и с данни, които приличат на продукционните. Грешките при кодиране, шрифтове, страници, криптиране или метаданни често се виждат само когато тестът съдържа кирилица, дълги имена, вложени обекти и празни стойности. Такъв набор от файлове дава по-надеждна гаранция от единичен пример
Ако кодът се изпълнява в услуга или пакетна задача, добавете отделни проверки за освобождаване на ресурси, повторно използване на компоненти, обработка на изключения и журналиране на причината за отказ. Клиентът трябва да получи ясен резултат: файлът е създаден, файлът е отхвърлен с разбираема причина или обработката може безопасно да се повтори
Преди публикуване сравнете изхода в поне два viewer-а или редактора и запишете минимален регресионен сценарий. Това пази статията полезна не само като пример, а като ориентир за поддръжка, диагностика и бъдещи версии на същия работен поток