THotPDF-komponentin pudottaminen lomakkeelle (form) suunnitteluaikana sopii nopeaan prototyyppiin, mutta se sitoo komponentin lomakkeen elinkaareen, mikä on harvoin sitä, mitä tuotantokoodissa halutaan. Raporttigeneraattori, joka suoritetaan kerran napin painalluksella, palvelusäie, joka eräajaa vientiä yön yli, apuluokka, jolla ei ole lainkaan lomaketta: jokaisessa näistä tilanteista haluat komponentin olevan olemassa tasan yhden PDF-työn keston ajan ja sitten katoavan. Tämä tarkoittaa ajonaikaista varaamista, ja se muuttaa kahta asiaa, jotka on syytä ymmärtää ennen ensimmäisen rivin kirjoittamista: kuka omistaa objektin ja miten siivous tapahtuu, kun jokin menee pieleen
Omistajasemantiikka VCL:ssä
Jokainen VCL-komponentin konstruktori ottaa parametrin Owner, joka on tyyppiä TComponent*. Arvon this (lomake) välittäminen rekisteröi uuden objektin lomakkeen omistamien komponenttien luetteloon, joten jos lomake tuhotaan komponentin ollessa vielä elossa, VCL vapauttaa sen automaattisesti. Arvon nullptr välittäminen tarkoittaa, ettei omistajaa ole: otat yksinvastuun osoittimesta (pointer), eikä mikään siivoa sitä puolestasi, jos poikkeus purkaa pinon ennen nimenomaista delete-kutsuasi
Kertaluonteisessa viennissä (export), joka suoritetaan yhden funktion sisällä, kumpikin vaihtoehto toimii, mutta näillä kahdella on erilaiset vikatilat. Kun omistajana on this, vuoto on mahdoton niin kauan kuin lomake lopulta sulkeutuu; kun käytetään arvoa nullptr, osoittimen täytyy saavuttaa lohko __finally. Käytännössä malli nullptr plus __finally on hieman selkeämpi lyhytikäisille objekteille, koska se tekee elinkaaren rajan näkyväksi yhdellä silmäyksellä ja estää lomaketta keräämästä omistettuja objekteja, joiden oli tarkoitus olla tilapäisiä
Poikkeusturvallinen rakenne
PDF-generointi voi epäonnistua syistä, joilla ei ole mitään tekemistä API:n kanssa: tulostehakemisto on vain luku, fonttitiedosto puuttuu, virta (stream) tyhjentyy ennenaikaisesti tai kutsujan toimittamat tiedot ylittävät pituusrajan. Olipa syy mikä tahansa, siivouspolun on suoritettava. Idiomaattinen tapa taata tämä C++Builderissa on 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;
}
}
Muutama asia tässä listauksessa on mainitsemisen arvoinen. Omistaja on nullptr, mikä tekee elinkaaresta nimenomaisen. Compression ja FontEmbedding asetetaan ennen kutsua BeginDoc: molemmat ovat asiakirjatason vaihtoehtoja, jotka HotPDF sitoo, kun asiakirja avautuu, ja niiden määrittämisellä sen jälkeen ei ole vaikutusta. TextOut ottaa koordinaatit pisteinä mitattuna sivun vasemmasta alakulmasta, jossa Y kasvaa ylöspäin; pari 72, 720 sijoittaa tekstin letter-kokoisen sivun vasemman yläkulman lähelle yhden tuuman vasemmalla marginaalilla. delete Pdf lohkossa __finally suoritetaan riippumatta siitä, laukaisiko BeginDoc, piirtäminen tai EndDoc poikkeuksen vai ei
Vältä kutsumasta mitään menetelmää objektille Pdf kutsun delete jälkeen. Jos osoitin on tallennettu jäsenmuuttujaan, aseta se arvoon nullptr heti poiston jälkeen, jotta mahdollinen vahingossa tapahtuva myöhempi haku aiheuttaa puhtaan kaatumisen hiljaisen korruption sijaan
Projektin asetukset
C++Builder löytää THotPDF-luokan sisällytyspolkujen, kirjastopolkujen ja pragma-direktiivin yhdistelmän kautta. Generoitu otsikkotiedosto sijaitsee yhdessä HPDFDoc.pas-tiedoston kanssa HotPDF:n lähdehakemistossa; lisää kyseinen hakemisto kohtaan Project > Options > C++ Compiler > Include path. Direktiivi #pragma link "HPDFDoc" käskee linkittäjää vetämään käännetyn yksikön sisään ilman sen luetteloimista manuaalisesti projektitiedostossa. Jos käytät ajonaikaista (runtime) pakettia staattisen linkityksen sijasta, asenna ensin HotPDF-suunnittelu- ja ajonaikaiset paketit; pragma on silti voimassa
Pidä yksikön nimi HPDFDoc muuttumattomana. C++Builder johtaa otsikkotiedoston nimen Pascal-yksikön nimestä, joten tiedoston uudelleennimeäminen tai polkualiaksen käyttö pragmassa rikkoo haun hiljaisesti
Laajuus ja moniasiakirjaiset työt
Käyttäjän toimen käynnistämässä yksittäisessä viennissä painikkeen käsittelijään (button handler) rajoitettu paikallinen muuttuja on oikea vastaus: se luodaan, sitä käytetään ja se tuhotaan yhden kutsukehyksen sisällä, ja tarkoitus on ilmeinen kenelle tahansa koodia myöhemmin lukevalle. Suunnitteluaikainen (design-time) vaihtoehto on perusteltu, kun sama lomake ohjaa jatkuvaa työnkulkua, kuten tulostuksen esikatselupaneelia, joka rakentaa asiakirjan uudelleen aina, kun käyttäjä muuttaa asetusta; siinä tapauksessa komponentin elossa pitäminen ja menetelmien BeginDoc/EndDoc toistuva kutsuminen on vähemmän häiritsevää kuin keko-objektien (heap objects) toistuva varaaminen ja vapauttaminen
Eräajoissa, jotka tuottavat useita asiakirjoja järjestyksessä, yhden THotPDF-instanssin rajaaminen asiakirjaa kohden on varauskustannuksen arvoista. Tila ei siirry asiakirjojen välillä, jos ei ole objektia sitä kantamassa, ja tämä on yksi satunnaisten ohjelmistovirheiden luokka, jota sinun ei koskaan tarvitse korjata. Varaa, generoi, poista, toista
Yksi ominaisuus, joka esiintyy useissa HotPDF-demoissa, on AutoLaunch, joka avaa generoidun tiedoston järjestelmän PDF-katseluohjelmassa välittömästi kutsun EndDoc jälkeen. Se on hyödyllinen kirjoitettaessa asettelun ensimmäistä luonnosta. Tuotannossa ohita se: avaa tulostepolku nimenomaisesti, varmista, että tiedosto on olemassa ja että sen koko ei ole nolla, kirjaa tulos ja anna kutsuvan työnkulun päättää, onko katseluohjelma olennainen. Eräajossa AutoLaunch käynnistää yhden katseluikkunan jokaista asiakirjaa kohden ja estää prosessin jossain järjestelmissä sen odottaessa katseluohjelman sulkeutumista
THotPDF-komponentti ja kaikki tässä näytetyt piirtokutsut ovat osa HotPDF-komponenttia Delphille ja C++Builderille