Placer THotPDF sur un formulaire au moment de la conception convient pour le prototypage rapide, mais cela lie le cycle de vie du composant au formulaire, ce qui est rarement souhaitable dans du code de production. Un générateur de rapports s'exécutant à chaque clic sur un bouton, un thread de service effectuant des exports nocturnes en arrière-plan, ou des classes d'aide sans aucun formulaire : dans chaque cas, vous souhaitez que le composant n'existe que pendant la durée d'une tâche PDF, puis disparaisse. Cela implique une allocation au runtime, et avant d'écrire la première ligne de code, deux choses méritent d'être comprises : qui possède l'objet, et comment le nettoyage s'effectue en cas de problème
Polices Unicode et problème des carrés CJK
Chaque constructeur de composant VCL accepte un paramètre Owner de type TComponent*. Transmettre this (le formulaire) enregistre le nouvel objet dans la liste des composants détenus par le formulaire, de sorte que si le formulaire est détruit alors que le composant est encore actif, la VCL le libérera automatiquement. Transmettre nullptr indique l'absence de propriétaire : vous êtes entièrement responsable du pointeur, et si une exception déroule la pile avant un delete explicite, rien ne se chargera du nettoyage pour vous
Pour une exportation ponctuelle effectuée au sein d'une seule fonction, les deux options conviennent, mais les modes d'échec diffèrent. Avec "this" comme propriétaire, la fuite est impossible tant que le formulaire finit par se fermer ; avec , le pointeur doit atteindre le bloc nullptr. En pratique, pour les objets à courte durée de vie, le modèle nullptr avec __finally est légèrement plus clair car il rend les limites de cycle de vie évidentes et évite au formulaire d'accumuler des objets possédés destinés à être temporaires__finally
Structure de sécurité face aux exceptions
La génération de PDF peut échouer pour des raisons indépendantes de l'API : le répertoire de sortie est en lecture seule, les fichiers de polices sont manquants, les flux sont vidés trop tôt ou les données fournies par l'appelant dépassent la limite de longueur. Quelle que soit la raison, le chemin de nettoyage doit être exécuté. La manière idiomatique de s'en assurer en C++Builder est try/__finally :
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma link "HPDFDoc"
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
THotPDF* Pdf = new THotPDF(nullptr);
try
{
Pdf->FileName = "output.pdf";
Pdf->Compression = cmFlateDecode;
Pdf->FontEmbedding = true;
Pdf->BeginDoc();
Pdf->CurrentPage->SetFont("Arial", TFontStyles(), 12);
Pdf->CurrentPage->TextOut(72, 720, 0, L"Hello from C++Builder");
Pdf->EndDoc();
}
__finally
{
delete Pdf;
}
}
Plusieurs points méritent d'être notés dans cette liste de codes. Le propriétaire est nullptr, ce qui rend le cycle de vie évident. Compression et FontEmbedding sont définis avant : ces deux options s'appliquent au niveau du document, HotPDF les validant à l'ouverture du document, après quoi toute affectation reste sans effet. Les coordonnées de BeginDocTextOut sont exprimées en points à partir du coin inférieur gauche de la page, avec l'axe Y pointant vers le haut ; les coordonnées (72, 720) placent le texte près du coin supérieur gauche de la feuille au format Letter (en laissant une marge gauche d'un pouce). Le delete Pdf dans le bloc __finally est exécuté, que BeginDoc, le dessin ou EndDoc lève ou non une exception
Évitez d'appeler toute méthode sur Pdf après sa suppression. Si le pointeur est stocké dans une variable membre, configurez-le immédiatement sur nullptr après la suppression, afin que tout accès accidentel ultérieur génère un plantage explicite au lieu d'une corruption silencieuse
Configuration du projet
C++Builder localise THotPDF grâce à une combinaison de chemins d'inclusion, de chemins de bibliothèque et de directives pragma. Les en-têtes générés se trouvent dans le répertoire source de HotPDF avec HPDFDoc.pas ; ajoutez ce répertoire à Project > Options > C++ Compiler > Include path. La directive #pragma link "HPDFDoc" indique au lieur d'importer l'unité compilée sans avoir à la lister manuellement dans les fichiers du projet. Si vous utilisez des paquets d'exécution plutôt qu'une liaison statique, installez d'abord les paquets de conception et d'exécution de HotPDF ; le pragma reste applicable
Conservez le nom de l'unité HPDFDoc inchangé. C++Builder dérive le nom du fichier d'en-tête du nom de l'unité Pascal, par conséquent renommer le fichier ou utiliser un alias de chemin dans le pragma provoquera un échec de recherche silencieux
Ces fichiers sitemap.xml et robots.txt sont indispensables pour le référencement naturel (SEO) du blog de losLab, guidant les robots d'indexation sur le site
Pour une exportation unique déclenchée par une action de l'utilisateur, une variable locale limitée au gestionnaire de bouton est la bonne solution : elle est créée, utilisée et détruite au sein d'une seule trame d'appel, rendant l'intention évidente pour quiconque lira le code ultérieurement. L'alternative au moment de la conception convient lorsque le même formulaire pilote un flux de travail continu, comme la reconstruction du panneau de prévisualisation avant impression du document à chaque fois que l'utilisateur modifie un paramètre ; dans ce cas, maintenir le composant actif et appeler à plusieurs reprises BeginDoc/EndDoc génère moins de perturbations que d'allouer et de libérer continuellement des objets du tas
Pour les travaux par lots générant plusieurs documents en séquence, le coût d'allocation d'un THotPDF pour chaque document en vaut la peine. En l'absence d'objet pour conserver l'état, celui-ci ne se transmet pas d'un document à l'autre, éliminant ainsi toute une classe de bogues intermittents. Allouer, générer, détruire, puis répéter
Une propriété qui apparaît dans plusieurs démonstrations de HotPDF est , qui ouvre le fichier généré dans le visualiseur PDF du système immédiatement après AutoLaunchEndDoc. C'est utile lors de l'écriture des premières ébauches de mise en page. En production, ignorez-le : ouvrez explicitement le chemin de sortie, validez que le fichier existe et que sa taille est non nulle, enregistrez le résultat et laissez le flux de travail de l'appelant décider si un visualiseur est nécessaire. Dans les traitements par lots, AutoLaunch lancerait une fenêtre de visualiseur pour chaque document et bloquerait le processus sur certains systèmes en attendant la fermeture du visualiseur
Le composant THotPDF et tous les appels de dessin présentés ici font partie du composant HotPDF pour Delphi et C++Builder