Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Adobe Reader einbinden (https://www.delphipraxis.net/185015-adobe-reader-einbinden.html)

idefix2 7. Mai 2015 16:18

Adobe Reader einbinden
 
Hallo,

weiss jemand ein Tutorial oder eine Beschreibung, wie man in Delphi Adobe Reader Funktionalität ansprechen kann?
Alles was ich brauche, ist: Ein Adobe PDf File öffnen, dort an bestimmten Orten Textfelder erstellen, in die Textfelder Daten (aus einer Datenbank) schreiben und das so geänderte Dokument unter neuem Namen abspeichern.
Ich denke, das sollte über die die Adobe ActiveX Schnittstelle leicht möglich sein, ich habe die Type Library importiert und jetzt eine ganze Reihe von TAcroxxx Komponenten (von TAcroApp bis TAcroAXDoc, insgesamt 13 Komponenten) in der Tool Palette verfügbar, aber ich habe keine Ahnung, wie ich diese Komponenten sinnvoll einsetzen kann. Habe schon eine ganze Weile im Internet gesucht, vieles gefunden, aber nichts, was mir weiterhelfen würde.

mkinzler 7. Mai 2015 16:22

AW: Adobe Reader einbinden
 
Änderungen an einer Pdf-Datei wirst Du nicht mit dem Reader durchführen können. Man kann zwar etwas , dafür vorgesehene Formularfelder eingeben, gespeichert werden diese Änderungen aber nicht. Für Deienn Zweck wirst Du nicht um eine PDF-Bibliothek herumkommen.

idefix2 7. Mai 2015 16:49

AW: Adobe Reader einbinden
 
Mit dem aktuellen Adobe Reader XI kann ich (manuell) Text an beliebiger Stelle in einem PDF Formular einsetzen und das auch wieder abspeichern. Der stellt zu dem Zweck jetzt die "Werkzeuge zum Ausfüllen und unterschreiben" an der Oberfläche zur Verfügung.
Das genügt mir, aber ich würde das eben gerne automatisiert aus Delphi heraus machen.

idefix2 7. Mai 2015 18:02

AW: Adobe Reader einbinden
 
Bis jetzt ist es mir noch nicht einmal gelungen, eine PDF Datei mit so einer Komponente zu öffnen. Ich geghe davon aus, dass ich erst einmal irgend etwas mit AcroApp machen muss, um eine Verbindung zum Adobe Reader herzustellen. Aber egal, was ich mache, bekomme ich die Fehlermeldung:

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt PdfTest.exe ist eine Exception der Klasse EOleSysError mit der Meldung 'Klasse nicht registriert' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------

Irgendwie scheint er den Adobe Reader nicht zu kennen, obwohl der natürlich in meinem System registriet ist und ich die Typbibliothek ganz normal generieren konnte (da müsste Windows doch die Klassen kennen, um die es geht?).

himitsu 7. Mai 2015 18:35

AW: Adobe Reader einbinden
 
Wo knallt es? (Befehl)

Adobe Acrobat muß sein ActiveX-Komponenten auch erstmal bei Windows registriert haben. (ordentlich installiert)
Und dann muß die installierte Acrobat-Version auch noch das Interface unterstützen, welches du da erstellen willst.

https://www.adobe.com/support/author...nstall_04.html
https://www.adobe.com/support/authorware/activex.html
usw.

Bernhard Geyer 7. Mai 2015 19:28

AW: Adobe Reader einbinden
 
Zitat:

Zitat von idefix2 (Beitrag 1300665)
Hallo,

weiss jemand ein Tutorial oder eine Beschreibung, wie man in Delphi Adobe Reader Funktionalität ansprechen kann?
...
Ich denke, das sollte über die die Adobe ActiveX Schnittstelle leicht möglich sein, ich habe die Type Library importiert und jetzt eine ganze Reihe von TAcroxxx Komponenten (von TAcroApp bis TAcroAXDoc, insgesamt 13 Komponenten) in der Tool Palette verfügbar,

n
Was nun? Willst du den kostenlosen Adobe Reader oder den kostenpflichtige Adobe Acrobat verwenden? Das sind zwei paar Stiefel.

idefix2 7. Mai 2015 21:36

AW: Adobe Reader einbinden
 
Den Acrobat Reader. Etwas anderes habe ich bis jetzt nie verwendet.

Es ist äusserst eigenartig. Auf den Hinweis von Himitsu hin habe ich den Acrobat Reader komplett deinstalliert und noch einmal neu installiert, und in Delphi die Komponenten ebenfalls deinstalliert und wollte sie neu importieren. Jetzt gibt es diese Typbibliothek für den Adobe Acrobat Reader 11, die ich eben vorher klaglos importiert hatte, plötzlich gar nicht mehr, sondern auf den Acrobat bezogen schlägt mir Delphi zum Importieren nur mehr vor:

Acrobat Access 3.0 Type Library
AcroBrokerLib
Adobe Acrobat 7.0 Browser Control Type Library
Adobe Reader File Preview Type Library

(wobei ich den Verdacht habe, dass die "Adobe Acrobat 7.0 Browser Control Type Library" irgend ein übriggebliebenes Relikt einer uralten Reader Installation sein dürfte, das wahrscheinlich nicht mehr funktioniert).

Die Typbibliothek, die ich wahrscheinlich brauchen würde, ist durch das Deinstallieren und Neuinstallieren des Readers verschwunden, sie war aber vorher da.

Hat jemand eine Idee, wie ich die Aufgabe (gegebenenfalls auch mit anderen Tools) lösen könnte? Wenn gar nichts anderes geht, werde ich autohotkey nehmen, um direkt auf der Oberfläche des Adobe Readers mit Tastatur und Maus zu fuhrwerken, aber über jeden anderen zielführenden Vorschlag wäre ich froh, denn die Lösung wäre alles andere als stabil.

Bernhard Geyer 7. Mai 2015 22:14

AW: Adobe Reader einbinden
 
Also es gibt eine sehr minimale (COM)API des Readers die man ohne jegliche Kosten verwenden kann aber nicht mehr kann als PDf öffnen, PDF drucken und auf Seite positionieren.

Es gibt ein Plug-in-API die man im Adobe Reader und Adobe Acrobat verwenden kann. Für den Adobe Acrobat ist sie kostenlos, für den Reader relativ teuer. Vor Jahren hatten wir ein Plugin das aber mit der damaligen neuen Reader-Version 6/7 neu zertifiziert werden sollte und 1000 €/$ gekostet hätte (von ehemals 100 €/$). Und es gibt die realtiv umfangreiche (COM)API des Adobe Acrobat die auch wieder kostenlos verwendet werden kann.

Meine Empfehlung ist aber Adobe zu meiden und *irgendeine* (Ausnahme: Gnostice-) 3th-Party-Bibliotheken zu verwenden welche genau dieses Feature bietet.

idefix2 7. Mai 2015 23:15

AW: Adobe Reader einbinden
 
Kannst du *irgendeine* kostengünstige Bibliothek empfehlen, mit das zu bewerkstelligen ist?

Das Ergebnis muss übrigens kein PDF sein. Eben ist mir die Idee gekommen, wenn es möglich wäre, das PDF in ein JPG zu verwandeln, dann könnte ich die einzutragenden Texte direkt in den Canvas eines TImage dazuzeichnen und das Ganze als JPG speichern.

edit
Und nachdem mir diese Idee gekommen ist, ist die Lösung einfach. Ich habe ja immer die gleichen PDFs als Vorlage, da brauche ich ja gar nichts, um die jedesmal von Neuem zur Laufzeit in JPGs umzuwandeln, das mache ich ein mal, und dann arbeite ich im Programm einfach mit den JPG-Vorlagen statt mit den PDF Vorlagen.
Zur Hölle mit dem Acrobat Format :)

Dalai 8. Mai 2015 00:05

AW: Adobe Reader einbinden
 
JPG ist für sowas ungeeignet. Also jetzt nicht unbedingt weil es ein Bilddateiformat ist, sondern weil JPG für Fotos gedacht sind, nicht für Screenshots oder allgemein Bilder mit wenigen Farben und ohne (große) Farbverläufe. Oder kurz gesagt: Nimm lieber PNG, sofern deine Dokumente nur Text und große gleichfarbige Flächen beinhalten. Das gibt keine Artefakte wie bei JPG (aufgrund der Qualitätseinstellungen) und die Dateien werden auch noch kleiner.

MfG Dalai

idefix2 8. Mai 2015 10:06

AW: Adobe Reader einbinden
 
Ok, danke für den Hinweis. Für Delphi ist ja von der Programmierung her kein Unterschied, oder?

jaevencooler 8. Mai 2015 10:08

AW: Adobe Reader einbinden
 
Moin, Moin,

schon mal hier nach geschaut ?

http://www.wpcubed.com/pdf/

Ich nutze die Tools und bin recht zufrieden......


Cu Michael

idefix2 8. Mai 2015 10:51

AW: Adobe Reader einbinden
 
Ja, danke, das hab ich bei meiner Suche auch schon gefunden und angeschaut.

Wenn ich damit rechnen würde, so etwas öfters zu brauchen, dann würde ich so ein Tool in Betracht ziehen. Aber voraussichtlich brauche ich das genau EIN mal, um in EINER Anwendung insgesamt 5 Formulare zu befüllen. Dafür will ich nicht etliche hundert Euro ausgeben.
Wenn man wirklich öfters PDF bearbeiten muss, dann ist das sicher eine gute Sache, aber mit dem Ansatz, den ich jetzt gefunden habe, komme ich bestens zurecht, ohne in Komponenten zu investieren, die ich nur einmal brauche und die mir in der Folge noch meine IDE zumüllen.

Was ich nicht verstehe, ist, dass es offenbar in einer älteren Reader Version eine DLL Funktionalität gegeben hat, die es in der aktuellen Version nicht mehr gibt. Das bestärkt mich darin, um Adobe einen Bogen zu machen. Wenn ich auf Basis der Version 9 oder 10 des Readers eine Lösung prtogrammiert hätte, die mit Version 11 plötzlich überhaupt nicht mehr geht, weil die neue DLL die Funktionen nicht mehr zu verfügung stellt, dann würde ich mich wirklich ärgern.

Bjoerk 8. Mai 2015 11:36

AW: Adobe Reader einbinden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Auf der Emba Homepage gibt es eine pdf.dll und dazu einen Wrapper für Delphi. Da wären wir aber wieder bei TextOut und StretchDraw und die GUI müßte gesondert programmiert werden. Ich hab das in einem Fall mal so gemacht (Edits und CheckBoxes drübergelegt). Sieht ganz nett aus soweit, ist aber ne blöde Pixel Fummelei.

mkinzler 8. Mai 2015 11:39

AW: Adobe Reader einbinden
 
Oder man verwendet eine Reporttool mit PDF-Export ( z.B. das gebündelte Fastreport)

oder

http://www.debenu.com/products/devel...-library-lite/

idefix2 8. Mai 2015 14:41

AW: Adobe Reader einbinden
 
Hallo Bjoerk,

danke für den Link. Das Tool ist für meine Zwecke perfekt und wirklich denkbar einfach zu verwenden. Innerhalb von weniger als 10 Minuten hatte ich schon eine erste Testausgabe fertig, bei der ich über das Formular einen Raster mit den Koordinaten (alle 50 Pixel) gelegt habe. Einfacher geht es wirklich nicht.

Eine Anzeige des formulars am Bildschirm brauche ich gar nicht, die ausgefüllten Formulare werden abgelegt und per Mail verschickt.

Zum richtigen Positionieren der Textausgaben muss ich mich jetzt noch etwas spielen, aber das müsste ich bei jeder gewählten Variante, und mit Hilfe des Formulars mit Raster sollte das recht schnell gehen.

:thumb:

Bjoerk 8. Mai 2015 15:17

AW: Adobe Reader einbinden
 
Fein. :)

Wenn du magst, hier hab den Wrapper von 72 auf 96 Pixel erweitert.

http://www.delphipraxis.net/1276386-post6.html

LG
Thomas

idefix2 8. Mai 2015 19:08

AW: Adobe Reader einbinden
 
Danke, ich glaube, das werde ich auch noch brauchen können.

Einen Fehler solltest du ausbessern, das
Delphi-Quellcode:
Exchange(FPageWidth, FPageWidth);
in SetOrientation wird nicht ganz das bringen, was man sich erwartet :wink:
Und es geht etwas kompakter:

Delphi-Quellcode:
  if (FOrientation = poPortrait) <> (FPageWidth < FPageHeight) then
      Exchange(FPageWidth, FPageHeight);

idefix2 8. Mai 2015 20:47

AW: Adobe Reader einbinden
 
@Mkinzler
Danke übrigens dir auch für den Link - habe es mir auch angeschaut, aber die Variante, die Björk vorgeschlagen hat, ist konkurrenzlos simpel und für meine Zwecke 100% ausreichend. Die Bibliothek von Debenu.com scheint einiges mehr zu können, aber dafür wäre es damit vermutlich etwas komplizierter, die triviale Aufgabe zu lösen, die ich habe.

Bjoerk 8. Mai 2015 21:09

AW: Adobe Reader einbinden
 
Zitat:

Zitat von idefix2 (Beitrag 1300770)
Danke, ich glaube, das werde ich auch noch brauchen können.
Einen Fehler solltest du ausbessern [..]

Kann sein. Hatte das damals so auf die Schnelle gemacht. Bevor ich aber was in meine Software einbaue schau ich für gewöhnlich nochmal drüber. Hier, wie ich es schließlich implementiert hab.

Delphi-Quellcode:
unit uPdf;

interface

uses
  Windows, SysUtils, Dialogs, Graphics, Math, ShellAPI;

type
  TDinAFormat = (DinAPortrait0, DinALandscape0,
    DinAPortrait1, DinALandscape1,
    DinAPortrait2, DinALandscape2,
    DinAPortrait3, DinALandscape3,
    DinAPortrait4, DinALandscape4);

  TDinAPage = record
  private
    FMMHeight: integer;
    FMMWidth: integer;
    FDinAFormat: TDinAFormat;
    function GetLandscape: boolean;
    procedure SetDinAFormat(const Value: TDinAFormat);
  public
    property Landscape: boolean read GetLandscape;
    property MMHeight: integer read FMMHeight;
    property MMWidth: integer read FMMWidth;
    property DinAFormat: TDinAFormat read FDinAFormat write SetDinAFormat;
  end;

  TPdf = class
  private
    FFileName: string;
    FAuthor: string;
    FTitle: string;
    FSubject: string;
    FKeywords: string;
    FCreator: string;
    FPixelsPerInch: integer;
    FAutoLaunch: boolean;
    FCanvas: TCanvas;
    FDinAPage: TDinAPage;
    function GetCanvas: TCanvas;
    function GetPageCount: integer;
    function GetPageWidth: integer;
    function GetPageHeight: integer;
    function GetPdfPageWidth: integer;
    function GetPdfPageHeight: integer;
    function GetMMWidth: double;
    function GetMMHeight: double;
    function GetDinAFormat: TDinAFormat;
    function DeviceCaps: integer;
  public
    procedure BeginDoc;
    procedure NewPage;
    procedure EndDoc;
    function MMToPixel(const MMX, MMY: double): TPoint;
    property Canvas: TCanvas read GetCanvas;
    property FileName: string read FFileName write FFileName;
    property Author: string read FAuthor write FAuthor;
    property Title: string read FTitle write FTitle;
    property Subject: string read FSubject write FSubject;
    property Keywords: string read FKeywords write FKeywords;
    property Creator: string read FCreator write FCreator;
    property PageCount: integer read GetPageCount;
    property PageWidth: integer read GetPageWidth;
    property PageHeight: integer read GetPageHeight;
    property PdfPageWidth: integer read GetPdfPageWidth;
    property PdfPageHeight: integer read GetPdfPageHeight;
    property MMWidth: double read GetMMWidth;
    property MMHeight: double read GetMMHeight;
    property AutoLaunch: boolean read FAutoLaunch write FAutoLaunch;
    property DinAFormat: TDinAFormat read GetDinAFormat;
    property PixelsPerInch: integer read FPixelsPerInch;
    constructor Create(const DinAFormat: TDinAFormat);
    destructor Destroy; override;
  end;

implementation
                         
const
  cPdfDllPixelsPerInch = 72;
  cPdfDll = 'pdf.dll';

procedure RolePDFBeginDoc(License, FileName, Title, Author, Subject, Keywords, Creator: PChar;
  PageWidth, PageHeight: integer); stdcall; external cPdfDll;

procedure RolePDFNewPage;
  stdcall; external cPdfDll;

procedure RolePDFEndDoc;
  stdcall; external cPdfDll;

function RolePDFGetDC: HDC;
  stdcall; external cPdfDll;

function RolePDFPageCount: integer;
  stdcall; external cPdfDll;

function RolePDFPageWidth: integer;
  stdcall; external cPdfDll;

function RolePDFPageHeight: integer;
  stdcall; external cPdfDll;

{ TDinAPage }

function TDinAPage.GetLandscape: boolean;
begin
  Result := FDinAFormat in [DinALandscape0, DinALandscape1, DinALandscape2,
    DinALandscape3, DinALandscape4];
end;

procedure TDinAPage.SetDinAFormat(const Value: TDinAFormat);
var
  X, Y: integer;
begin
  FDinAFormat := Value;
  case FDinAFormat of
    DinAPortrait3, DinALandscape3:
    begin
      X := 297;
      Y := 2 * 210;
    end;
    DinAPortrait2, DinALandscape2:
    begin
      X := 2 * 210;
      Y := 2 * 297;
    end;
    DinAPortrait1, DinALandscape1:
    begin
      X := 2 * 297;
      Y := 4 * 210;
    end;
    DinAPortrait0, DinALandscape0:
    begin
      X := 4 * 210;
      Y := 4 * 297;
    end
    else // DinAPortrait4, DinALandscape4:
    begin
      X := 210;
      Y := 297;
    end;
  end;
  if Landscape then
  begin
    FMMWidth := Max(X, Y);
    FMMHeight := Min(X, Y);
  end
  else
  begin
    FMMWidth := Min(X, Y);
    FMMHeight := Max(X, Y);
  end;
end;

{ TPdf }

constructor TPdf.Create(const DinAFormat: TDinAFormat);
begin
  FCanvas := TCanvas.Create;
  FCanvas.Font.Charset := ANSI_CHARSET;
  FPixelsPerInch := DeviceCaps;
  FAutoLaunch := true;
  FDinAPage.DinAFormat := DinAFormat;
end;

destructor TPdf.Destroy;
begin
  FCanvas.Free;
  inherited;
end;

function TPdf.GetPageWidth: integer;
begin
  Result := Round(FPixelsPerInch / 25.4 * FDinAPage.MMWidth);
end;

function TPdf.GetPageHeight: integer;
begin
  Result := Round(FPixelsPerInch / 25.4 * FDinAPage.MMHeight);
end;

function TPdf.GetMMWidth: double;
begin
  Result := FDinAPage.MMWidth;
end;

function TPdf.GetMMHeight: double;
begin
  Result := FDinAPage.MMHeight;
end;

function TPdf.GetDinAFormat: TDinAFormat;
begin
  Result := FDinAPage.DinAFormat;
end;

function TPDF.DeviceCaps: integer;
var
  DC: HDC;
begin
  DC := GetDC(0);
  try
    Result := GetDeviceCaps(DC, LOGPIXELSX);
  finally
    ReleaseDC(0, DC);
  end;
end;

procedure TPdf.BeginDoc;
begin
  RolePDFBeginDoc(PChar(''), PChar(FFileName), PChar(FTitle), PChar(FAuthor),
    PChar(FSubject), PChar(FKeywords), PChar(FCreator),
    Round(cPdfDllPixelsPerInch / FPixelsPerInch * PageWidth),
    Round(cPdfDllPixelsPerInch / FPixelsPerInch * PageHeight));
end;

procedure TPdf.NewPage;
begin
  RolePDFNewPage;
end;

procedure TPdf.EndDoc;
begin
  RolePDFEndDoc;
  if FAutoLaunch then
    ShellExecute(0, 'open', PChar(FFileName), nil, nil, SW_SHOW);
end;

function TPdf.GetCanvas: TCanvas;
begin
  FCanvas.Handle := RolePDFGetDC;
  Result := FCanvas;
end;

function TPdf.GetPageCount: integer;
begin
  Result := RolePDFPageCount;
end;

function TPdf.GetPdfPageWidth: integer;
begin
  Result := RolePDFPageWidth;
end;

function TPdf.GetPdfPageHeight: integer;
begin
  Result := RolePDFPageHeight;
end;

function TPdf.MMToPixel(const MMX, MMY: double): TPoint;
begin
  Result.X := Round(FPixelsPerInch * MMX / 25.4);
  Result.Y := Round(FPixelsPerInch * MMY / 25.4);
end;

end.

slemke76 3. Feb 2018 12:11

AW: Adobe Reader einbinden
 
Hallo,

Zitat:

Zitat von Bernhard Geyer (Beitrag 1300704)
Meine Empfehlung ist aber Adobe zu meiden und *irgendeine* (Ausnahme: Gnostice-) 3th-Party-Bibliotheken zu verwenden welche genau dieses Feature bietet.

ein ganz wenig off-topic, aber ich frage trotzdem ;-)
Ich habe die Tage Gnostice mal angetestet - gibt es einen Grund, die Komponente zu meiden?

lg

Bernhard Geyer 3. Feb 2018 13:37

AW: Adobe Reader einbinden
 
Zitat:

Zitat von slemke76 (Beitrag 1393032)
Hallo,

Zitat:

Zitat von Bernhard Geyer (Beitrag 1300704)
Meine Empfehlung ist aber Adobe zu meiden und *irgendeine* (Ausnahme: Gnostice-) 3th-Party-Bibliotheken zu verwenden welche genau dieses Feature bietet.

ein ganz wenig off-topic, aber ich frage trotzdem ;-)
Ich habe die Tage Gnostice mal angetestet - gibt es einen Grund, die Komponente zu meiden?

lg

Grund ist (zu unserer Zeit) die grotten schlechte SW-Qualität. Selbst nach einer (laut Aussage Hersteller) Kompletten Reimplementierung hatten wir sehr oft mit "real World"-PDF das Problem das in der Gnostice-Bibliothek "Amok laufende" Zeiger auftraten, die das ganze Programm zum Absturz brachten. Immer wieder waren es PDF-Elemente die noch nicht oder nicht korrekt implementiert waren. Vor allem bei Nicht-Bekannten Elementen darf eine Implementierung "wild um sich pointern".
Hab dann auch Knoctice ein paar Fehler gemeldet (welche z.B. durch Einsatz von FastMM schon während der Entwicklung auftreten hätten müssen). Nach einiger Zeit mussten wir uns klar machen das der Einsatz dieser Komponenten ein vielfaches der Lizenzkosten uns durch Fehlersuche und Workarounds gekostet hatte. Jetzt verwenden wir PDFBox und haben seid dem Wechsel praktisch keine Problem mehr in diesem Bereich.

In 2018 würde ich beim Thema PDF-Anzeigen evtl. Chromium mal eine Chance geben.

slemke76 4. Feb 2018 11:31

AW: Adobe Reader einbinden
 
Guten Morgen,

vielen Dank für die Info - ich werde da beim testen intensivst drauf achten.
Meine Anforderung ist "nur" der Ausdruck eines PDFs, ich würde aber gerne auf externe Komponenten (DLLs, etc.) verzicheten.

lg
Sebastian


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:56 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