PDF-katseluohjelma Delphissä tiivistyy kahteen komponenttiin ja niiden väliseen kytkentään. TPdf omistaa dokumentin: se avaa tiedoston, purkaa salauksen, ja vastaa kysymyksiin sivumäärästä ja metatiedoista. TPdfView on visuaalinen ohjausobjekti, joka piirtää sivuja näytölle ja käsittelee vierityksen, zoomauksen, ja sivun, jota käyttäjä parhaillaan katsoo. PDFium Component kietoo sisäänsä saman hahmonnusmoottorin, joka toimitetaan Chromen sisällä, joten kankaalle saamanne glyyfit, reunanpehmennys, ja väri vastaavat sitä, mitä käyttäjänne jo näkevät selaimessaan. Työ ei ole hahmonnuksessa. Se on dokumenttiobjektin liittämisessä näkymään, lataamisessa kaatumatta vioittuneella tai salasanasuojatulla tiedostolla, ja käyttäjälle sen kourallisen hallintaelementtejä antamisessa, jotka saavat katseluohjelman tuntumaan valmiilta: käännä sivua, vaihda zoomausta, sovita sivu ikkunaan
Tämä käy läpi kyseisen kokoonpanon siinä järjestyksessä, jossa sen todella rakennatte. Kaikki tässä hahmontaa yhden sivun kerrallaan, mitä useimmat dokumenttien työnkulut haluavat. Jos tarvitsette sivut pinottuna yhteen jatkuvasti vierivään sarakkeeseen, se on eri asetteluratkaisu eikä tämän artikkelin polku
TPdf:n kytkeminen TPdfView:hen
Pudottakaa TPdf ja TPdfView lomakkeelle, ja kertokaa sitten näkymälle, mitä dokumenttia näyttää. Tuo yksittäinen sijoitus on koko linkki ei-visuaalisen dokumentin ja sitä piirtävän ohjausobjektin välillä
procedure TFormMain.FormCreate(Sender: TObject);
begin
// Pdf ja PdfView pudotettiin suunnitteluaikana.
PdfView.Pdf := Pdf; // näkymä piirtää mitä tahansa tämä dokumentti sisältää
PdfView.FitMode := pfmFitWidth; // aloita käyttäjä järkevässä zoomauksessa
end;
Ennen kuin mikään tästä toimii, PDFiumin natiivikirjaston on oltava koneella. PDFium Component kutsuu pdfium32.dll:ää tai pdfium64.dll:ää kohdealustastanne riippuen, ja dokumentti yksinkertaisesti kieltäytyy avautumasta, jos DLL:ää ei löydy. Toimittakaa vastaava DLL suoritettavan tiedostonne vierestä, tai sijoittakaa se paikkaan, josta järjestelmän lataaja sen löytää. V8-käyttöiset koontiversiot ovat olemassa vain PDF-tiedostoille, jotka kantavat JavaScriptiä, jota haluatte suorittaa, mitä tavallinen katseluohjelma ei tee, joten tarttukaa vakio-DLL:ään, ellei teillä ole konkreettista syytä olla tekemättä niin
Dokumentin lataaminen luottamatta syötteeseen
Vaisto on kietoa lataus try/except-lohkoon ja käsitellä heitetty poikkeus epäonnistumisena. Tuo vaisto on väärässä tässä, ja sen väärin ymmärtäminen tuottaa katseluohjelman, joka näyttää kunnossa olevalta, kunnes joku antaa sille rikkinäisen tiedoston. Active := True -asettaminen ei nosta poikkeusta latausvirheessä. PDFium Component nappaa sisäisen virheen ja jättää Active-arvon lukemaan False, joten ainoa rehellinen tapa tietää, avautuiko dokumentti, on lukea ominaisuus takaisin sen jälkeen, kun sen asetitte
procedure TFormMain.OpenDocument(const FileName: string);
begin
Pdf.FileName := FileName;
Pdf.Active := True; // ei koskaan nosta poikkeusta; epäonnistuminen jättää Active = False
if not Pdf.Active then
begin
ShowMessage('Could not open ' + FileName);
Exit;
end;
PdfView.PageNumber := 1; // näkymä seuraa omaa nykyistä sivuaan
UpdatePageLabel;
end;
Kaksi asiaa ansaitsee huomiota. Ensimmäinen on, että PageNumber on olemassa molemmissa objekteissa ja ne kaksi ovat riippumattomia. Pdf.PageNumber on dokumentin käsitys nykyisestä sivusta; PdfView.PageNumber on sivu, jota ohjausobjekti todellisuudessa näyttää, ja se on se, jota asetatte siirtääksenne käyttäjää tiedoston läpi. Toisen asettaminen ei liikuta toista, joten katseluohjelma ohjaa aina näkymän ominaisuutta. Toinen on 1-pohjainen indeksointi: sivut kulkevat 1:stä Pdf.PageCount:iin, ei 0:sta, mikä yllättää kenet tahansa, joka on tottunut nollapohjaisiin taulukoihin
Salatun tiedoston käsittely
Salatut dokumentit taipuvat samaan latauspolkuun. Jos avaussalasana asetetaan ennen aktivointia, dokumentti purkaa salauksensa avautuessaan; jos se on väärä tai puuttuu, Active pysyy arvossa False aivan kuten vioittuneella tiedostolla. Joten toipuminen on kysyä salasanaa ja yrittää aktivointia uudelleen
procedure TFormMain.OpenWithPassword(const FileName: string);
var
Password: string;
begin
Pdf.FileName := FileName;
Pdf.Active := True;
if not Pdf.Active then
begin
if InputQuery('Password required', 'Password:', Password) then
begin
Pdf.Password := Password; // on asetettava ennen Active := True
Pdf.Active := True;
end;
if not Pdf.Active then
begin
ShowMessage('Unable to open the document.');
Exit;
end;
end;
PdfView.PageNumber := 1;
end;
Koska epäonnistuminen on hiljainen sekä väärälle salasanalle että vioittuneelle tiedostolle, ette voi erottaa niitä kahta pelkästä Active-arvosta. Käytännössä se on hyväksyttävää katseluohjelmalle: käyttäjä joko antaa oikean salasanan tai saa tietää, ettei tiedosto avaudu, ja viesti lukee saman kummassakin tapauksessa
Dokumentin selaaminen sivu kerrallaan
Dokumentin ollessa auki, navigointi on aritmetiikkaa PdfView.PageNumber:lla, jota rajoittaa Pdf.PageCount. Ainoa todellinen työ on rajaus, jotta painikkeet eivät koskaan työnnä sivua alueen ulkopuolelle ja ensimmäinen ja viimeinen painike pysyvät poissa käytöstä tiedoston päissä
procedure TFormMain.GoToPage(NewPage: Integer);
begin
if not Pdf.Active then
Exit;
if NewPage < 1 then
NewPage := 1
else if NewPage > Pdf.PageCount then
NewPage := Pdf.PageCount;
PdfView.PageNumber := NewPage;
UpdatePageLabel;
end;
// neljä navigointipainiketta supistuvat kukin yhteen kutsuun
procedure TFormMain.FirstClick(Sender: TObject); begin GoToPage(1); end;
procedure TFormMain.PrevClick(Sender: TObject); begin GoToPage(PdfView.PageNumber - 1); end;
procedure TFormMain.NextClick(Sender: TObject); begin GoToPage(PdfView.PageNumber + 1); end;
procedure TFormMain.LastClick(Sender: TObject); begin GoToPage(Pdf.PageCount); end;
"Siirry sivulle N" -tekstiruutu on sama GoToPage-kutsu syötettynä jäsennetyllä kokonaisluvulla, ja rajaus kattaa tapauksen, jossa käyttäjä kirjoittaa 9999 kymmensivuiseen tiedostoon. Pitäkää UpdatePageLabel ainoana paikkana, joka kirjoittaa "Sivu 3/12", jotta lukema ei koskaan ajaudu pois synkronoinnista siitä, mitä näkymä näyttää
Zoomaus: tarkat prosentit ja sovitustilat
Zoomaus TPdfView:ssä saapuu kahtena muotona, jotka vaikuttavat toisiinsa, ja tuon vuorovaikutuksen ymmärtäminen on ero hyvin käyttäytyvän zoomaushallinnan ja käyttäjää vastaan taistelevan välillä. Suora reitti on Zoom-ominaisuus, prosenttiluku, jossa 100 tarkoittaa todellista kokoa. Toinen reitti on FitMode, joka kertoo näkymälle laskea zoomauksen puolestanne ja pitää sen laskemisen ajan tasalla ikkunan koon muuttuessa
// kiinteät suurennokset
PdfView.Zoom := 100; // todellinen koko
PdfView.Zoom := 50; // puolet
PdfView.Zoom := 200; // kaksinkertainen
// anna näkymän mitoittaa sivu ikkunaan, ja pitää se mitoitettuna koon muuttuessa
PdfView.FitMode := pfmFitWidth; // sivun leveys täyttää ohjausobjektin
PdfView.FitMode := pfmFitPage; // koko sivu näkyvissä
PdfView.FitMode := pfmActualSize; // 1:1 dokumentin pisteiden kanssa
Tässä on osa, joka kompastuttaa ihmisiä. Zoom-arvon suora asettaminen nollaa FitMode-arvon arvoon pfmNone. Se on oikeaa käytöstä, ei virhe: sillä hetkellä, kun käyttäjä valitsee tarkan 150 %:n, näkymä ei voi enää myöskään noudattaa "sovita leveyteen" -asetusta, koska nämä kaksi pyyntöä ovat ristiriidassa. Seuraus käyttöliittymällenne on, että zoomaa sisään -painike ja sovita sivulle -painike ovat toisensa poissulkevia tiloja, ja työkalupalkin tulisi tehdä aktiivinen tila näkyväksi. Kun käyttäjä napsauttaa sovita sivulle, asettakaa FitMode; kun hän napsauttaa numeerista zoomausta, asettakaa Zoom ja antakaa sen tyhjentää sovitustila itsestään
Jos haluatte mieluummin laskea sovitusarvon itse, ehkä alustaaksenne zoomausliukusäätimen nykyisellä sovitusprosentilla, sivukohtaiset apufunktiot antavat teille luvut muuttamatta tilaa. PageWidthZoom[N], PageZoom[N], ja ActualSizeZoom[N] palauttavat prosentin, joka sovittaisi sivun N leveyteen, sovittaisi sen kokonaan, tai hahmontaisi sen todellisessa koossa
// alusta zoomauslukema nykyisen sivun sovita-leveyteen-arvosta
var
FitPercent: Double;
begin
FitPercent := PdfView.PageWidthZoom[PdfView.PageNumber];
ZoomEdit.Text := Format('%.0f%%', [FitPercent]);
end;
Mitä valmis katseluohjelma todella tarvitsee
Yllä oleva katseluohjelma on muutama tusina rivejä, ja se jo hoitaa tehtävän, jota dokumenttien työnkulku tarvitsee: avaa tiedosto, selviää huonosta sellaisesta, näyttää sivun, liikkuu sivujen välillä, ja muuttaa suurennosta käsin tai sovituksella. PDFium hoitaa vaikeat osat hiljaa. Upotetut fontit ratkeavat, kommentit ja lomakekentät piirtyvät sinne, minne dokumentti ne sijoittaa, ja näkemänne sivu vastaa sitä, jonka Chrome-käyttäjä näkisi, koska sama moottori piirtää molemmat
Tästä pohjasta lisäykset ovat asteittaisia eivätkä rakenteellisia. Tekstin valinta ja haku lukevat samasta tekstikerroksesta, jonka PDFium jo rakentaa; metatiedot kuten Pdf.Title ja Pdf.Author ovat yhden ominaisuuden luvun päässä; kierto ja harmaasävy ovat hahmonnusasetuksia, jotka annatte, kun piirrätte sivun bittikarttaan. Mikään näistä ei muuta selkärankaa, joka teillä on täällä, joka on dokumenttiobjekti, näkymä, ja niitä yhdistävä lataa-sitten-navigoi-kulku. Saakaa se selkäranka oikein ja loput ovat koristeita
TPdf- ja TPdfView-komponentit, joita käytetään läpi tämän artikkelin, ovat osa PDFium Component -tuotetta Delphille ja C++Builderille, joka kantaa täyden katseluohjelmareferenssin tuotesivullaan