PDF peržiūros programa Delphi susideda iš dviejų komponentų ir jų tarpusavio sujungimo. TPdf valdo dokumentą: jis atidaro failą, jį iššifruoja ir pateikia informaciją apie puslapių skaičių bei metaduomenis. TPdfView yra vizualinis valdiklis, kuris piešia puslapius ekrane ir valdo slinkimą, mastelį bei puslapį, kurį vartotojas šiuo metu žiūri. PDFium Component apgaubia tą patį atvaizdavimo variklį, kuris pateikiamas kartu su Chrome, todėl glifai, glotninimas (anti-aliasing) ir spalvos drobėje atitinka tai, ką jūsų vartotojai jau mato savo naršyklėje. Didžiausias darbas yra ne pats atvaizdavimas. Tai yra dokumento objekto prijungimas prie peržiūros valdiklio, saugus įkėlimas išvengiant programos lūžių esant sugadintam ar slaptažodžiu apsaugotam failui ir keleto pagrindinių valdymo elementų pateikimas vartotojui: puslapio vertimas, mastelio keitimas, puslapio pritaikymas prie lango
Šiame straipsnyje apžvelgiamas šis kūrimo procesas ta tvarka, kuria jį atliksite. Viskas čia atvaizduoja po vieną puslapį vienu metu, ko paprastai ir reikalauja dauguma dokumentų apdorojimo procesų. Jei jums reikia puslapių, išdėstytų viename nepertraukiamai slenkamame stulpelyje, tai yra kitoks maketo sprendimas, aprašytas atskirame straipsnyje, ir čia jis nenagrinėjamas
TPdf sujungimas su TPdfView
Perkelkite TPdf ir TPdfView į formą, tada nurodykite peržiūros valdikliui, kurį dokumentą rodyti. Šis vienas priskyrimas yra visa jungtis tarp nevizualaus dokumento ir jį piešiančio valdiklio
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;
Prieš paleidžiant programą, kompiuteryje turi būti įdiegta vietinė PDFium biblioteka. PDFium Component kreipiasi į pdfium32.dll arba pdfium64.dll, priklausomai nuo jūsų tikslinės platformos, o dokumentas tiesiog neatsidarys, jei ši DLL biblioteka nebus rasta. Platinamą DLL failą pateikite šalia vykdomojo failo arba padėkite jį ten, kur jį ras sistemos įkėliklis. V8 versijos reikalingos tik tiems PDF failams, kuriuose yra JavaScript kodas, kurį norite vykdyti (ko nereikia paprastam peržiūros įrankiui), todėl rinkitės standartinį DLL, nebent turite konkrečių priežasčių elgtis kitaip
Dokumento įkėlimas nepasitikint įvestimi
Pirmasis impulsas yra apgaubti įkėlimą su try/except bloku ir laikyti kilusią išimtį nesėkme. Šis impulsas čia yra klaidingas, o jį pritaikius peržiūros programa veiks gerai tik tol, kol kas nors pateiks sugadintą failą. Nustatymas Active := True nesukelia išimties įkėlimo nesėkmės atveju. PDFium Component pati sugauna vidinę klaidą ir palieka Active reikšmę ties False, todėl vienintelis patikimas būdas sužinoti, ar dokumentas atsidarė, yra perskaityti šią savybę ją nustačius
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;
Du dalykai reikalauja dėmesio. Pirmasis – savybė PageNumber egzistuoja abiejuose objektuose ir jie yra nepriklausomi. Pdf.PageNumber yra dokumento supratimas apie dabartinį puslapį; PdfView.PageNumber yra puslapis, kurį valdiklis yra faktiškai rodantis, ir būtent jį nustatote norėdami perkelti vartotoją per failą. Vieno nustatymas neperkelia kito, todėl peržiūros programa visada valdo peržiūros valdiklio savybę. Antrasis dalykas – indeksavimas prasideda nuo 1: puslapiai numeruojami nuo 1 iki Pdf.PageCount, o ne nuo 0, kas gali klaidinti tuos, kurie pripratę prie nulinio indeksavimo
Šifruoto failo apdorojimas
Šifruoti dokumentai įkeliami tuo pačiu būdu. Jei slaptažodis yra nustatomas prieš aktyvavimą, atidarant dokumentas iššifruojamas; jei slaptažodis neteisingas arba jo trūksta, Active lieka False, lygiai taip pat, kaip ir sugadinto failo atveju. Sprendimas – paprašyti slaptažodžio ir bandyti aktyvuoti vėl
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;
Kadangi įvykus nesėkmei tiek dėl blogo slaptažodžio, tiek dėl sugadinto failo klaida pranešama tyliai, negalite jų atskirti vien tik pagal Active reikšmę. Praktikoje peržiūros programai tai yra priimtina: vartotojas arba pateikia teisingą slaptažodį, arba sužino, kad failas neatsidaro, o pranešimas abiem atvejais skamba vienodai
Puslapių vertimas dokumente
Kai dokumentas atidarytas, navigacija yra aritmetinis veiksmas su PdfView.PageNumber, kurio ribas nustato Pdf.PageCount. Vienintelis darbas yra ribojimas, kad mygtukai niekada neišstumtų puslapio už leistinų ribų, o pirmasis bei paskutinis mygtukai liktų neaktyvūs failo pradžioje ir pabaigoje
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;
Laukas „eiti į puslapį N“ yra tas pats GoToPage iškvietimas, kuriam perduodamas išanalizuotas sveikasis skaičius, o ribojimas apsaugo nuo situacijos, kai vartotojas įveda 9999 dešimties puslapių faile. Palikite UpdatePageLabel kaip vienintelę vietą, kuri įrašo „Puslapis 3 iš 12“, kad rodmenys niekada nesiskirtų nuo to, ką rodo peržiūros valdiklis
Mastelis: konkretūs procentai ir pritaikymo režimai
Mastelio keitimas su TPdfView pateikiamas dviem būdais, kurie sąveikauja tarpusavyje, o šios sąveikos supratimas lemia, ar mastelio valdymas veiks tvarkingai, ar kovos su vartotoju. Tiesioginis kelias yra savybė Zoom – procentinė reikšmė, kur 100 reiškia tikrąjį dydį. Kitas kelias yra FitMode, nurodantis peržiūros valdikliui apskaičiuoti mastelį už jus ir jį perskaičiuoti pasikeitus lango dydžiui
// 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
Štai dalis, kurioje dažnai daromos klaidos. Tiesioginis Zoom nustatymas grąžina FitMode į pfmNone. Tai yra teisingas elgesys, o ne klaida: tą akimirką, kai vartotojas pasirenka tikslų 150% mastelį, valdiklis nebegali lygiuotis į „pritaikyti plotį“, nes šie du reikalavimai prieštarauja vienas kitam. Pasekmė jūsų vartotojo sąsajai – mastelio didinimo mygtukas ir puslapio pritaikymo mygtukas yra viena kitą šalinančios būsenos, todėl įrankių juostoje turėtų būti matomas aktyvus režimas. Kai vartotojas spusteli pritaikymą puslapiui, nustatykite FitMode; kai pasirenka skaitinį mastelį, nustatykite Zoom ir leiskite jam pačiam išvalyti pritaikymo režimą
Jei norite patys apskaičiuoti pritaikymo reikšmę, pavyzdžiui, užpildyti mastelio slankiklį dabartiniu pritaikymo procentu, kiekvienam puslapiui skirti pagalbiniai metodai suteikia šiuos skaičius nekeisdami režimo. PageWidthZoom[N], PageZoom[N] ir ActualSizeZoom[N] grąžina procentą, kuris pritaikytų puslapį N pagal plotį, rodytų jį visą arba atvaizduotų tikruoju dydžiu
// 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;
Ko iš tikrųjų reikia užbaigtai peržiūros programai
Originalus straipsnio pavadinimas šiek tiek padidina šį darbą. Aukščiau pateikta peržiūros programa susideda tik iš kelių dešimčių eilučių ir jau atlieka viską, ko reikia dokumentų apdorojimui: atidaro failą, išvengia lūžių esant blogam failui, rodo puslapį, perkelia tarp puslapių bei keičia mastelį rankiniu būdu ar automatiškai. PDFium atlieka visas sudėtingas dalis tyliai. Įterptieji šriftai atpažįstami, anotacijos ir formų laukai piešiami ten, kur juos nurodo dokumentas, o matomas puslapis atitinka tą, kurį matytų Chrome vartotojas, nes abiem atvejais piešia tas pats variklis
Nuo šio pagrindo bet kokie papildymai yra palaipsniai, o ne struktūriniai. Teksto žymėjimas ir paieška nuskaitomi iš to paties teksto sluoksnio, kurį PDFium jau sukuria; metaduomenys, tokie kaip Pdf.Title ir Pdf.Author, nuskaitomi viena savybe; pasukimas bei pilkumo pustoniai (grayscale) yra atvaizdavimo parinktys, kurias perduodate piešdami puslapį į taškinį paveikslėlį. Nė vienas iš šių dalykų nekeičia pagrindinės ašies, kurią čia turite: dokumento objekto, peržiūros valdiklio ir juos jungiančio įkėlimo bei navigacijos srauto. Tinkamai sutvarkykite šią ašį, o visa kita bus tik papildoma puošyba
Čia naudojami TPdf ir TPdfView komponentai yra PDFium Component, skirto Delphi ir C++Builder, dalis, o jo produkto puslapyje pateikiama išsami informacija apie peržiūros programos kūrimą