Τεχνικό Άρθρο

Υπερσύνδεσμοι HotPDF στη Delphi: συμβουλές PrintHyperlink

Οι υπερσύνδεσμοι PDF είναι σχολιασμοί URI: ένα ορθογώνιο που καλύπτει κάποια περιοχή της σελίδας και, όταν πατηθεί, λέει στον προβολέα να ανοίξει ένα URL. Ο σχολιασμός και το κείμενο κάτω από αυτόν είναι εντελώς ανεξάρτητα αντικείμενα. Η PrintHyperlink του HotPDF συνδυάζει και τα δύο σε μία κλήση, σχεδιάζοντας το κείμενο και υπολογίζοντας το ορθογώνιο του σχολιασμού από τις μετρικές του αποδιδόμενου κειμένου. Αυτή η ευκολία κρύβει μια λεπτομέρεια που αξίζει να κατανοήσετε πριν γράψετε κώδικα παραγωγής. Δεν είναι επίσης όλη η ιστορία: η AddURILink τοποθετεί μια περιοχή κλικ πάνω σε περιεχόμενο που σχεδιάσατε εσείς, και η AddGoToLink χειρίζεται την εσωτερική πλοήγηση — και οι δύο καλύπτονται παρακάτω

Πώς λειτουργεί η PrintHyperlink

Η PrintHyperlink βρίσκεται στην THPDFPage και δέχεται τέσσερα ορίσματα: συντεταγμένες X και Y (σε σημεία, με αρχή κάτω αριστερά και το Y να αυξάνεται προς τα πάνω), τη συμβολοσειρά ετικέτας που θα σχεδιαστεί, και το URL προορισμού. Εσωτερικά καλεί την TextOut με το τρέχον χρώμα υπερσυνδέσμου, και έπειτα αμέσως υπολογίζει το ορθογώνιο του σχολιασμού από τις TextWidth και TextHeight με τις τρέχουσες μετρικές γραμματοσειράς. Αυτό σημαίνει ότι η γραμματοσειρά και το μέγεθος πρέπει να οριστούν πριν την κλήση, και δεν πρέπει να αλλάξουν ανάμεσα στη σχεδίαση της ετικέτας και την τοποθέτηση του σχολιασμού, επειδή και τα δύο επιλύονται στην ίδια κλήση

Ανατομία μίας κλήσης PrintHyperlink του HotPDF που γράφει δύο ανεξάρτητα αντικείμενα PDF: τις ορατές γλυφές της ετικέτας που σχεδιάζει η TextOut και ένα ορθογώνιο σχολιασμού συνδέσμου URI υπολογισμένο από τις TextWidth και TextHeight
Οι γλυφές της ετικέτας και το ορθογώνιο URI είναι ξεχωριστά αντικείμενα PDF, γι' αυτό η γραμματοσειρά και το χρώμα υπερσυνδέσμου πρέπει να έχουν οριστεί πριν μία κλήση γράψει και τα δύο

Το προεπιλεγμένο χρώμα είναι 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);

    // Προεπιλεγμένο μπλε για πληροφοριακούς συνδέσμους
    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');

    // Κόκκινο για τον σύνδεσμο ενέργειας
    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);  // επαναφορά προεπιλογής

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

Η παγίδα των συντεταγμένων

Το HotPDF χρησιμοποιεί αρχή κάτω αριστερά με το Y να μεγαλώνει προς τα πάνω, σε σημεία (1/72 της ίντσας). Μια σελίδα A4 είναι 595 x 842 pt· μια σελίδα US Letter είναι 612 x 792 pt. Το 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

Παράκαμψη του περιορισμού των πολλών γραμμών

Όταν μια ετικέτα συνδέσμου πρέπει πραγματικά να εκτείνεται σε περισσότερες από μία γραμμές — ένα μακρύ URL τυπωμένο αυτολεξεί, ή μια αναδιπλωμένη πρόταση που πρέπει να δέχεται κλικ από άκρη σε άκρη — η λύση είναι να σταματήσετε να την αντιμετωπίζετε ως έναν σύνδεσμο και να την αντιμετωπίσετε ως έναν σύνδεσμο ανά γραμμή. Κάθε κλήση της PrintHyperlink υπολογίζει το ορθογώνιό της από το κείμενο που σχεδιάζει, οπότε αρκετές κλήσεις που μοιράζονται τον ίδιο προορισμό Link παράγουν αρκετούς σωστά διαστασιολογημένους σχολιασμούς που όλοι ανοίγουν το ίδιο URL. Ο αναγνώστης δεν μπορεί να καταλάβει τη διαφορά· κάθε γραμμή αποκρίνεται σε κλικ

Σύγκριση μιας αναδιπλωμένης ετικέτας υπερσυνδέσμου HotPDF που παίρνει έναν σχολιασμό ο οποίος καλύπτει μόνο την πρώτη της γραμμή έναντι μίας κλήσης PrintHyperlink ανά αποδιδόμενη γραμμή με κοινό URL προορισμού
Ένα ορθογώνιο υπολογισμένο για μία γραμμή αφήνει ακάλυπτη κάθε αναδιπλωμένη συνέχεια, ενώ οι κλήσεις ανά γραμμή μοιράζονται έναν προορισμό και κρατούν ολόκληρο το μπλοκ ενεργό για κλικ
procedure PrintWrappedHyperlink(Page: THPDFPage; X, TopY, LineStep: Single;
  const Lines: array of AnsiString; const Link: AnsiString);
var
  I: Integer;
begin
  for I := 0 to High(Lines) do
    Page.PrintHyperlink(X, TopY - I * LineStep, Lines[I], Link);
end;

// Χρήση: σπάστε την ετικέτα στις θέσεις όπου την αναδιπλώνει η διάταξή σας
Pdf.CurrentPage.SetFont('Arial', [], 10);
PrintWrappedHyperlink(Pdf.CurrentPage, 50, 400, 14,
  ['https://www.loslab.com/en-us/pdf-library/',
   'delphi-pdf-component.html'],
  'https://www.loslab.com/en-us/pdf-library/delphi-pdf-component.html');

Ο διαχωρισμός της συμβολοσειράς είναι δική σας ευθύνη: σπάστε τη στις ίδιες θέσεις όπου θα αναδιπλωνόταν οπτικά με την τρέχουσα γραμματοσειρά και πλάτος στήλης, χρησιμοποιώντας την TextWidth για να δοκιμάσετε κάθε υποψήφια γραμμή. Η εναλλακτική είναι να σχεδιάσετε εσείς το αναδιπλωμένο κείμενο με απλές κλήσεις TextOut και έπειτα να απλώσετε ένα ορθογώνιο AddURILink πάνω από κάθε γραμμή — η καλύτερη διαδρομή όταν το κείμενο παράγεται ήδη από τη δική σας λογική αναδίπλωσης λέξεων, κάτι που μας φέρνει σε αυτή τη συνάρτηση

AddURILink: περιοχές κλικ πάνω σε οτιδήποτε σχεδιάσατε

Η PrintHyperlink είναι ένα περιτύλιγμα ευκολίας: σχεδιάζει τη δική της ετικέτα και παράγει το ορθογώνιο από τις μετρικές αυτής της ετικέτας. Η AddURILink είναι το χαμηλότερου επιπέδου μισό, εκτεθειμένο απευθείας:

function AddURILink(Rectangle: TRect; const URL: AnsiString;
  const Description: AnsiString = ''): THPDFDictionaryObject;

Γράφει μόνο τον σχολιασμό — δεν σχεδιάζεται κείμενο και δεν αλλάζει χρώμα. Το Rectangle ερμηνεύεται στον ίδιο χώρο συντεταγμένων με τις κλήσεις σχεδίασής σας, οπότε μπορείτε να επαναχρησιμοποιήσετε τις ακριβείς τιμές X/Y που περάσατε στην TextOut ή σε μια κλήση εικόνας. Αυτό το καθιστά το σωστό εργαλείο όποτε το ορατό περιεχόμενο υπάρχει ήδη: ένα hotspot εικόνας, ένα κελί πίνακα, ένα μπλοκ κειμένου που σχεδιάστηκε νωρίτερα, ή μία γραμμή μιας αναδιπλωμένης παραγράφου όπως στη λύση παραπάνω. Ο σχολιασμός φέρει περίγραμμα μηδενικού πλάτους, οπότε τίποτα ορατό δεν αλλάζει· η περιοχή κλικ είναι ακριβώς το ορθογώνιο που καθορίζετε

Η συνάρτηση επιστρέφει το λεξικό του σχολιασμού ως THPDFDictionaryObject. Οι περισσότεροι καλούντες απορρίπτουν το αποτέλεσμα, αλλά η διατήρησή του σας επιτρέπει να προσαρμόσετε τις καταχωρίσεις του σχολιασμού πριν γραφτεί το έγγραφο

Δύο λεπτομέρειες συμμόρφωσης είναι ενσωματωμένες. Στις λειτουργίες PDF/A η σημαία εκτύπωσης του σχολιασμού ορίζεται όπως απαιτούν αυτά τα πρότυπα. Υπό PDFUACompliance η παράμετρος Description πρέπει να είναι μη κενή συμβολοσειρά — γίνεται η καταχώριση /Contents του σχολιασμού, που είναι αυτό που εκφωνεί η υποστηρικτική τεχνολογία για τον σύνδεσμο — και η κλήση εγείρει εξαίρεση αντί να εκπέμψει σιωπηλά ένα μη συμμορφούμενο αρχείο. Η PrintHyperlink προηγείται αυτού του κανόνα και δεν επισυνάπτει περιγραφή, οπότε για έξοδο PDF/UA σχεδιάστε την ετικέτα με την TextOut και τοποθετήστε τον σχολιασμό με την AddURILink συν μια ουσιαστική περιγραφή

Ο κανόνας απόφασης είναι απλός: χρησιμοποιήστε την PrintHyperlink όταν ο σύνδεσμος είναι ένα σύντομο κομμάτι κειμένου που δεν έχετε σχεδιάσει ακόμη· χρησιμοποιήστε την AddURILink όταν η περιοχή κλικ ορίζεται από περιεχόμενο που σχεδιάζετε ή μετράτε εσείς

Εσωτερική πλοήγηση με την AddGoToLink

Τα εξωτερικά URL είναι μόνο το μισό από όσα κάνουν οι σχολιασμοί συνδέσμων. Το άλλο μισό είναι η πλοήγηση μέσα στο έγγραφο — ένας πίνακας περιεχομένων που μεταπηδά σε κεφάλαια, παραπομπές μεταξύ ενοτήτων. Το HotPDF το εκθέτει μέσω της AddGoToLink:

procedure AddGoToLink(Rectangle: TRect; TargetPageIndex: Integer;
  YPos: Single = -1; const Description: AnsiString = '');

Τρεις σημασιολογίες αξίζει να δηλωθούν με ακρίβεια, αφού καμία δεν μαντεύεται από την υπογραφή. Το TargetPageIndex ξεκινά από το μηδέν: η πρώτη σελίδα του εγγράφου είναι η σελίδα 0, σε αντιστοιχία με το CurrentPageNumber. Η σελίδα προορισμού πρέπει να υπάρχει ήδη όταν κάνετε την κλήση· αν ο δείκτης είναι εκτός εύρους, η διαδικασία επιστρέφει χωρίς να προσθέσει σχολιασμό — καμία εξαίρεση, κανένας σύνδεσμος, καμία προειδοποίηση. Για έναν πίνακα περιεχομένων που δείχνει προς τα εμπρός, δημιουργήστε πρώτα όλες τις σελίδες, έπειτα γυρίστε πίσω και προσθέστε τους συνδέσμους

Το YPos επιλέγει την κατακόρυφη θέση στη σελίδα προορισμού, στον ίδιο χώρο συντεταγμένων με τις κλήσεις σχεδίασής σας. Η προεπιλογή -1 (οποιαδήποτε αρνητική τιμή) γράφει μια μηδενική (null) συντεταγμένη προορισμού, λέγοντας στον προβολέα να κρατήσει την τρέχουσα κατακόρυφη θέση του όταν προσγειώνεται στη σελίδα προορισμού. Περάστε μια μη αρνητική τιμή και ο προβολέας κυλά ώστε αυτή η θέση να βρεθεί στην κορυφή του παραθύρου — χρησιμοποιήστε τη συντεταγμένη Y της επικεφαλίδας στην οποία συνδέετε. Το ζουμ μένει πάντα αμετάβλητο. Όπως και με την AddURILink, το Description πρέπει να είναι μη κενό υπό PDFUACompliance και γίνεται το εναλλακτικό κείμενο του συνδέσμου

HotPDF: Συνδεδεμένος πίνακας περιεχομένων χτισμένος με την AddGoToLink που δείχνει μεταπηδήσεις TargetPageIndex από το μηδέν, από τη σελίδα περιεχομένων σε σελίδες κεφαλαίων όπου κάθε επικεφαλίδα προσγειώνεται στην κορυφή του παραθύρου
Τα ορθογώνια εκτείνονται πέρα από το κείμενο ώστε να αποκρίνονται ολόκληρες σειρές, και ένα σταθερό Y προσγείωσης τοποθετεί κάθε επικεφαλίδα κεφαλαίου στην κορυφή του παραθύρου
procedure BuildLinkedTOC(const FileName: string);
const
  Chapters: array[0..2] of string =
    ('Introduction', 'Installation', 'API Reference');
var
  Pdf: THotPDF;
  I, Y: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.BeginDoc;                        // η σελίδα 0 γίνεται η σελίδα περιεχομένων

    // Δημιουργήστε πρώτα τις σελίδες κεφαλαίων ώστε να υπάρχουν οι προορισμοί των συνδέσμων
    for I := 0 to High(Chapters) do
    begin
      Pdf.AddPage;                       // σελίδες 1..3
      Pdf.CurrentPage.SetFont('Arial', [fsBold], 14);
      Pdf.CurrentPage.TextOut(50, 780, 0, Chapters[I]);
    end;

    // Γυρίστε στη σελίδα 0 και σχεδιάστε τις εγγραφές περιεχομένων με τους συνδέσμους τους
    Pdf.CurrentPageNumber := 0;
    Pdf.CurrentPage.SetFont('Arial', [fsBold], 16);
    Pdf.CurrentPage.TextOut(50, 760, 0, 'Contents');
    Pdf.CurrentPage.SetFont('Arial', [], 11);

    Y := 720;
    for I := 0 to High(Chapters) do
    begin
      Pdf.CurrentPage.TextOut(70, Y, 0, Chapters[I]);
      Pdf.CurrentPage.AddGoToLink(
        Rect(70, Y + 14, 300, Y - 3),    // καλύπτει την εγγραφή με περιθώριο
        I + 1,                           // από το μηδέν: τα κεφάλαια είναι οι σελίδες 1..3
        780,                             // προσγείωση με την επικεφαλίδα στην κορυφή
        AnsiString('Go to ' + Chapters[I]));
      Y := Y - 25;
    end;

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

Κάθε εγγραφή παίρνει ένα ορθογώνιο πλατύτερο από το κείμενο ώστε ολόκληρη η σειρά να αποκρίνεται στον δείκτη, και κάθε σύνδεσμος προσγειώνεται με την επικεφαλίδα του κεφαλαίου (σχεδιασμένη στο Y=780) στην κορυφή του παραθύρου. Αν αργότερα εισαγάγετε μια σελίδα πριν από τα κεφάλαια, κάθε TargetPageIndex μετατοπίζεται κατά ένα· υπολογίστε τους δείκτες από τον βρόχο δημιουργίας σελίδων σας αντί να τους κωδικοποιείτε σταθερά

Ένα πλήρες παράδειγμα δημιουργίας εγγράφου

Το παρακάτω μοτίβο δείχνει ένα πιο ρεαλιστικό σενάριο: τη δημιουργία μιας σύντομης αναφοράς με ενότητα κεφαλίδας, κείμενο σώματος και μια σειρά συνδέσμων στο υποσέλιδο, όλα από κώδικα αντί από μια φόρμα με πεδία 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;

    // Κεφαλίδα
    Pdf.CurrentPage.SetFont('Arial', [fsBold], 16);
    Pdf.CurrentPage.TextOut(50, 750, 0, WideString(ProductName));

    // Θέση για παράγραφο σώματος
    Pdf.CurrentPage.SetFont('Arial', [], 11);
    Pdf.CurrentPage.TextOut(50, 710, 0, 'See the links below for full documentation.');

    // Σύνδεσμοι υποσέλιδου
    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 σε μια νέα σελίδα, το ορθογώνιο σχολιασμού θα υπολογιστεί με βάση όποιες κι αν είναι οι προεπιλεγμένες μετρικές της σελίδας, οι οποίες μπορεί να διαφέρουν από αυτό που περιμένετε

Πού διαφέρει ο χειρισμός σχολιασμών μεταξύ προβολέων

Οι σχολιασμοί URI του PDF ορίζονται στο ISO 32000-1 §12.6.4.7, και κάθε συμμορφούμενος προβολέας θα πρέπει να τους ακολουθεί. Στην πράξη, μερικές συμπεριφορές διαφέρουν ανά προβολέα. Το Adobe Acrobat εμφανίζει μια προτροπή ασφαλείας στο πρώτο κλικ για URL που δεν βρίσκονται στη λίστα αξιόπιστων τομέων· πολλά προγράμματα περιήγησης και ελαφριοί αναγνώστες δεν το κάνουν. Ορισμένοι εταιρικοί προβολείς PDF σε κλειδωμένα περιβάλλοντα απενεργοποιούν εντελώς τους σχολιασμούς URI βάσει πολιτικής, οπότε ένα κλικ δεν κάνει τίποτα, χωρίς ορατό σφάλμα. Οι εφαρμογές PDF για κινητά διαφέρουν ως προς το αν ανοίγουν συνδέσμους μέσα στην προβολή web της εφαρμογής ή τους παραδίδουν στο πρόγραμμα περιήγησης του συστήματος

Κανένα από αυτά δεν είναι σφάλμα που μπορείτε να διορθώσετε από την πλευρά της δημιουργίας· είναι αποφάσεις πολιτικής του προβολέα. Αυτό που μπορείτε να κάνετε είναι να γράφετε ετικέτες συνδέσμων που κάνουν το URL ορατό και στο σώμα του εγγράφου, ώστε ένας αναγνώστης σε περιορισμένο περιβάλλον να μπορεί ακόμη να αντιγράψει τη διεύθυνση χειροκίνητα. Ο σχολιασμός είναι η ευκολία· το κείμενο είναι η εφεδρεία

Μια ακόμη λεπτομέρεια που αξίζει να γνωρίζετε: οι σχολιασμοί URI του PDF δεν φέρουν από προεπιλογή καμία οπτική υπογράμμιση. Η υπογράμμιση που βλέπετε στους περισσότερους προβολείς σχεδιάζεται από τον ίδιο τον προβολέα με βάση τον τύπο σχολιασμού, όχι από μια γλυφή στη ροή περιεχομένου. Αν χρειάζεστε μια φυσική υπογράμμιση που επιβιώνει στην εκτύπωση σε μη διαδραστικό αποδότη ή στη μετατροπή PDF σε εικόνα, σχεδιάστε τη ρητά με LineTo και Stroke στην κατάλληλη μετατόπιση Y κάτω από τη γραμμή βάσης του κειμένου. Αυτή είναι μια ξεχωριστή λειτουργία σχεδίασης, όχι κάτι που χειρίζεται για εσάς η PrintHyperlink

Το API υπερσυνδέσμων που παρουσιάζεται εδώ είναι μέρος του HotPDF Delphi Component για Delphi και C++Builder