AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

2 PDFium-Frames synchronisieren

Ein Thema von Delbor · begonnen am 14. Nov 2017 · letzter Beitrag vom 15. Nov 2017
Antwort Antwort
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#1

2 PDFium-Frames synchronisieren

  Alt 14. Nov 2017, 14:38
Delphi-Version: XE8
Hi zusammen
Von hier hab ich mir die synpdf.zip heruntergeladen. Sie enthält ein Beispielprogramm, das die PDFium.dll nutzt und das schon eigentlich alles macht, was ich realisieren will, nämlich PDFs anzeigen, auch mehrseitige.
Trotzdem sticht mich der Hafer, und so will ich das um eine Sidebar erweitern, die eine Übersicht über die in der PDF-Darei vorhandenen Seiten bietet. Halt etwa so, wie es in den gängigen PDF-Programmen der Fall ist.

Das klappt soweit - nur sollte ein Klick auf eine der Seiten in der Sidebar nun auch die entsprechende Seite im Hauptfenster anzeigen. Das klappt schon fast. Bis halt auf die Tatsache, dass dabei die Originalgrössen des PDFs berücksichtigt werden. Das führt dazu, das ein Klich auf Seite1 zwar auch diese zurückgibt, aber erst ein Klick auf Seite 4 in der Sidebar meldet eine andere Seite.

Ein klassisches ScreenToClient/ClientToScreen-Problem halt. Nur - um diese Methoden einsetzen zu können, bräuchte ich die Originalabmessungen der PDF-Seiten. Und wie ich die kriege, hab ich bislang nicht herausgefunden. Meine bisherigen Versuche:

Delphi-Quellcode:
procedure TSynpdfMain.BtnFileOpenClick(Sender: TObject);
  var PIndex : integer; PageHandle : THandle; PDFPage : TPDFPage;
begin
  if Opendialog1.Execute then
  begin
    Self.PDFiumFrame1.LoadFromFile(Opendialog1.FileName);
    Self.PDFiumFrame1.ZoomMode := zmPageWidth; //zmCustom; HPDFPage;
    Self.PDFiumFrame2.LoadFromFile(Opendialog1.FileName);
    Self.PDFiumFrame2.ZoomMode := zmPageWidth; // <--
    for PIndex := 0 to PDFiumFrame2.PageCount -1 do
    begin
      PDFPage := PDFiumFrame2.PageCount[PDFiumFrame2.PageIndex];
      PageHandle := PDFiumFrame2.PageCount[PIndex];
// Memo1.Lines.Add('PDFiumFrame2.Pages[PageIndex]).PageWidth))' +IntToStr(PDFiumFrame2.PageCount[PIndex]).h));
      Memo1.Lines.Add('PDFiumFrame2.Pages[PageIndex]).PageWidth))' +IntToStr(PDFPage.PageWidth));
      Memo1.Lines.Add('PDFiumFrame2.Pages[PageIndex]).PageHeight))' +IntToStr(PDFPage.PageHeight));
    end;

// Self.PDFiumFrame2
  end;
  Button3Click(Sender); //mnFitWidthClick(Sender); := Self.PDFiumFrame1.
end;
Die ersten 4 Zeilen laden das PDF in je einen Frame. Allerdings - in beiden Frames werden die PDFs übergross dargestellt, also nicht an die verfügbare Seitenbreite(Clientbereich) angepasst. Erst über den Button in der Werkzeugleiste kriege ich es hin, dass beide PDFs sich an den jeweiligen Clientbereich anpassen (siehe Anhang).

Innerhalb der Schleife wird ein Kompilierungsversuch schon bei der ersten Zeile abgebrochen. Die Fehlermeldung: Arraytyp erfforderlich. Die selbe Fehlermeldung steht gleich darunter für Zeile 2. Die Deklarationen im Publicteil des PDFiumFrames:
Delphi-Quellcode:
    property PageIndex: Integer read FPageIndex;
    property PageCount: Integer read FPageCount;
Die Funktion GetPage des Frames (Opensource):
Delphi-Quellcode:
function TPDFiumFrame.GetPage(PageIndex: Integer): TPDFPage;
var
  Index :Integer;
begin
  for Index := 0 to FPages.Count - 1 do
  begin
    Result := FPages[Index];
    if Result.Index = PageIndex then
      Exit;
  end;
  Result := TPDFPage.Create;
  FPages.Add(Result);
  Result.Index := PageIndex;
  Result.Handle := FPDF_LoadPage(FDocument, PageIndex);
end;
Die Funktion ist übrigens kein Getter eines Page-Propertys. Ich wollte dem Frame ein solches verpassen, aber da wird ein Kompilerungsversuch abgebrochen mit der etwas lapidaren Fehlermeldung: "Inkompatible Typen", ohne dass dabei die beiden Datentypen aufgeführt werden.

Was mache ich falsch?

Gruss
Delbor
Miniaturansicht angehängter Grafiken
synpdftestprojct.jpg  
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
bra

Registriert seit: 20. Jan 2015
711 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#2

AW: 2 PDFium-Frames synchronisieren

  Alt 14. Nov 2017, 14:47
PDFiumFrame2.PageCount[PDFiumFrame2.PageIndex];
Das kann doch nicht funktionieren, wenn PageCount nur ein Integer-Wert ist. Müsste hier nicht PDFiumFrame2.GetPage(xxx), PDFiumFrame2.Pages[xxx] o.ä. aufgerufen werden?
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: 2 PDFium-Frames synchronisieren

  Alt 14. Nov 2017, 15:23
Hi bra

Zitat:
Müsste hier nicht PDFiumFrame2.GetPage(xxx), PDFiumFrame2.Pages[xxx] o.ä. aufgerufen werden?
Ersteres geht nicht, da GetPage privat deklariret ist.
Und letzteres geht auch nicht, da mit 'PDFiumFrame2.Pages' ein Property angesprochen würde
  • das es nicht gibt
  • das ich einführen wollte, das aber wegen angeblich inkompatiblen Typen nicht akzeptiert wird.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
bra

Registriert seit: 20. Jan 2015
711 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#4

AW: 2 PDFium-Frames synchronisieren

  Alt 14. Nov 2017, 16:30
Kann man da nicht über PDFiumFrame2.Page zugreifen? Und mit PDFiumFrame2.First/PDFiumFrame2.Next wechselt man die Seiten?
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: 2 PDFium-Frames synchronisieren

  Alt 14. Nov 2017, 17:15
Hi bra

Nein, leider ist das nicht so einfach - sowas wäre im Rahmen der Delphi-OOP ja auch schon logisch. Aber dem Programmm liegt die pdfium.dll zugrunde. Und die ist meines Wissens in C oder C++ programmiert.

Aber ich habe hier noch was interessantes gefunden. Leider ist diese Dokumentation englisch, aber sie hat mir schonmal geholfen.
Laut dieser Doku muss erst das Dokument geladen werden und anschliessend die darin enthaltenen Seiten.
Wobei dies eigentlich genau das ist, was ich nicht tun wollte.

Eine meiner ersten Regungen war, in der Sidebar eine Scrollbox zu platzieren, darauf verschiedene Panels mit je einem PDFium-Frame anzuordnen und in jeden dieser Frames eine Seite des PDF-Dokumentes zu laden. Das habe ich wieder verworfen, da die Panels vollkommen überflüssig wären, wenn mir die Kooordinaten der Seiten bekannt wären.

Andrerseits wiederstrebte es mir, das PDF-Dokument und die einzelnen Seiten separat zu laden - das Beispielprogramm lädt von Haus auf auch nur gerade das Dokument, nicht aber die zugehörigen Seiten. Trotzdem kann man beliebig zwischen diesen Seiten hin- und herscrollen, auch per Mausrad. Und da war natürlich mein Gedanke: wozu etwas laden, das ohnehin schon da ist...

Ach ja - gerade habe ich dies in meinem ersten Beitrag gesehen:
Zitat:
Memo1.Lines.Add('PDFiumFrame2.Pages[PageIndex]).PageWidth))' +IntToStr(PDFPage.PageWidth));
Memo1.Lines.Add('PDFiumFrame2.Pages[PageIndex]).PageHeight))' +IntToStr(PDFPage.PageHeight));
Das stammt noch von meinen Versuchen, dem PDFium-Frame ein Pages-Property zu verpassen. Da es dieses aktuell nicht mehr gibt, sind diese Zeilen eigenlich überflüssig.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: 2 PDFium-Frames synchronisieren

  Alt 15. Nov 2017, 11:01
Hi zusammen

Um mir die Abläufe während des Kompilierens im Nachhinein anzeigen zu können, hab ich mir mal was mit einer Stringliste gebastelt, deren Einträge der Destruktor vor dem Beendem in eine Datei speichert. Das Resultat:

Zitat:
15.11.2017 10:47:58
----------------
----------------------------------
procedure TPDFiumFrame.SetDocument
----------------------------------
Aufrufe:
- FPDF_CloseDocument:
- FPDF_GetLastError:
- SetPageCount(FPDF_GetPageCount(FDocument)):
----------------------------------
procedure TPDFiumFrame.LoadFromFile
----------------------------------
Aufrufe:
- _Document := FPDF_LoadDocument
----------------------------------
function TPDFiumFrame.GetPage
----------------------------------
Aufrufe:
- Result := TPDFPage.Create;
- FPages.Add(Result);
- Result.Handle := FPDF_LoadPage(FDocument, PageIndex);
Wobei ich es gerade darauf abgesehen hatte, die Aufrufe der Funktion GetPage zu dokumentieren. Wieso diese Funktion oben nur einmal aufgeführt ist, weiss ich im Moment nicht. Das Testdokument enthält 13 Seiten, also solllte die Funktion 13 Mal aufgeführt sein.
Die Funktion gibt folgendes zurück:
Delphi-Quellcode:
  Result.Index := PageIndex;
  Result.Handle := FPDF_LoadPage(FDocument, PageIndex);
Dass diese Funktion aufgerufen wird, beweist: Die Seiten sind innerhalb des Frames vorhanden - sie also nochmal zu laden, wäre völliger Quatsch. Dem Frame ein Property Page zu verpassen, war also eben doch der richtige Weg. Nur, um mich mal selbst zu zitieren:
Zitat:
Und letzteres geht auch nicht, da mit 'PDFiumFrame2.Pages' ein Property angesprochen würde

-das es nicht gibt
-das ich einführen wollte, das aber wegen angeblich inkompatiblen Typen nicht akzeptiert wird.
Hier wird ein Kompilierungsversuch wegen inkompatibler Typen abgebrochen:

Property PDFPage : TPDFPage read GetPage;

Das Result der Funktion GetPage allerdings:
Delphi-Quellcode:
  Result := TPDFPage.Create;
  FPages.Add(Result);
  Result.Index := PageIndex;
  Result.Handle := FPDF_LoadPage(FDocument, PageIndex);
Das heisst, der Frame erzeugt ein TPDFPage-Object und gibt diese in Result zurück, nachdem er dem Objekt den Index und das Handle zugewiesen hat.

Ist meine Property-Deklaration falsch?

Gruss
Delbor

PS: Ja, sie war falsch. So ist es besser, bzw. wird akzeptiert:
Property PDFPages : TList read FPages;
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor (15. Nov 2017 um 14:34 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz