Sonntag, 7. September 2008

entwickler.com Magazine Konferenzen Akademie Entwickler-Forum Jobbörse Bücher
Software & Support Verlag




April 2006
aus Der Entwickler Ausgabe: 03.2004
Plugins für Adobe Acrobat
Programmieren mit dem Acrobat SDK
von Cord Jastram

Für Adobe Acrobat 6.0 existiert eine in C implementierte Programmierschnittstelle, durch die ein Entwickler das Programm nach eigenen Vorstellungen anpassen oder erweitern kann. Die Möglichkeiten reichen von einfachen Aufgaben wie z.B. der Änderungen der Benutzungsoberfläche über die Entwicklung von eigenen Komponenten für die elektronische Signatur von PDF-Dateien bis zu komplexen Aufgabenstellungen wie die Integration von Acrobat in ein Dokumenten Management System. Dieser Artikel soll einen ersten Einblick in die Programmierung der so genannten Plugins für Acrobat unter Windows geben.


Das von Adobe eingeführte PDF-Format stellt heute den Quasistandard für plattformübergreifende elektronische Dokumente dar. PDF-Dateien werden über den kostenlos erhältlichen Acrobat Reader stets im Original-Layout mit allen Schriften, Grafiken und Sonderzeichen gedruckt und kommen dem WYSIWIG - Versprechen recht nahe, insbesondere dann, wenn eine Vielzahl von Ausgabegeräten unterstützt werden soll. Die kostenpflichtige Versionen Adobe Acrobat 6.0 bzw. Acrobat Professional ermöglichen die komfortable Erstellung und Bearbeitung von PDF-Dateien, wobei insbesondere die gute Integration in die Microsoft Office Familie über den mitgelieferten PDF Maker hervorzuheben ist. Weitgehend unbekannt ist jedoch die Tatsache, dass alle Produkte über ein in C implementiertes Software Development Kit (SDK) nach eigenen Wünschen über so genannte Plugins modifiziert werden können oder sogar als Plattform für eigene Anwendungen dienen können. Dieser Mechanismus wird von Adobe selbst für die Entwicklung der Acrobat Produktfamilie genutzt und viele Erweiterungen der Kernfunktionalität wie z.B. die Formularfunktionalität und der HTML nach PDF-Konverter sind über ein Plugin realisiert.

Dieser Artikel vermittelt nur einen allerersten Überblick über die Programmierung mit dem Acrobat SDK unter Windows. Und auch der Überblick kann nicht alle Aspekte der Entwicklung skizzieren, was aber bei einer PDF-Spezifikation von über 1150 Seiten und einem auf über 3300 Seiten dokumentiertem Core-API des SDK nicht weiter verwunderlich ist.

Die Entwicklungsumgebung und die Dokumentation
Für die Entwicklung benötigt man Microsoft Visual C++ 6.0 sowie die aktuelle Adobe Acrobat Version 6.0. Visual Studio .NET wird zu Zeit nicht offiziell als Entwicklungsplattform unterstützt. Plugins können auch für die Macintosh-Plattform entwickelt werden; dieser Artikel beschränkt sich jedoch auf die Entwicklung unter Windows. Das komplette Acrobat SDK ist seit der Version 6.0 leider nicht mehr kostenlos erhältlich. Für den Download des kompletten SDK mit umfangreicher Dokumentation und einer Sammlung an Beispielen muss man Mitglied bei dem Acrobat Solutions Network Developer Program (ASND) werden, was bei der günstigsten Form der Mitgliedschaft mit 195 $ pro Jahr zu Buche schlägt.

Nach der kostenlosen Registrierung bei dem Adobe Solution Network (ASN) unter partners.adobe.com/asn/programs/webaccount.jsp kann man jedoch die zu dem SDK zugehörigen Header-Dateien herunterladen und auch die wichtigsten Dokumentationen sind frei verfügbar. Diese sind:
  • Acrobat Developer FAQ.
  • Acrobat Core API Reference.
  • Acrobat FORMS API Reference.
  • Adobe PDF Reference.
Die Dokumentation und die Header-Dateien findet man unter partners.adobe.com/asn/programs/index.jsp. Es lohnt sich auch, das SDK für die Acrobat Version 5.0 herunterzuladen, da die dort mitgelieferten Beispielprogramme und Dokumentationen auch für die Version 6.0 von Interesse sind.

Es besteht die Möglichkeit, Plugins auch für den Acrobat Reader zu entwickeln. Es müssen dabei jedoch technische und lizenzrechtliche Einschränkungen beachtet werden. Je nachdem, ob die Plugins kostenlos abgegeben werden oder gegen Entgeld vertrieben werden und ob sie nur für den internen Gebrauch in einer Firma oder frei erhältlich sind, werden Lizenzgebühren bis zu 2500 $ erhoben. Die wichtigste technische Einschränkung besteht darin, dass Plugins für Acrobat Reader keine Änderungen an PDF-Dateien vornehmen können. Weitere Informationen befinden sich auf den Adobe Webseiten und in der Acrobat Developer FAQ.

Die Konfiguration der Entwicklungsumgebung
Für die Entwicklung von Plugins benötigt man nur die Header-Dateien des SDK; es werden keinen Bibliotheken oder weitere Tools benötigt. Nach dem Herunterladen der Header-Dateien extrahiert man die in einer Zip-Datei zusammengefassten Dateien in ein beliebiges Unterverzeichnis. Die für die Plugin-Entwicklung benötigten Dateien liegen dann in den Unterverzeichnis PluginSupport\Headers, PluginSupport\Headers\Headers sowie in PluginSupport\Headers\ADMHeaders. Es empfiehlt sich, die angegebenen Verzeichnisse in die Liste der nach Include-Dateien zu durchsuchenden Verzeichnisse aufzunehmen.

In dem Unterverzeichnis PluginSupport\Samples\Starter findet man die Minimalversion einer Visual C++-Projektdatei für ein Plugin. Nach dem Öffnen der Projektdatei starter.dsw wählt man noch den vollständigen Pfad für Acrobat.exe als ausführbare Datei für das Debugging in den Projekteinstellungen aus und gibt bei den Optionen für den Linker als Ausgabedatei den Plugin-Namen mit der Dateiendung api in den Plugin-Ordner von Acrobat. Dann kann man Acrobat über den VC++ Debugger starten und das Plugin direkt debuggen. Abbildung 1 zeigt einen Ausschnitt der Verzeichnisstruktur der Acrobat Installation. Der Plugin-Order besitzt den Name plug_in.


Abb. 1: Verzeichnisstruktur der Acrobat Installation

Das Plugin-Präfix
Der Zugriff auf Ressourcen findet innerhalb des Acrobat SDK in vielen Fällen über einen Namen statt. Sollen selbst entwickelte Plugins zusammen mit Plugins von Drittanbietern installiert werden, so muss sichergestellt sein, dass die verwendeten Namen eindeutig sind, damit z.B. nicht zwei unterschiedliche Plugins einen Menüeintrag mit gleichem Namen in die Acrobat-Menüleiste einbauen. Deshalb können Entwickler bei Adobe ein eindeutiges Präfix registrieren lassen, der aus vier Zeichen besteht. Stellt man das Präfix allen Bezeichnern voran, so wird dadurch ein eindeutiger Namensraum definiert und es kann zu keinen Überschneidungen kommen.

Das Acrobat SDK API
Das API des Acrobat SDK ist in der Programmiersprache C implementiert. Das SDK besticht durch ein durchdachtes Design der nach Außen hin sichtbaren Schnittstellen. Die Implementierung ist objektbasiert, wobei konsequent das Geheimnisprinzip (Information Hiding) verwendet wird. Nur an wenigen Stellen, insbesondere dann, wenn auf Windows-Interna zugegriffen wird, sind die internen Datenstrukturen offen zugänglich. In allen anderen Fällen existieren Objekte in Form von opaquen Datentypen, d.h. die innere Struktur ist für den Entwickler nicht bekannt, sie wird über einen Satz von Funktionen manipuliert.

Die Objekte und die zugehörigen Funktionen lassen sich wie in Abbildung 2 dargestellt in drei Kategorien einteilen. Die erste Kategorie bilden die Methoden und Objekte der Acrobat Viewer (AV) Schicht. Sie ermöglicht es, die eigentliche Acrobat-Anwendung zu programmieren und zu modifizieren. Alle Objekte einer Schicht sowie fast alle Funktionsaufrufe beginnen mit dem jeweiligen Kürzel der Schicht wie AV oder PD.


Abb. 2: Die Schichten des Acrobat SDK

Die zweite Kategorie bilden die Methoden und Objekte, über die der Entwickler auf PDF-Dateien und ihre internen Strukturen zugreifen kann. Zu dieser Kategorie gehört die Portable Document Schicht (PD), die auf einem hohen Abstraktionsniveau arbeitet. Im Gegensatz dazu stellt die Commom Object System-Schicht (COS) den PDF-Assembler dar, mit Hilfe dessen man auf die grundlegenden Bausteine einer PDF-Datei wie z.B. Arrays, Dictionaries und Streams zugreifen kann. Im Gegensatz zu der Funktionalität der PD-Schicht kann man mit der COS-Schicht-Datei erzeugen, die nicht der PDF-Spezifikation entsprechen. Um dem Entwickler die Arbeit zu erleichtern existiert deshalb die PDFEdit-Gruppe, die einen sicheren Zugang zu den Low-Level PDF-Objekten ermöglicht, aber stets die Korrektheit des erzeugten PDF-Dokumentes sicherstellt. Zusätzlich existiert noch die PDSEdit-Gruppe für die Bearbeitung von Strukturinformationen in einer PDF-Datei.

Die dritte Kategorie wird durch die Acrobat Support (AS) Schicht gebildet. Sie ermöglicht den plattformunabhängigen Zugriff auf das verwendete Dateisystem und bietet eine Vielzahl von häufig benötigten Hilfsfunktionen. Die unterschiedlichen Schichten sollen an Hand eines einfachen Beispiels illustriert werden. Eine PDF-Datei wird in der AV-Schicht durch den Objekttyp AVDoc repräsentiert. Die zur Verfügung gestellten Funktionen arbeiten immer mit einer in der Anwendung geladenen PDF-Datei. Zu der gebotenen Funktionalität gehört z.B. das Drucken der Datei über die Funktion void AVDocDoPrint(AVDoc avDoc) oder das Sichern der Datei über die Funktion AVDocDoSave(AVDoc avDoc). Die PD-Schicht ermöglicht über den Objekttyp PDDoc den Zugriff auf eine PDF-Datei, ohne dass die Datei in der Anwendung geladen sein muss. Die Datei kann dann über Funktionen wie void PDDocMovePage(PDDoc pdDoc, ASInt32 moveToAfterThisPage, ASInt32 pageToMove) modifiziert werden. Öffnet man eine PDF-Datei in der Cos-Schicht, so kann man gezielt auf einzelne Bestandteile der PDF-Datei zugreifen, z.B. über die Funktion CosObj CosDocGetRoot(CosDoc cosDoc). Die Arbeit mit den Objekten der Cos-Schicht erfordert dann jedoch genaue Kenntnisse der PDF-Spezifikation.

Die hier vorgestellte Kernfunktionalität des SDK wird von Adobe durch eine Vielzahl von Plugins erweitert. Von besonderem Interesse sind dabei das Acrobat Forms API, das den Zugriff auf Formularfelder innerhalb einer PDF-Datei ermöglicht und das Digital Signature API, das das elektronische Signieren von PDF-Dateien unterstützt.

Javascript
Eigentlich kann man alle Programmieraufgaben für die Manipulation von PDF-Dateien mit Hilfe der PD und der COS-Gruppe lösen. In der Praxis dauert es jedoch oft sehr lange, bis man die benötigte Funktionalität in der Dokumentation gefunden hat und noch länger, bis die Implementierung fertig gestellt ist. Hier hilft es oft, auf die Funktionalität des in Acrobat enthaltenen Javascript-Interpreter zurückzugreifen. Das Acrobat Forms API stellt dafür die Funktion AFExecuteThisScript zur Verfügung, der beliebiger Javascript-Quelltext als Argument übergeben werden kann. Dieser Quelltext wird dann innerhalb des Funktionsaufrufs durch den Javascript-Interpreter ausgeführt.

Dies ist zwar nicht immer die eleganteste Vorgehensweise, aber sie bringt den Entwickler oft sehr schnell ans Ziel. Außerdem besitzt die Acrobat Vollversion einige Fähigkeiten, die nur über die Javascript-Schnittstelle angesprochen werden können. Dazu gehört z.B. die Möglichkeit, per SOAP (Simple Object Access Protocoll) auf ein externes System zuzugreifen.

Wie wird ein Plugin geladen
Ein Plugin unter Windows ist eine DLL mit der Dateiendung .api, die sich in dem Plugin-Verzeichnis der Acrobat-Installation oder in einem direkt darunter liegenden Unterverzeichnis befindet. Dateien in tiefer geschachtelten Unterverzeichnissen werden nicht als Plugin erkannt. Für die Installation eines Plugins ist es am einfachsten, alle benötigten Dateien sowie das Plugin selbst in einem Unterverzeichnis zu gruppieren.

Die DLL wird während des Acrobat Startvorganges über die Funktion LoadLibrary aus dem Win32-API geladen. Für jedes gefundene Plugin werden während des Ladevorganges folgenden Funktionen aufgerufen:
  • PluginExportHFTs ermöglicht es, Funktionen aus einem Plugin anderen Plugins zur Verfügung zu stellen. Dies geschieht dadurch, dass das Plugin ein Array mit Funktionszeigern auf die zu exportierenden Funktionen füllt. Diese Arrays werden Host Function Tables (HFT) genannt und sind letztendlich die technologische Basis für das dynamische Laden von Plugins.
  • PluginImportReplaceAndRegister ermöglicht es Funktionen von anderen Plugins zu importieren, vorhandene Acrobat Funktionen durch eigene zu ersetzen und sich für bestimmte Nachrichten zu registrieren.
  • PluginInit: In dieser Funktion werden alle für das Plugin benötigten Initialisierungen durchgeführt wie z.B. die Anpassung der Benutzungsoberfläche.
Vor dem Entladen des Plugins kann der Entwickler in der Fuktion PluginUnload alle vorher belegten Ressourcen wieder freigeben. Dies gilt besonders für den belegten Speicher sowie die angemeldeten Callback-Funktionen.

Ein einfaches Plugin
In dem letzen Abschnitt des Artikels wird jetzt ein einfaches Plugin entwickelt, das es ermöglicht, alle in der Liste der zuletzt geöffneten Dateien befindlichen PDF-Dateien in einem Schritt zu öffnen. Prinzipiell müssen bei der Entwicklung eines Plugins immer zwei Teile programmiert werden. Eine Komponente implementiert die fachliche Funktionalität, die andere Komponente sorgt dafür, dass diese Funktionalität über die Benutzungsoberfläche auch angesprochen werden kann.

In unserem Beispiel sollen die Dateien über einen neuen Menüpunkt in Acrobat geöffnet werden. In dem folgenden Quelltext ist XXXX dabei der Platzhalter für das verwendete Präfix, gExtensionID ist eine Variable die zuvor durch Acrobat initialisiert wurde. Die Anpassung der Benutzungsoberfläche erfolgt, wie schon erwähnt, in der Funktion PluginInit unter Nutzung der Funktionalität der Acrobat Viewer (AV) Gruppe. Es werden dazu die Objekttypen AVMenu und AVMenuItem verwendet:

AVMenu commandMenu = AVMenuNew ("Demo Plugin", "XXXX:Demo", gExtensionID);
AVMenuItem menuItem = AVMenuItemNew ( "&Demo1", "XXXX:Test",(AVMenu)NULL, false,<br></br> NO_SHORTCUT, 0, NULL, gExtensionID);

Für den Menüpunkt wird dann über die Funktion AVMenuItemSetExecute eine Callback-Funktion registriert, die bei der Auswahl des Menüpunktes aufgerufen wird; die Definition der Callback-Funktion erfolgt über das Macro ASCallbackCreateProto:

AVMenuItemSetExecuteProc (menuItem, ASCallbackCreateProto(AVExecuteProc, &TestCommand), NULL);

Dann werden der Menüeintrag und der zugehörige Untermenüpunkt in die Acrobat-Menüleiste eingehängt:

AVMenuAddMenuItem (commandMenu, menuItem, APPEND_MENUITEM);
AVMenubar menubar = AVAppGetMenubar ();
AVMenubarAddMenu (menubar, commandMenu, APPEND_MENU);

In Abbildung 3 erkennt man den erzeugten zusätzlichen Menüeintrag in der Acrobat Menüleiste. Im letzten Schritt wird die als Callback registrierte Funktion TestCommand implementiert. Die Funktion liest die Einträge für die zuletzt verwendeten Dateien in der Registry und öffnet dann die Dateien.

Funktionen des SDK liefern in den meisten Fällen keine Rückgabewerte, die über den Erfolg oder Misserfolg eines Funktionsaufrufs informieren. Stattdessen werden bei Fehlern Ausnahmen aufgeworfen, die über Macros implementiert sind. In der einfachsten Form verwendet man die Macros DURING, HANDLER und END_HANDLER. Die Implementierung der Funktion TestCommand sieht somit folgendermaßen aus (Listing1).

Listing 1

ACCB1 void ACCB2 TestCommand (void *data) {

HKEY hKey = NULL;
LONG lResult;
DWORD dwSize = 0;
DWORD dwType;
char strPath[260];
char strKey[60];
char* keyTemplate =
"Software\\Adobe\\Adobe Acrobat\\6.0\\AVGeneral\\cRecentFiles\\c%i";

lResult = ERROR_SUCCESS;
int count = 0;
while (true) {
count++;
sprintf(strKey, keyTemplate, count);
lResult = ::RegOpenKeyEx (HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey);
lResult = ::RegQueryValueEx (hKey, "sDI", NULL, &dwType, NULL, &dwSize);
lResult = ::RegQueryValueEx (hKey, "sDI", NULL, &dwType, (LPBYTE)strPath, &dwSize);
if (lResult != ERROR_SUCCESS)
break;

DURING

ASPathName pathName = ASFileSysPathFromDIPath (NULL, strPath, NULL);
AVDocOpenFromFile (pathName, NULL, NULL);

HANDLER
// Fehlerbehandlung

END_HANDLER
}
return;
}


Abb. 3: Der neue Menüeintrag für das Plugin

Der Programmieraufwand liegt in dem Auslesen der Einträge in der Registry; das eigentliche Öffnen der Dateien erfolgt komfortabel über den Aufruf von AVDocOpenFromFile.

Fazit
Das in diesem Artikel vorgestellte Acrobat Software Development Kit ermöglicht es, Adobe Acrobat nach eigenen Vorstellungen anzupassen und zu erweitern. Die Komplexität des Acrobat zu Grunde liegenden PDF-Formates führt jedoch dazu, dass das API sehr komplex und sehr umfangreich ist. Geht das Entwicklungsziel über die in einem Beispiel implementierte reine Anpassung der Benutzungsoberfläche hinaus, so sollte man eine mehrwöchige Einarbeitungszeit einplanen. Mit den dann zur Verfügung stehenden Möglichkeiten kann man jedoch auch sehr komplexe Aufgaben unter der Verwendung der PDF- und Acrobat-Technologie lösen.


    Hat Ihnen dieser Artikel gefallen? Dann abonnieren Sie das Entwickler Magazin direkt über unser Online-Formular.



zur vorherigen Seite
zurück
an den Anfang der Seite
nach oben
Diesen Artikel drucken
drucken
Diesen Artikel weiterempfehlen
empfehlen
Software & Support Verlag GmbH