التعليق التوضيحي ليس محتوى الصفحة. عندما تستدعي TextOut أو ترسم مستطيلًا، تصبح العلامات جزءًا من تدفق محتوى الصفحة، أي من البتات التي يرسمها العارض. أما التعليق التوضيحي فهو قاموس منفصل يتدلى من الصفحة عبر المصفوفة /Annots، وله مستطيله الخاص ومظهره الخاص ودورة حياته الخاصة. يمكن للقارئ فتحه أو نقله أو إخفاؤه أو إزالته من دون لمس أي غليف من الصفحة الأصلية. هذا الفصل هو سبب وجود التعليقات التوضيحية أصلًا، وهو أيضًا مصدر أول شيئين يفاجئان الناس: أين يقع التعليق التوضيحي، وكيف يبدو عندما يتعامل معه عارض معين
يعرض HotPDF الأنواع الفرعية للتعليقات التوضيحية في ISO 32000 عبر عائلة من الاستدعاءات AddXxxAnnotation على كائن الصفحة. تشترك كلها في الشكل نفسه: مستطيل يثبت التعليق التوضيحي على الصفحة في فضاء مستخدم PDF، وحمولة ما مثل نص أو اسم ختم أو زوج من النقاط، ولون. إذا ضبطت المستطيل جيدًا فقد أنجزت معظم العمل. وما تبقى هو معرفة أي الأنواع الفرعية تملك مظهرها الخاص وأيها يعتمد على العارض لرسمه

المستطيل هو التعليق التوضيحي، لا النص
كل استدعاء للتعليق التوضيحي يأخذ TRect، وهذا المستطيل يعني شيئًا مختلفًا عن الإحداثيات التي تمررها إلى TextOut. بالنسبة إلى الملاحظة النصية فهو منطقة النقر، أي المنطقة الصغيرة التي تجلس فيها أيقونة الملاحظة وعند النقر عليها تنفتح التعليقات. أما بالنسبة إلى مربع أو مربع النص الحر فهو الامتداد المرئي للوسم. وبالنسبة إلى الختم فهو الصندوق الذي يتم تحجيم شكل الختم داخله. هذه الأرقام هي نقاط فضاء مستخدم PDF، مقاسة من الزاوية السفلية اليسرى للصفحة مع ازدياد Y إلى الأعلى، وهو نفس الاصطلاح الذي يستخدمه بقية HotPDF
الملاحظة النصية هي أخف نوع فرعي. تعطيها نص الجسم، ومستطيلًا للأيقونة، وعلمًا يحدد ما إذا كانت تنفتح افتراضيًا، واسم أيقونة، ولونًا
Pdf.CurrentPage.AddTextAnnotation(
'Reviewer: confirm the totals on this line before sign-off.',
Rect(120, 700, 140, 720), // icon hotspot, ~20pt square
False, // closed until the reader clicks it
taComment, // bubble icon
clBlue);
المستطيل هنا صغير عمدًا، حوالي عشرين نقطة لكل ضلع، لأن الملاحظة النصية ليست سوى أيقونة إلى أن ينقرها أحدهم. إذا جعلت المستطيل كبيرًا فلن تحصل على ملاحظة كبيرة، بل على منطقة نقر ضخمة مع تثبيت الأيقونة في إحدى الزوايا. يتحكم العلم Open في ما إذا كانت النافذة المنبثقة ظاهرة عند تحميل المستند. وإذا جعلت عدة ملاحظات True فإنها تتراكب فوق بعضها وفوق المحتوى، لذا احتفظ بذلك للملاحظة الوحيدة التي تريد من القارئ رؤيتها فورًا
يأتي اسم الأيقونة من THPDFTextAnnotationType، الذي يطابق أيقونات الملاحظات القياسية: taComment وtaKey وtaNote وtaHelp وtaParagraph وtaNewParagraph وtaInsert. الأيقونة هي الشيء الوحيد الذي يغيّره النوع. فهي لا تغير السلوك، ومن المهم أن تعرف أن ليس كل عارض يرسم الأنواع السبعة كلها؛ والاختيارات الآمنة عبر القراء القدامى والجدد هي taComment وtaNote وtaHelp
النص الحر يكتب على الصفحة لكنه يبقى تعليقًا توضيحيًا
يبدو التعليق التوضيحي من نوع النص الحر كأنه محتوى لأن النص مرئي من دون نقر، ويجلس داخل مستطيله مثل تسمية. لكنه يظل تعليقًا توضيحيًا بكل ما يعنيه ذلك من قابلية الفصل، وهذا بالضبط ما تريده لوسم مراجعة أو تسمية مسودة ينبغي أن يقدر أحدهم على إزالتها لاحقًا. وتستبدل التوقيع هنا الأيقونة وعلم الفتح بقيمة محاذاة
Pdf.CurrentPage.AddFreeTextAnnotation(
'DRAFT - not for distribution',
Rect(200, 210, 400, 235), // the box the text is laid into
ftCenter, // ftLeftJust / ftCenter / ftRightJust
clRed);
هنا يصبح المستطيل أهم مما هو عليه مع الملاحظة النصية لأن النص يلتف ويتحاذى داخله. إذا جعلت الصندوق قصيرًا جدًا فسيتقصّ النص عند الحافة السفلية، وإذا جعلته ضيقًا جدًا فسيلتف في مواضع لم تقصدها. تأتي المحاذاة من THPDFFreeTextAnnotationJust ولا تملك إلا ثلاث قيم. وبما أن النص الحر تعليق توضيحي من نوع markup، يمكن للقارئ الذي يفتح الملف في محرر أن يحدده أو ينقله أو يحذفه كوحدة واحدة، وهذا هو الفارق الذي يحدد ما إذا كنت ستستخدم النص الحر أم سترسم الكلمات بـ TextOut. إذا كانت التسمية يجب أن تبقى دائمة فارسمها. وإذا كانت تحريرية ومقصودًا إزالتها لاحقًا فاجعلها تعليقًا توضيحيًا
تعليقات هندسية وخطية للإشارة إلى الأشياء
المربعات والدوائر والخطوط هي الوسوم التي تستخدمها للإشارة إلى منطقة بدل وصفها بالكلمات. يغطي AddCircleSquareAnnotation شكلي الصندوق عبر THPDFCSAnnotationType بقيمتي csCircle أو csSquare، ويحدد المستطيل حدود الشكل
// A box drawn around a figure that needs attention
Pdf.CurrentPage.AddCircleSquareAnnotation(
'Check this region against the source data',
Rect(50, 300, 120, 360),
csSquare,
clGreen);
// A line, given two points rather than a rectangle
var
StartPt, EndPt: THPDFCurrPoint;
begin
StartPt.X := 130; StartPt.Y := 360;
EndPt.X := 250; EndPt.Y := 320;
Pdf.CurrentPage.AddLineAnnotation(
'Points from the note to the figure',
StartPt, EndPt,
clBlue);
end;
لاحظ أن التعليق التوضيحي الخطي يكسر نمط المستطيل: فهو يأخذ سجلين من نوع THPDFCurrPoint، نقطة بداية ونقطة نهاية، لأن الخط يُعرَّف بنقطتيه الطرفيتين لا بصندوق احتواء. اللون يحدد الضربة. وإذا كنت تريد رؤوس أسهم فـ HotPDF يملك تحميلات زائدة لـ AddLineAnnotation تقبل أنماط نهايات الخط، لكن الصيغة البسيطة ذات الوسيطات الثلاث ترسم خطًا مجردًا، وهذا هو ما يريده الاستدعاء التوضيحي غالبًا
تعمل الأنواع الفرعية لتنسيق النص على منطقة سبق أن وضعتها. يأخذ AddHighlightAnnotation مستطيلًا ومحتوى اختياريًا ولونًا افتراضيه الأصفر، ويصبغ المنطقة كما يفعل قلم التظليل. وهو مخصص لأن يجلس فوق نص حقيقي، لذا يجب أن يطابق المستطيل حدود الكلمات التي رسمتها، وهذا يعني أنك عادة تحسبه من الإحداثيات نفسها التي مررتها إلى TextOut بدل التخمين
الأختام تعتمد على العارض في رسمها
التعليق التوضيحي من نوع الختم هو الأكثر احتمالًا لأن يبدو مختلفًا من قارئ إلى آخر، ومن المفيد فهم السبب. يحدد AddStampAnnotation ختمًا قياسيًا عبر THPDFStampAnnotationType، بقيم مثل satApproved وsatConfidential وsatFinal وsatDraft وsatForComment
Pdf.CurrentPage.AddStampAnnotation(
'Approved for release on review',
Rect(50, 400, 200, 440),
satApproved,
clGreen);
اسم الختم هنا مجرد طلب. يحدد PDF مجموعة أسماء أختام قياسية لكنه لا يحدد الرسومات نفسها، لذلك يشحن كل عارض رسمه الخاص لكلمتي "APPROVED" أو "CONFIDENTIAL"، وبعضها لا يرسم شيئًا على الإطلاق للأسماء التي لا يتعرف عليها. يتحكم المستطيل في الصندوق الذي يتحجّم داخله الرسم، واللون مجرد تلميح قد يلتزم به العارض أو لا يلتزم. إذا كان يجب أن يبدو الختم نفسه في كل مكان، فالمسار الموثوق ليس ختمًا قياسيًا أصلًا: ارسم العلامة بنفسك بـ TextOut واستدعاءات الرسم، أو ضعها كتوضيح نص حر تتحكم في مظهره. استخدم الختم القياسي عندما تريد المظهر المألوف للعارض ويمكنك تحمل التباين
تتبع مرفقات الملفات الشكل نفسه المكوَّن من مستطيل وحمولة. يأخذ AddFileAttachmentAnnotation الوصف ومسار الملف المراد تضمينه ومستطيلًا لأيقونة المشبك ولونًا. يعيش الملف داخل PDF، والأيقونة هي المقبض الذي يستخدمه القارئ لاستخراجه
كيف تختلف التعليقات التوضيحية عن حقول AcroForm
أكثر ما يضيع الوقت هو معاملة التعليق التوضيحي كما لو كان حقل نموذج. كلاهما يرتبط بالصفحة عبر /Annots، وحقل النموذج في الواقع نوع فرعي خاص من التعليقات التوضيحية، أي widget، ولهذا يبدوان مرتبطين. لكنهما غير قابلين للتبادل. حقل النموذج يحمل قيمة وله اسم ويشارك في ترتيب التنقل ويمكن إرساله أو إعادة ضبطه أو برمجته؛ وتُنشئ هذه الحقول عبر استدعاءات AddTextField وAddCheckBox وAddPushButton، لا عبر استدعاءات التعليقات التوضيحية في هذه الصفحة. أما تعليق markup فيحمل ملاحظة أو شكلاً، وليس له قيمة تُرسل، وهو الأداة الخاطئة بمجرد أن تحتاج إلى جمع إدخال
الاختبار العملي بسيط. إذا كان من المفترض أن يكتب المستخدم أو يختار أو ينقر ويحتفظ المستند بذلك، فأنت تريد حقل AcroForm. وإذا كنت تترك ملاحظة أو تحدد منطقة أو تضع ختم حالة ينتقل مع الملف لكنه ليس بيانات، فأنت تريد تعليقًا توضيحيًا. الخلط بينهما ينتج مستندات تبدو صحيحة لكنها تتصرف بشكل خاطئ، مثل "حقل" لا يستطيع أحد تعبئته أو تعليق يختفي عند إعادة ضبط النموذج. والجانب التفاعلي، بما فيه أنواع الحقول والتحقق وإجراءات الإرسال، موضوع مستقل يغطيه شرح حقول وإجراءات AcroForm
تركيب صفحة كاملة
تتجمع الأجزاء كما يفعل باقي HotPDF. اضبط خصائص المستند، واستدع BeginDoc، وارسم أي محتوى تحتاجه من الصفحة باستدعاءات النص والرسوميات، ثم أضف التعليقات التوضيحية فوقه، وأغلق بـ EndDoc. ترتبط التعليقات التوضيحية بـ CurrentPage، لذلك بعد AddPage ستقع على الصفحة الجديدة، وأي ملاحظة كنت تقصدها للصفحة الأولى ستظهر بهدوء في الصفحة الثانية إذا أضفتها بعد الفاصل
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'annotated.pdf';
Pdf.Compression := cmFlateDecode;
Pdf.FontEmbedding := True;
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 740, 0, 'Quarterly figures, draft for review');
Pdf.CurrentPage.AddTextAnnotation(
'Confirm the totals before sign-off.',
Rect(50, 720, 70, 740), False, taComment, clBlue);
Pdf.CurrentPage.AddFreeTextAnnotation(
'DRAFT', Rect(450, 720, 540, 745), ftCenter, clRed);
Pdf.CurrentPage.AddStampAnnotation(
'For comment', Rect(50, 660, 180, 695), satForComment, clGreen);
Pdf.EndDoc;
finally
Pdf.Free;
end;
عادة أخيرة تستحق أن تكتسبها عندما يبدو الخرج خطأ: افتح الملف في أكثر من عارض قبل أن تقرر أن الشفرة معطلة. الأختام وأيقونات الملاحظات النادرة هي المسببات المعتادة، وبما أن التعليق التوضيحي طلب موجَّه إلى القارئ لا بكسلات مرسومة، فإن الاختلاف بين Acrobat وعارض خفيف يكون غالبًا من المواصفة كما صُممت، لا من خطأ في الاستدعاء
استدعاءات التعليقات التوضيحية المعروضة هنا جزء من HotPDF Component لـ Delphi و C++Builder