מאמר טכני

היפר-קישורים של HotPDF ב-Delphi: טיפים להערות PrintHyperlink

היפר-קישורים ב-PDF הם הערות URI: מלבן המכסה אזור מסוים בעמוד שבעת לחיצה עליו, אומר לצופה לפתוח כתובת URL. ההערה והטקסט שמתחתיה הם אובייקטים בלתי תלויים לחלוטין. ה-PrintHyperlink של HotPDF מאגד את שניהם לקריאה אחת, תוך ציור הטקסט וחישוב מלבן ההערה ממדדי הטקסט שעובד. נוחות זו מסתירה פרט ששווה להבין לפני שאתה כותב קוד ייצור

כיצד PrintHyperlink עובד

PrintHyperlink יושב על THPDFPage ולוקח ארבעה ארגומנטים: קואורדינטות X ו-Y (בנקודות, מקור שמאלי תחתון, Y עולה כלפי מעלה), מחרוזת התווית לציור ויעד ה-URL. פנימית הוא קורא ל-TextOut בצבע ההיפר-קישור הנוכחי, ואז מיד מחשב את מלבן ההערה מ-TextWidth ו-TextHeight במדדי הגופן הנוכחיים. המשמעות היא שיש להגדיר את הגופן והגודל לפני הקריאה, ואסור להם להשתנות בין ציור התווית להצבת ההערה, מכיוון ששניהם נפתרים באותה קריאה

צבע ברירת המחדל הוא clBlue. ה-SetRGBHyperlinkColor משנה אותו עבור קריאות עוקבות בלבד; הוא אינו מעדכן רטרואקטיבית הערות שכבר נכתבו. אם אתה זקוק לצבעים שונים עבור קבוצות קישורים שונות באותו עמוד, קרא ל-SetRGBHyperlinkColor לפני כל קבוצה ואפס אותו לאחר מכן

להלן מסמך מינימלי שכותב שלושה קישורים עם שני צבעים שונים:

procedure CreateLinkedReport(const FileName: string);
var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.BeginDoc;

    Pdf.CurrentPage.SetFont('Arial', [], 11);

    // Default blue for informational links
    Pdf.CurrentPage.TextOut(50, 750, 0, 'Reference links:');
    Pdf.CurrentPage.PrintHyperlink(50, 720, 'Product page', 'https://www.loslab.com/en-us/pdf-library/delphi-pdf-component.html');
    Pdf.CurrentPage.PrintHyperlink(50, 695, 'Online manual', 'https://www.loslab.com/en-us/pdf-library/delphi-pdf-component.html');

    // Red for the action link
    Pdf.CurrentPage.SetRGBHyperlinkColor(clRed);
    Pdf.CurrentPage.PrintHyperlink(50, 660, 'Purchase license', 'https://www.loslab.com/en-us/buy-hotpdf-fastspring.html');
    Pdf.CurrentPage.SetRGBHyperlinkColor(clBlue);  // restore default

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

מלכודת הקואורדינטות

HotPDF משתמש במקור שמאלי תחתון עם Y שגדל כלפי מעלה, בנקודות (1/72 אינץ'). עמוד A4 הוא 595 x 842 נקודות; עמוד US Letter הוא 612 x 792 נקודות. Y=750 יושב קרוב לראש עמוד A4, ו-Y=50 יהיה קרוב לשוליים התחתונים. כל מי שמגיע מגרפיקת מסך או מ-HTML מניח את ההיפך וממקם את שורת הקישור הראשונה הישר מחוץ לאזור הגלוי

מלבן ההערה ש-PrintHyperlink מחשב משתמש באותה מערכת קואורדינטות. אם בשלב מאוחר יותר תסובב את העמוד, תשנה את קנה המידה שלו, או תשנה את גודל העמוד מבלי לחשב מחדש את ערכי ה-X/Y שלך, הטקסט הגלוי והמלבן הלחיץ יתרחקו זה מזה. הקישור "עובד" במובן שלחיצה איפשהו ליד הטקסט מפעילה את ה-URL, אך האזור החם כבר אינו תואם למה שהקורא רואה. בדוק על גודל העמוד ורמת הזום האמיתיים שאתה שולח, לא רק על מכונת הפיתוח ב-100%

מקרה אחד שבו הסחיפה מובטחת: אם אתה קורא ל-PrintHyperlink עם קואורדינטות המתאימות לעמוד A4 ואז עובר לעמוד מותאם אישית בפורמט צר מבלי להתאים את ערכי ה-X/Y, ההערה יכולה להסתיים מחוץ לעמוד לחלוטין. אובייקט ההערה עדיין נכתב לתוך ה-PDF; רוב הצופים חותכים אותו בשקט, כך שהקישור פשוט נעלם ללא כל שגיאה

טקסט התווית מול יעד ה-URL

הארגומנטים של Text ו-Link הם בלתי תלויים. אתה יכול לצייר "Download invoice PDF" בעוד שהיעד הוא URL מסוג HTTPS מוסמך במלואו עם פרמטרי שאילתה. הפרדה זו היא מכוונת; התווית הגלויה צריכה להיות קריאה לאדם וה-URL יכול להיות ארוך או מיוצר דינמית

מה שיוצר בעיות הוא כאשר התווית היא ה-URL הגולמי עצמו, במיוחד אם הוא ארוך. אם ה-URL עוטף ויזואלית על פני שתי שורות אך מלבן ההערה חושב עבור מחרוזת של שורה אחת, רק השורה הראשונה תהיה לחיצה. PrintHyperlink אינו מטפל בזרימה מרובת שורות; שמור על תווית קצרה מספיק כדי להתאים לשורה אחת בגודל הגופן ורוחב העמוד הנוכחיים, או השתמש בתווית תיאורית קצרה עם ה-URL המלא כיעד

עבור מסמכים שיישמרו בארכיון או יופצו ללא חיבור אינטרנט פעיל, שקול גם האם ה-URL עצמו צריך להופיע בצורה מודפסת איפשהו בגוף המסמך, ולא רק כמטא-נתונים של הערה. קורא שמדפיס את ה-PDF על נייר אינו מקבל דבר מהערת URI

דוגמה מלאה להפקת מסמך

התבנית שלהלן מציגה תרחיש מציאותי יותר: יצירת דוח קצר עם קטע כותרת עליונה, טקסט גוף, ושורת קישורים בתחתית, הכל מקוד במקום מטופס עם שדות TEdit:

procedure GenerateProductSheet(
  const FileName, ProductName, ProductURL, SupportURL: string);
var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Compression := cmFlateDecode;
    Pdf.BeginDoc;

    // Header
    Pdf.CurrentPage.SetFont('Arial', [fsBold], 16);
    Pdf.CurrentPage.TextOut(50, 750, 0, WideString(ProductName));

    // Body paragraph placeholder
    Pdf.CurrentPage.SetFont('Arial', [], 11);
    Pdf.CurrentPage.TextOut(50, 710, 0, 'See the links below for full documentation.');

    // Footer links
    Pdf.CurrentPage.SetFont('Arial', [], 10);
    Pdf.CurrentPage.TextOut(50, 80, 0, 'Links:');
    Pdf.CurrentPage.PrintHyperlink(50, 60, 'Product page', ProductURL);
    Pdf.CurrentPage.PrintHyperlink(200, 60, 'Support', SupportURL);

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

שים לב שנקראת פונקציית SetFont לפני כל קבוצה של קריאות טקסט. הגופן אינו נשמר לרוחב AddPage, ואם תשכח להגדיר אותו לפני PrintHyperlink בעמוד חדש, מלבן ההערה יחושב כנגד המדדים שיהיו מדדי ברירת המחדל של העמוד, אשר עשויים להיות שונים ממה שציפית

היכן הטיפול בהערות משתנה בין צופים (viewers)

הערות URI ב-PDF מוגדרות בתקן ISO 32000-1 סעיף 12.6.4.7, וכל צופה שעומד בתקן אמור לפעול לפיהן. בפועל, מספר התנהגויות נבדלות בין צופים. Adobe Acrobat מציג הנחיית אבטחה בלחיצה ראשונה עבור כתובות URL שאינן ברשימת הדומיינים המהימנים; דפדפנים וצופים קלי משקל רבים אינם עושים זאת. כמה צופי PDF ארגוניים בסביבות נעולות משביתים הערות URI לחלוטין על פי מדיניות, כך שלחיצה לא עושה דבר, ללא שגיאה גלויה. אפליקציות PDF לנייד משתנות בשאלה האם הן פותחות קישורים בתוך תצוגת האינטרנט של האפליקציה או מעבירות לדפדפן המערכת

אף אחד מאלה אינם באגים שניתן לתקן מצד היצירה; אלו החלטות מדיניות של הצופה. מה שאתה יכול לעשות הוא לכתוב תוויות קישור שהופכות את ה-URL לגלוי גם בגוף המסמך, כך שקורא בסביבה מוגבלת עדיין יוכל להעתיק את הכתובת ידנית. ההערה היא הנוחות; הטקסט הוא הגיבוי

פרט נוסף ששווה לדעת: הערות URI ב-PDF אינן נושאות קו תחתון ויזואלי כברירת מחדל. הקו התחתון שאתה רואה ברוב הצופים מצויר על ידי הצופה עצמו בהתבסס על סוג ההערה, ולא על ידי גליף בזרם התוכן. אם אתה זקוק לקו תחתון פיזי ששורד הדפסה למעבד (renderer) לא אינטראקטיבי או להמרה של PDF לתמונה, צייר אותו במפורש עם LineTo ו-Stroke בהיסט ה-Y המתאים מתחת לקו הבסיס של הטקסט. זוהי פעולת ציור נפרדת, לא משהו ש-PrintHyperlink מטפל בו עבורך

ממשק ה-API של ההיפר-קישורים המוצג כאן הוא חלק מרכיב ה-HotPDF עבור Delphi ו-C++Builder