Et PDF-visningsprogram i Delphi koker ned til to komponenter og kablingen mellom dem. TPdf eier dokumentet: det åpner filen, dekrypterer den og svarer på spørsmål om sideantall og metadata. TPdfView er den visuelle kontrollen som maler sider på skjermen og håndterer rulling, zoom og siden brukeren ser på for øyeblikket. PDFium-komponenten pakker inn den samme gjengivelsesmotoren som leveres inni Chrome, så glyfene, anti-aliasingen og fargen du får på lerretet samsvarer med det brukerne dine allerede ser i nettleseren sin. Arbeidet ligger ikke i gjengivelsen. Det ligger i å koble dokumentobjektet til visningen, laste inn uten å krasje på en skadet eller passordbeskyttet fil, og gi brukeren den håndfullen kontroller som får et visningsprogram til å føles ferdig: bla om siden, endre zoomen, tilpass siden til vinduet
Dette går gjennom den sammensetningen i den rekkefølgen du faktisk bygger den. Alt her gjengir én enkelt side om gangen, som er det de fleste dokumentarbeidsflyter ønsker. Hvis du trenger sider stablet i én kontinuerlig rullende kolonne, er det en annen layoutbeslutning og ikke stien her
Koble TPdf til TPdfView
Slipp en TPdf og en TPdfView på skjemaet, og fortell deretter visningen hvilket dokument som skal vises. Den ene tildelingen er hele koblingen mellom det ikke-visuelle dokumentet og kontrollen som maler det
procedure TFormMain.FormCreate(Sender: TObject);
begin
// Pdf and PdfView were dropped at design time.
PdfView.Pdf := Pdf; // the view paints whatever this document holds
PdfView.FitMode := pfmFitWidth; // start the user at a sensible zoom
end;
Før noe av dette kjører, må PDFium-biblioteket være på maskinen. PDFium-komponenten kaller inn i pdfium32.dll eller pdfium64.dll avhengig av målplattformen din, og dokumentet nekter rett og slett å åpne hvis DLL-en ikke kan bli funnet. Send med den samsvarende DLL-en ved siden av den kjørbare filen din, eller plasser den der systemlasteren vil finne den. Byggene med V8-støtte eksisterer bare for PDF-er som bærer JavaScript du vil kjøre, noe et rent visningsprogram ikke gjør, så strekk deg etter standard DLL med mindre du har en konkret grunn til å la være
Laste inn et dokument uten å stole på inndataene
Instinktet er å pakke innlastingen i en try/except og behandle et kastet unntak som feil. Det instinktet er feil her, og å ta feil gir et visningsprogram som ser bra ut helt til noen gir den en ødelagt fil. Å sette Active := True hever ikke noe ved en innlastingsfeil. PDFium-komponenten fanger opp den interne feilen og lar Active sitte på False, så den eneste ærlige måten å vite om dokumentet åpnet seg er å lese egenskapen tilbake etter at du har satt den
procedure TFormMain.OpenDocument(const FileName: string);
begin
Pdf.FileName := FileName;
Pdf.Active := True; // never raises; failure leaves Active = False
if not Pdf.Active then
begin
ShowMessage('Could not open ' + FileName);
Exit;
end;
PdfView.PageNumber := 1; // the view tracks its own current page
UpdatePageLabel;
end;
To ting krever oppmerksomhet. Det første er at PageNumber eksisterer på begge objektene, og de to er uavhengige. Pdf.PageNumber er dokumentets forestilling om en gjeldende side; PdfView.PageNumber er siden kontrollen faktisk viser, og det er den du stiller inn for å flytte brukeren gjennom filen. Å sette den ene flytter ikke den andre, så et visningsprogram driver alltid visningens egenskap. Det andre er den 1-baserte indekseringen: sider løper fra 1 til Pdf.PageCount, ikke fra 0, noe som fanger alle som er vant til nullbaserte matriser
Håndtering av en kryptert fil
Krypterte dokumenter foldes inn i samme innlastingsbane. Hvis åpningspassordet er satt før aktivering, dekrypteres dokumentet etter hvert som det åpnes; hvis det er feil eller mangler, forblir Active False akkurat som det gjør for en korrupt fil. Så gjenopprettingen er å be om et passord og prøve aktiveringen igjen
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; // must be set before 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;
Fordi feilen er stille for både et dårlig passord og en skadet fil, kan du ikke skille de to fra hverandre utelukkende fra Active. I praksis er det akseptabelt for et visningsprogram: brukeren oppgir enten riktig passord eller lærer at filen ikke vil åpne, og meldingen lyder likt uansett
Bla gjennom dokumentet
Med dokumentet åpent er navigasjon aritmetikk på PdfView.PageNumber avgrenset av Pdf.PageCount. Det eneste virkelige arbeidet er klamming (clamping), slik at knappene aldri skyver siden utenfor området, og den første og den siste knappen forblir deaktivert ved filens ender
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;
// the four navigation buttons reduce to one call each
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;
En "gå til side N"-tekstboks er det samme GoToPage-kallet matet fra et tolket heltall, og klammen dekker tilfellet der brukeren skriver inn 9999 i en tisiders fil. Behold UpdatePageLabel som det ene stedet som skriver "Side 3 av 12", slik at avlesningen aldri driver ut av synkronisering med det visningen viser
Zoom: eksplisitte prosenter og passformmoduser
Zoom på TPdfView kommer i to smaker som samhandler, og å forstå samhandlingen er forskjellen mellom en zoomkontroll som oppfører seg bra og en som kjemper mot brukeren. Den direkte ruten er Zoom-egenskapen, en prosentandel der 100 betyr faktisk størrelse. Den andre ruten er FitMode, som ber visningen om å beregne zoomen for deg og fortsette å beregne den på nytt når vinduet endrer størrelse
// fixed magnifications
PdfView.Zoom := 100; // actual size
PdfView.Zoom := 50; // half
PdfView.Zoom := 200; // double
// let the view size the page to the window, and keep it sized on resize
PdfView.FitMode := pfmFitWidth; // page width fills the control
PdfView.FitMode := pfmFitPage; // whole page visible
PdfView.FitMode := pfmActualSize; // 1:1 with the document's points
Her er den delen som feller folk. Å tilordne Zoom direkte tilbakestiller FitMode til pfmNone. Det er riktig oppførsel, ikke en feil: det øyeblikket brukeren velger nøyaktig 150 %, kan visningen ikke lenger også respektere "tilpass til bredde", fordi de to forespørslene er i konflikt. Konsekvensen for brukergrensesnittet ditt er at en zoom-inn-knapp og en tilpass-til-side-knapp er gjensidig utelukkende tilstander, og verktøylinjen bør gjøre den aktive modusen synlig. Når brukeren klikker tilpass-til-side, sett FitMode; når de klikker på en numerisk zoom, sett Zoom og la den fjerne passformmodusen på egen hånd
Hvis du heller vil beregne passformverdien selv, kanskje for å så en zoomglidebryter med gjeldende passformprosent, gir hjelperne per side deg tallene uten å endre modusen. PageWidthZoom[N], PageZoom[N] og ActualSizeZoom[N] returnerer prosentandelen som ville passe side N til bredden, passe den hel, eller gjengi den i faktisk størrelse
// seed a zoom readout from the fit-to-width value of the current page
var
FitPercent: Double;
begin
FitPercent := PdfView.PageWidthZoom[PdfView.PageNumber];
ZoomEdit.Text := Format('%.0f%%', [FitPercent]);
end;
Hva et ferdig visningsprogram faktisk trenger
Visningsprogrammet ovenfor er noen få dusin linjer, og det gjør allerede den jobben en dokumentarbeidsflyt trenger: åpne en fil, overleve en dårlig en, vise en side, bevege seg mellom sider, og endre forstørrelsen for hånd eller med passform. PDFium gjør de vanskelige delene stille. Innebygde skrifttyper løses opp, merknader og skjemafelt males der dokumentet plasserer dem, og siden du ser samsvarer med den en Chrome-bruker ville se, fordi det er den samme motoren som tegner begge
Fra denne basen er tilleggene inkrementelle snarere enn strukturelle. Tekstvalg og søk leser fra det samme tekstlaget PDFium allerede bygger; metadata som Pdf.Title og Pdf.Author er én egenskapslesing unna; rotasjon og gråskala er gjengivelsesalternativer du sender når du tegner en side til et bitkart. Ingen av disse endrer ryggraden du har her, som er dokumentobjektet, visningen og last-inn-og-naviger-flyten som forbinder dem. Få den ryggraden riktig, og resten er dekorasjon
Komponentene TPdf og TPdfView som brukes gjennomgående er en del av PDFium-komponenten for Delphi og C++Builder, som bærer den fulle visningsreferansen på sin produktside