En PDF-fremviser i Delphi bunder i to komponenter og forbindelsen mellem dem. TPdf ejer dokumentet: den åbner filen, dekrypterer den og besvarer spørgsmål om sideantal og metadata. TPdfView er den visuelle kontrol, der tegner sider på skærmen og håndterer rulning, zoom og den side, brugeren i øjeblikket kigger på. PDFium Component indkapsler den samme renderingsmaskine, der leveres indeni Chrome, så de glyphs, anti-aliasing og farver, du får på dit lærred, matcher det, dine brugere allerede ser i deres browser. Arbejdet ligger ikke i renderingen. Det ligger i at forbinde dokumentobjektet til visningen, at indlæse uden at gå ned på en beskadiget eller adgangskodebeskyttet fil, og at give brugeren den håndfuld kontroller, der får en fremviser til at føles færdig: skift side, ændre zoom, tilpas siden til vinduet
Dette gennemgår denne samling i den rækkefølge, du rent faktisk bygger den. Alt her renderes en enkelt side ad gangen, hvilket er, hvad de fleste dokumentarbejdsgange ønsker. Hvis du har brug for sider stablet i en kontinuerligt rullende kolonne, er det en anden layoutbeslutning og ikke den vej, vi går her
Forbindelse af TPdf til TPdfView
Placer en TPdf og en TPdfView på formularen, og fortæl derefter visningen, hvilket dokument der skal vises. Denne ene tildeling er hele linket mellem det ikke-visuelle dokument og den kontrol, der tegner 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 noget af dette kører, skal det indfødte PDFium-bibliotek være på maskinen. PDFium Component kalder ind i pdfium32.dll eller pdfium64.dll afhængigt af din målplatform, og dokumentet nægter simpelthen at åbne, hvis DLL'en ikke kan findes. Lever den matchende DLL ved siden af din eksekverbare fil, eller placer den, hvor systemindlæseren vil finde den. De V8-aktiverede builds findes kun for PDF'er, der bærer JavaScript, du vil udføre, hvilket en simpel fremviser ikke gør, så ræk ud efter standard DLL'en, medmindre du har en konkret grund til at lade være
Indlæsning af et dokument uden at stole på inputtet
Instinktet er at pakke indlæsningen ind i en try/except og behandle en kastet undtagelse som en fejl. Det instinkt er forkert her, og at gøre det forkert producerer en fremviser, der ser fin ud, indtil nogen rækker den en ødelagt fil. At sætte Active := True kaster ikke en undtagelse ved en indlæsningsfejl. PDFium Component fanger den interne fejl og efterlader Active stående på False, så den eneste ærlige måde at vide, om dokumentet åbnede, er at læse egenskaben tilbage, efter du har sat 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 fortjener opmærksomhed. Den første er, at PageNumber eksisterer på begge objekter, og de to er uafhængige. Pdf.PageNumber er dokumentets opfattelse af en aktuel side; PdfView.PageNumber er den side, kontrollen rent faktisk viser, og det er den, du sætter for at flytte brugeren gennem filen. At sætte den ene flytter ikke den anden, så en fremviser driver altid visningens egenskab. Den anden er den 1-baserede indeksering: sider løber fra 1 til Pdf.PageCount, ikke fra 0, hvilket fanger enhver, der er vant til nul-baserede arrays
Håndtering af en krypteret fil
Krypterede dokumenter foldes ind i den samme indlæsningssti. Hvis åbne-adgangskoden er indstillet før aktivering, dekrypteres dokumentet, når det åbnes; hvis den er forkert eller mangler, forbliver Active på False præcis, som den gør for en beskadiget fil. Så gendannelsen er at anmode om en adgangskode og prøve aktiveringen igen
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 fejlen er stille for både en dårlig adgangskode og en beskadiget fil, kan du ikke adskille de to alene ud fra Active. I praksis er det acceptabelt for en fremviser: brugeren angiver enten den rigtige adgangskode eller lærer, at filen ikke vil åbne, og beskeden lyder ens uanset hvad
Gennembladring af dokumentet
Når dokumentet er åbent, er navigation aritmetik på PdfView.PageNumber begrænset af Pdf.PageCount. Det eneste reelle arbejde er at fastspænde, så knapperne aldrig skubber siden uden for rækkevidde, og den første og sidste knap forbliver deaktiveret i enderne af filen
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 kald fodret fra et parset heltal, og fastspændingen dækker tilfældet, hvor brugeren skriver 9999 i en fil på ti sider. Behold UpdatePageLabel som det eneste sted, der skriver "Side 3 af 12", så udlæsningen aldrig driver ud af synkronisering med, hvad visningen viser
Zoom: eksplicitte procenter og tilpasningstilstande
Zoom på TPdfView kommer i to varianter, der interagerer, og at forstå interaktionen er forskellen mellem en zoomkontrol, der opfører sig pænt, og en, der kæmper mod brugeren. Den direkte rute er egenskaben Zoom, en procentdel hvor 100 betyder faktisk størrelse. Den anden rute er FitMode, som fortæller visningen at beregne zoomen for dig og fortsætte med at genberegne den, når vinduet ændrer 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 del, der snyder folk. Direkte tildeling af Zoom nulstiller FitMode til pfmNone. Det er korrekt adfærd, ikke en fejl: i det øjeblik brugeren vælger præcis 150 %, kan visningen ikke længere samtidig ære "tilpas til bredde," fordi de to anmodninger er i konflikt. Konsekvensen for din brugergrænseflade er, at en zoom-ind-knap og en tilpas-til-side-knap er udelukkende tilstande, og værktøjslinjen bør gøre den aktive tilstand synlig. Når brugeren klikker på tilpas-til-side, skal du sætte FitMode; når de klikker på en numerisk zoom, skal du sætte Zoom og lade den rydde tilpasningstilstanden på egen hånd
Hvis du hellere selv vil beregne tilpasningsværdien, måske for at indstille en zoomskyder med den aktuelle tilpasningsprocent, giver pr.-side-hjælperne dig tallene uden at ændre tilstanden. PageWidthZoom[N], PageZoom[N] og ActualSizeZoom[N] returnerer den procentdel, der ville tilpasse side N til bredden, tilpasse den som helhed, eller rendere 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;
Hvad en færdig fremviser egentlig har brug for
Ovenstående fremviser er et par dusin linjer, og den gør allerede det arbejde, en dokumentarbejdsgang kræver: åbne en fil, overleve en dårlig, vise en side, flytte mellem sider og ændre forstørrelsen manuelt eller ved tilpasning. PDFium klarer de svære dele i stilhed. Indlejrede skrifttyper løses, annotationer og formularfelter males, hvor dokumentet placerer dem, og den side, du ser, matcher den, en Chrome-bruger ville se, fordi det er den samme maskine, der tegner begge
Ud fra denne base er tilføjelserne trinvise snarere end strukturelle. Tekstvalg og søgning læser fra det samme tekstlag, som PDFium allerede bygger; metadata som Pdf.Title og Pdf.Author er én egenskabslæsning væk; rotation og gråtone er render-indstillinger, du overfører, når du tegner en side til et bitmap. Ingen af disse ændrer den rygrad, du har her, som er dokumentobjektet, visningen og indlæs-derefter-naviger flowet, der forbinder dem. Få den rygrad rigtig, og resten er dekoration
TPdf og TPdfView komponenterne, der bruges overalt, er en del af PDFium Component for Delphi og C++Builder, som har den fulde fremviser-reference på sin produktside