Dieses Tutorial zeigt, wie ein minimales Add-in von Grund auf erstellt wird. Am Ende steht ein funktionierendes Add-in, das einen Command registriert, einen Menüpunkt hinzufügt und eine Benachrichtigung anzeigt.
Zurück zur Übersicht.
WvdS.Document.Host.Api)hello-world/
├── plugin.json ← Manifest
├── package.nls.json ← Standard-Übersetzung
├── bin/
│ └── HelloWorld.dll ← Wird vom Compiler erzeugt
├── media/
│ └── hello.svg ← Command-Icon
└── src/
├── HelloWorld.lpr ← Library-Hauptdatei
└── HelloWorldPlugin.pas ← Plugin-Implementierung
Die Datei plugin.json beschreibt das Add-in vollständig. Der Host liest sie, bevor die DLL geladen wird.
{ "id": "demo.hello-world", "name": "hello-world", "displayName": "Hello World", "description": "Ein minimales Beispiel-Add-in", "version": "1.0.0", "publisher": "demo", "kind": "native", "main": "bin/HelloWorld.dll", "engineVersion": "^1.0.0", "activationEvents": [ "onCommand:hello.sayHello" ], "permissions": [], "contributes": { "commands": [ { "command": "hello.sayHello", "title": "Hallo sagen", "category": "Hello" } ], "menus": { "menuBar/help": [ { "command": "hello.sayHello", "group": "demo", "order": 1 } ], "commandPalette": [ { "command": "hello.sayHello" } ] } } }
Die Datei deklariert einen einzigen Command (hello.sayHello), der im Hilfe-Menü erscheint und über die CommandPalette erreichbar ist. Das activationEvents-Array sagt dem Host, dass die DLL erst geladen werden soll, wenn dieser Command zum ersten Mal aufgerufen wird.
Die Datei HelloWorld.lpr ist der Einstiegspunkt der DLL. Sie exportiert die beiden Funktionen, die der Host erwartet.
library HelloWorld; {$mode objfpc}{$H+} uses WvdS.Document.Host.Api, HelloWorldPlugin; const WVDS_MAGIC = $57564453; ABI_VERSION = 1; FPC_VERSION = {$I %FPCVERSION%}; function GetAbiInfo: TPluginAbiInfo; stdcall; begin Result.Magic := WVDS_MAGIC; Result.AbiVersion := ABI_VERSION; Result.FpcVersion := FPC_VERSION; end; function CreatePlugin(const AHost: IHost): IPlugin; stdcall; begin Result := THelloWorldPlugin.Create(AHost); end; exports GetAbiInfo, CreatePlugin; end.
GetAbiInfo liefert die Kompatibilitätsinformationen. Der Host prüft Magic-Number, ABI-Version und FPC-Version, bevor er CreatePlugin aufruft. CreatePlugin erzeugt das Plugin-Objekt und gibt es als IPlugin zurück.
Die Datei HelloWorldPlugin.pas enthält das Plugin und seinen Command-Handler.
unit HelloWorldPlugin; {$mode objfpc}{$H+} interface uses WvdS.Document.Host.Api; type THelloWorldPlugin = class(TInterfacedObject, IPlugin) private FHost: IHost; public constructor Create(const AHost: IHost); procedure Activate(const AContext: IExtensionContext); procedure Deactivate; end; implementation type TSayHelloHandler = class(TInterfacedObject, ICommandHandler) private FHost: IHost; public constructor Create(const AHost: IHost); procedure Execute; end; { THelloWorldPlugin } constructor THelloWorldPlugin.Create(const AHost: IHost); begin inherited Create; FHost := AHost; end; procedure THelloWorldPlugin.Activate(const AContext: IExtensionContext); begin AContext.Subscribe( FHost.Commands.RegisterCommand('hello.sayHello', 'Hallo sagen', TSayHelloHandler.Create(FHost)) ); end; procedure THelloWorldPlugin.Deactivate; begin // Nichts zu tun — der Host räumt alle Registrierungen automatisch auf. end; { TSayHelloHandler } constructor TSayHelloHandler.Create(const AHost: IHost); begin inherited Create; FHost := AHost; end; procedure TSayHelloHandler.Execute; begin FHost.Notifications.ShowInfo('Hallo von Hello World!'); end; end.
Der TSayHelloHandler ist der eigentliche Code hinter dem Command. Wenn der Benutzer „Hallo sagen“ auswählt, ruft der Host Execute auf, und das Add-in zeigt eine Benachrichtigung an.
Wichtig: Die Deactivate-Methode ist leer. Das ist der Normalfall, weil der Host alle über AContext.Subscribe registrierten Disposables automatisch aufräumt. Nur wenn das Add-in eigene Ressourcen verwaltet (Threads, Datenbankverbindungen), muss es in Deactivate selbst aufräumen.
fpc -FUbin -obin/HelloWorld.dll src/HelloWorld.lpr
Die DLL wird im bin/-Verzeichnis erzeugt, wo das Manifest sie erwartet („main“: „bin/HelloWorld.dll“).
Das fertige Add-in wird als .wvdsx-Paket ausgeliefert:
cd hello-world zip -r ../demo.hello-world-1.0.0.wvdsx plugin.json package.nls.json bin/ media/
wdochost --install-extension demo.hello-world-1.0.0.wvdsx
Nach dem Neustart der Anwendung erscheint „Hallo sagen“ im Hilfe-Menü und in der CommandPalette. Beim ersten Aufruf wird die DLL geladen und der Handler aktiviert.
plugin.json und liest es.hello.sayHello als Lazy-Stub und fügt den Menüpunkt ins Hilfe-Menü ein.HelloWorld.dll, ruft GetAbiInfo und CreatePlugin auf.THelloWorldPlugin.Activate registriert den echten Handler.TSayHelloHandler.Execute aus. Die Benachrichtigung erscheint.Ab diesem Punkt ist das Add-in aktiv. Jeder weitere Aufruf des Commands geht direkt an den Handler, ohne erneute Aktivierung.
Weiter zum Document-View Tutorial oder zurück zur Übersicht.