Aynı anda açık iki belge, aynı sayfa numarası, her biri kendi kaydırılabilir panelinde: bir karşılaştırma görüntüleyicisinin özü budur. PDFium Component bunu, TPdf bileşeninin dosyaya, TPdfView bileşeninin ise görüntüye sahip olduğu yalın bir nesne modeliyle sunar. Bir belge, bir TPdf, bir TPdfView. Üç panel isterseniz üç çiftiniz olur. Zor kısımlar API çağrıları değildir; pencere yeniden boyutlandığındaki yerleşim aritmetiği ve hangi görünümün hangisini izleyeceğine karar verdiğinizdeki sayfa eşitleme mantığıdır
Form Yerleşimi
VCL formu yan yana üç TScrollBox kapsayıcı barındırır; her birinin içinde bir TPdfView vardır ve kutuyu doldurması için alClient ile hizalanmıştır. Kullanıcının sütun genişliklerini çalışma zamanında ayarlayabilmesi için kutuların arasında iki TSplitter bileşeni durur. Panellerin üstündeki bir araç çubuğu açma düğmelerini, yakınlaştırma denetimlerini ve iki görünüm / üç görünüm anahtarını taşır
Üç görünüm kipi, formun içeride izlediği bir mantıksal değerdir. Değiştiğinde genişlikleri yeniden hesaplar ve üçüncü sütunu gösterir ya da gizlersiniz. En basit yaklaşım, tüm Align özelliklerini temizlemek, ayırıcıları gizlemek ve sonra mutlak konumları ayarlamaktır:
procedure TFormMain.UpdateLayout;
var
TotalWidth: Integer;
begin
TotalWidth := ClientWidth;
if ThreeViewMode then
begin
ScrollBox3.Visible := True;
ScrollBox1.Left := 0;
ScrollBox1.Width := TotalWidth div 3;
ScrollBox2.Left := ScrollBox1.Width;
ScrollBox2.Width := TotalWidth div 3;
ScrollBox3.Left := ScrollBox2.Left + ScrollBox2.Width;
ScrollBox3.Width := TotalWidth - ScrollBox3.Left;
// Aynı (ClientHeight - araç çubuğu yüksekliği) değerini üç Height alanına da uygula
end
else
begin
ScrollBox3.Visible := False;
ScrollBox1.Left := 0;
ScrollBox1.Width := TotalWidth div 2;
ScrollBox2.Left := ScrollBox1.Width;
ScrollBox2.Width := TotalWidth - ScrollBox2.Left;
end;
end;
Tamsayı aritmetiğinden önce üç kutuda da Align := alNone ayarlamak, VCL kısıt motorunun atamalarınızla boğuşmasını önler. İki görünüm kipinde sürükleyerek boyutlandırma istiyorsanız konumlandırmadan sonra ayırıcı görünürlüğünü geri verin
Her kaydırma kutusunun yüksekliği, istemci alanından araç çubuğu paneli yüksekliği çıkarılmış değerdir. Araç çubuğu alTop ile üste yerleştiği için ClientHeight - PanelButtons.Height size kullanılabilir dikey alanı verir. Bunu üç kutuya da aynı UpdateLayout çağrısı içinde atayın ki bir kutunun diğerlerinden uzun olduğu ve yerleşim titremesine yol açtığı bir kare hiç oluşmasın
Belge Açma
Her panel çiftinin kendi açma yordamına ihtiyacı vardır. Desen kısadır: bileşeni devre dışı bırakın, dosya adını ayarlayın, etkinleştirin, sonra Active değerini denetleyin; False kaldıysa parola isteyip yeniden deneyin. Şunu unutmayın: işlemeyi denetleyen TPdfView.Active değeridir ama dosyayı gerçekten açan TPdf.Active değeridir; ikisi bağımsızdır. Bağlı TPdf bileşeni henüz etkin değilken PdfView.Active := True ayarlamak zararsızdır ama hiçbir şey göstermez
procedure TFormMain.OpenPdfFile(PdfComponent: TPdf;
PdfViewComponent: TPdfView);
var
Password: string;
begin
if not OpenDialog.Execute then
Exit;
PdfComponent.Active := False;
PdfComponent.FileName := OpenDialog.FileName;
PdfComponent.Password := '';
PdfComponent.Active := True;
// Yükleme hataları sessizdir: istisna yerine Active False kalır.
if not PdfComponent.Active then
begin
// Büyük olasılıkla parola korumalı bir dosya; kullanıcıya bir hak ver.
if InputQuery('Password', 'Enter document password:', Password) then
begin
PdfComponent.Password := Password;
PdfComponent.Active := True;
end;
end;
if not PdfComponent.Active then
begin
ShowMessage('Could not open ' + OpenDialog.FileName +
' (damaged file or wrong password)');
Exit;
end;
PdfViewComponent.PageNumber := 1;
SetActivePdfView(PdfViewComponent);
end;
Atamadan sonra PdfComponent.Active değerini her zaman denetleyin; hasarlı bir dosya ya da yanlış bir parola, varsayılan yolda istisna fırlatmadan yüklemenin sessizce başarısız olmasına yol açar. Başarılı bir açmanın ardından PdfViewComponent.PageNumber := 1 ayarını açıkça yapmak, önceki belgeden kalan bayat bir sayfa numarasını önler
Sondaki mesaj iletişim kutusu bilinçlidir: bozuk ya da desteklenmeyen dosyaların sessiz bir boş panel olarak yutulması yerine hemen yüzeye çıkmasını istersiniz. Hiçbir şey görmeyen bir kullanıcı, dosyanın yüklenip gerçekten boş mu olduğunu yoksa bileşenin onu reddedip reddetmediğini bilemez. Hatayı bildirmek sorunu görünür tutar
Etkin Panel Takibi
Kullanıcı bir panelin içine tıkladığında o panel etkin olur. Form, özel bir FActivePdfView: TPdfView alanını izler. Görsel geri bildirim, kapsayan TScrollBox üzerindeki bir kenarlık rengi değişimidir: etkin olan için clHighlight, diğerleri için clWindow ayarlayın. Bunu her TPdfView.OnClick olayına ve açma yordamına bağlayın ki odak, az önce açtığınız belgeyi izlesin
Bazı işlemler yalnızca etkin panele değil görünür panellerin hepsine uygulanır. Formdaki mantıksal bir FAllViewsMode alanı bu dalı sürer. Değeri true olduğunda yakınlaştırma değişiklikleri ve sayfa gezinmesi, etkin belgesi olan her panele dağılır:
procedure TFormMain.ApplyZoomToAll(NewZoom: Double);
begin
if PdfView1.Active then PdfView1.Zoom := NewZoom;
if PdfView2.Active then PdfView2.Zoom := NewZoom;
if ThreeViewMode and PdfView3.Active then PdfView3.Zoom := NewZoom;
end;
Eşzamanlı Sayfa Gezinmesi
Eşzamanlı gezinme isteğe bağlıdır ama her iki dosyanın aynı sayfa aralığını kapsadığı belge revizyon akışlarında yararlıdır. Mantık, kullanıcı bir görünümde gezindikten sonra tetiklenen bir olay işleyicisine aittir. Bir kaynak görünüm PageNumber değerini değiştirdiğinde işleyici bu numarayı diğer görünümlere yayar; tek bir koruma vardır: hedef görünümün en az o kadar sayfası olmalıdır, yoksa atlanır
TPdfView üzerindeki PageNumber ile TPdf üzerindeki bağımsızdır. TPdf.PageNumber, belge bileşeninin geçerli saydığı sayfayı izler; TPdfView.PageNumber ise ekranda görüntülenen sayfayı izler. Gezinme amacıyla belge özelliğini değil görünüm özelliğini istersiniz
"Sayfaları eşitle" gibi bir etiket taşıyan bir onay kutusu denetimi kullanıcıya verir. İşaretli değilken her panel bağımsız gezinir ve işleyici hemen çıkar. Bu bağımsızlık, iki belgenin sayfa sayılarının farklı olduğu ya da kullanıcının farklı bir sayfada başlayan bir çeviride eşdeğer bölümü bulmak istediği kullanım durumları için önemlidir. Eşitlemeyi her zaman zorlamak, aracı iki pencereli basit bir masaüstü düzeninden daha kullanışsız kılar
Dikkat edilecek bir nokta: eşitleme işleyicisi içinde PdfView.PageNumber değerini programla ayarlamak, o görünümde değişim olayını da tetikler. Atamadan önce ayarlayıp hemen sonra temizlediğiniz bir mantıksal bayrakla sonsuz özyinelemeye karşı korunun. Bayrak görünüm başına değil form başınadır; çünkü üç görünüm de aynı işleyiciyi paylaşır
Panel Başına Yakınlaştırma
Her TPdfView kendi Zoom özelliğini taşır; bu, yüzde cinsinden bir Double değerdir ve Zoom := 100 gerçek boyut (%100) demektir. Onu ayarlamak etkin herhangi bir FitMode ayarını geçersiz kılar. Etkin panelde genişliğe sığdır düğmesi için sığdırma yakınlaştırmasını PdfView.PageWidthZoom[PdfView.PageNumber] değerinden okuyup atayın. Sayfaya sığdır için PageZoom[PageNumber] kullanın. İkisi de 1 tabanlı sayfa numarasıyla dizinlenen dizi özellikleridir; bu yüzden onlara erişmeden önce sıfır sayfa numarasına karşı koruma koyun
Geçerli sayfayı bir görüntüye aktardığınızda döndürmeyi görünümden okuyun ama RenderPage çağrısını görünümde değil TPdf bileşeninde yapın. TPdf.RenderPage çağrısının bit eşlem biçimi açık piksel boyutlarının yanı sıra bir TRotation değeri ve bir TRenderOptions kümesi alır. İşlev biçimi, kaydettikten sonra kendiniz serbest bırakacağınız, çağırana ait bir TBitmap döndürür:
procedure TFormMain.SaveActiveViewAsImage;
var
Pdf: TPdf;
Bmp: TBitmap;
Jpeg: TJpegImage;
begin
if not Assigned(FActivePdfView) or not FActivePdfView.Active then
Exit;
Pdf := FActivePdfView.Pdf;
Pdf.PageNumber := FActivePdfView.PageNumber;
Bmp := Pdf.RenderPage(
0, 0,
Round(Pdf.PageWidth * 2),
Round(Pdf.PageHeight * 2),
FActivePdfView.Rotation, [], clWhite);
try
if SavePictureDialog.Execute then
begin
Jpeg := TJpegImage.Create;
try
Jpeg.Assign(Bmp);
Jpeg.CompressionQuality := 90;
Jpeg.SaveToFile(SavePictureDialog.FileName);
finally
Jpeg.Free;
end;
end;
finally
Bmp.Free;
end;
end;
Genişlik ve yükseklikteki 2 kat çarpan, ince metinli belgeler için daha keskin çıktı verir. Bit eşlem serbest bırakmasının çevresindeki try/finally isteğe bağlı değildir; bir TSaveDialog iptali de finally bloğuna girer ve kullanıcı ne yapmış olursa olsun bit eşlemin bırakılmasını istersiniz
DLL Gereksinimleri
PDFium Component yerel pdfium kütüphanesini sarmalar. 32 bitlik bir barındırıcı süreç pdfium32.dll ister; 64 bitlik bir barındırıcı pdfium64.dll ister. V8 JavaScript motorunu içeren çeşitler v8 sonekini alır ve 5-6 MB boyutundaki standart yapılara karşılık kabaca 23-27 MB ağırlığındadır. Form doldurmayı devre dışı bırakan (Pdf.FormFill := False) bir karşılaştırma görüntüleyicisi için standart, V8 içermeyen yapı yeterlidir ve dağıtımı daha küçük tutar
DLL dosyasını yürütülebilir dosyayla aynı dizine ya da sistem PATH değerindeki herhangi bir dizine koyun. Bileşen onu ilk TPdf etkinleştirildiğinde istek üzerine yükler; dolayısıyla eksik bir DLL uygulama başlangıcında değil o noktada ortaya çıkar. Bir kurulum paketi gönderiyorsanız en güvenilir yaklaşım, bir yöneticinin sonradan temizleyebileceği bir sistem dizinine güvenmek yerine DLL dosyasını kurulum sırasında uygulama klasörüne kopyalamaktır
V8 yapıları esas olarak PDF JavaScript eylemleriyle etkileşmeniz gerektiğinde, örneğin hesaplama alanlarını ya da gönderme işleyicilerini tetiklemek için yararlıdır. Edilgen bir karşılaştırma görüntüleyicisinin JavaScript çalıştırmak için hiçbir nedeni yoktur; Active := True öncesinde Pdf.FormFill := False ayarlamak form doldurma ortamını tümüyle atlar ve bu, standart yapı kullanılsa bile hiçbir JS motorunun başlatılmaması demektir. Hangi DLL çeşidini gönderirseniz gönderin, salt okunur bir görüntüleyici için doğru varsayılan budur
PDFium Component ve tam API arayüzü hakkında ayrıntılar için Delphi PDFium Component ürün sayfasını ziyaret edin