Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Plugins selbst gemacht? (https://www.delphipraxis.net/4829-plugins-selbst-gemacht.html)

MichaelK 13. Mai 2003 13:30


Plugins selbst gemacht?
 
Hi

ist eigentlich nur eine Spinnerei: aber kann ich mit Delphi irgendwie PlugIns für meine Programme schreiben? Damit könnte ich mein Programm erweitern, ohne groß code schreiben zu müssen - wenn ich einen PlugIn-Editor baue.

Also einfaches Beispiel: ich will einem Program die Fähigkeit geben und nehmen können z.B. Druckausgabe zu unterstützen, ohne das Programm dabei groß ändern zu müssen - einfach nur durch eine externe Datei, die auf Existenz geprüft wird.

ungefähr so:

if FilExists(PluginName+'.plg') then EnableFunction(PlugInTitle);

wobei die Befehle in einer externen Datei und in einer Speziellen Plugin-Sprache vorliegen...

Eine BEfehlsfolge könnte dann so aussehen:

PrinterCmd=CommandStream.Beginn;
CreatePrinter;
SetupPage;
PrintDocument;
DestroyPrinter;
PrinterCmd=CommandStream.End;

Hat jemand eine Idee, wie man sowas verwirklichen könnte?

Alexander 13. Mai 2003 13:35

Man könnte das zum Beispiel mit einer oder mehreren DLL's lösen.
Such mal auf der SEite, da gibt es relativ viele Beispiele mit DLL's.

sakura 14. Mai 2003 13:47

Für die unter Euch, welche den Thread beobachten, hier ein Link zum aktuellen Tutorial: http://www.delphipraxis.net/viewtopic.php?t=5390

...:cat:...

MichaelK 20. Mai 2003 16:36

Hi...

ich hab mal ein Testproramm für mein erstes Plugin geschrieben. Das Plugin an sich ist sinnlos, deshalb poste ich auch nix davon. mein Testprogramm sieht so aus:

Code:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, PluginDef;

type

  TLibraryData = record
    Handle: Cardinal;
    Plugin: TPlugin;
    MenuItem: TMenuItem;
  end;

  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    mnuPlugins: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FPlugins: array of TLibraryData;

    procedure LoadPlugin(DLLName: string);
    procedure LoadPlugins;
    procedure ExecutePlugin (Sender: TObject);
    procedure UnloadPlugins;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Inifiles;

procedure TForm1.LoadPlugins;
var
  PluginRegistryFile: string;
  i: integer;
  iniFile: TInifile;
  Plugins: TStringlist;

begin
  PluginRegistryFile := ExtractFilePath(Application.Exename)+'Plugins.ini';
  if not FileExists (PluginRegistryFile) then
    Exit;

  iniFile := TIniFile.Create(PluginRegistryFile);

  try
    Plugins := TStringlist.Create;
    try
      IniFile.ReadSections(Plugins);
      for i:= 0 to Pred(Plugins.Count) do
      begin
        if AnsiCompareText(iniFile.ReadString(Plugins[i],'type',''),'plugin') = 0 then
        begin
          LoadPlugin(iniFile.ReadString(Plugins[i],'dllname',''));
        end;
      end;
    finally
      Plugins.Free;
    end;
  finally
    iniFile.Free;
  end;


end;

procedure TForm1.LoadPlugin(DLLName: string);
var
  TempHandle: Cardinal;
  ProcAddr: Pointer;
  LoadPluginProc: TLoadPlugin;
  TempPlugin: TPlugin;
begin

    if not ((Copy(DLLName,2,1) = ':') or (Copy(DLLName, 1,2) = '\\')) then
      DLLName := ExtractFilePath(Application.Exename)+DLLName;

    TempHandle := LoadLibrary (PChar(DLLName));
    if (TempHandle <> INVALID_HANDLE_VALUE) and (TempHandle <> 0) then
    begin
       ProcAddr := GetProcAddress (TempHandle, 'LoadPlugIn');
       if ProcAddr = nil then begin
          FreeLibrary (TempHandle);
          Exit;
       end;
       LoadPluginProc := TLoadPlugin(ProcAddr);
       try
         TempPlugin := nil;
         LoadPluginProc(Application.Handle, TempPlugin);
       except
         FreeLibrary(TempHandle);
         exit;
       end;
       SetLength(FPlugIns, Succ(Length(FPlugins)));
       FPlugins[High(Fplugins)].Handle := TempHandle;

       //Add the Plugin to the menu
       with FPlugins[High(FPlugins)] do begin
          Plugin := TempPlugin;
          MenuItem := TMenuItem.Create(Self);
          MenuItem.Caption := TempPlugin.GetMenuText;
          MenuItem.Enabled := TempPlugin.GetEnabled;
          MenuItem.Tag := High(FPlugins);
          MenuItem.OnClick := ExecutePlugin;
       end;
       mnuPlugins.Add(FPlugins[High(Fplugins)].MenuItem);
    end;
end;

procedure TForm1.ExecutePlugin (Sender: TObject);
begin
  if Sender = nil then
    exit;

  if not (Sender is TMenuItem) then
    exit;

(*  if FPlugins[TMenuItem(Sender).Tag].Plugin <> nil then
    FPlugins[TMenuItem(Sender).Tag].Plugin.Execute; *)

  if FPlugins[(Sender as TMenuItem).Tag].Plugin <> nil then
    FPlugins[(Sender as TMenuItem).Tag].Plugin.Execute;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetLength(FPlugins, 0);
  LoadPlugins;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnloadPlugins;
end;

procedure TForm1.UnloadPlugins;
var i: integer;
begin
  if Length(FPlugins) > 0 then
  begin
    for i:= 0 to Pred(Length(FPlugins)) do
    try
      if FPlugins[i].MenuItem <> nil then
        FPlugins[i].MenuItem.Free;
      if FPlugins[i].Plugin <> nil then
        FPlugins[i].Plugin.Free;
      FreeLibrary(FPlugins[i].Handle);
    except
    end;
  end;
end;

end.
in der unit PluginDef steht nur die Definition (also die Klasse) wie ein Plugin aufgebaut ist.

Wenn ich auf den erstellten Menüpunkt klicke, bekomme ich beim ersten Klicken eine "INVALID POINTER OPERATION". Bei weiteren Klicks funktioniert es. Beim Beenden des Programms bekomme ich eine AccessViolation an der Adresse $00000000.
Meine große Frage: WARUM?

@sakura (falls du das lesen solltest): du wirst den code erkennen :-)

MichaelK 20. Mai 2003 16:43

OK, Sorry, vergesst es: ich habe vergessen die Unit SHAREMEM in das projekt einzubinden... Ohne die kann es nicht funzen :oops: :twisted: :mrgreen: :coder: :witch: :nerd: :freak: :bounce1: :bouncing4: :dancer2:

sakura 20. Mai 2003 21:06

Zitat:

Zitat von MichaelK
@sakura (falls du das lesen solltest): du wirst den code erkennen :-)

Natürlich habe ich das gelesen :-D Aber Du hast den Fehler ja gefunden.

...:cat:...

MichaelK 21. Mai 2003 11:01

taj ja, manchmal sollte man vorher denken, bevor man das Forum bemüht *leicht-selbst-kristitsch-bemerk*

:dancer: anyway - plugins sind cool

MichaelK 21. Mai 2003 11:34

hmmm, irgendwie hab ich's zur Zeit mit AccessViolations, ich schaff es immer wieder, egal, was ich mache... Spaß beiseite.
Rein theoretisch müsste ich die Klasse TPlugIn mit ein paar Prozeduren erweitern können. Ich will nämlich ein Aboutbox-Plugin schreiben und der Form, die ich in das Plugin eingebunden habe, ein paar Informationen geben:
  • Den Progeammnamen
    die Programmversion
    ein Copyright
    ein paar Kommentare
    und ein Bild


Dashier:
Code:
public
    constructor Create(aParent: THandle);

    procedure SubmitPicutre(Filename: string); virtual; stdcall; abstract;
    procedure SubmitProductname(Productname: string); virtual; stdcall; abstract;
    procedure SubmitVersion(Version: string); virtual; stdcall; abstract;
    procedure SubmitCopyright(Copyright: string); virtual; stdcall; abstract;
    procedure SubmitComments(Comments: string); virtual; stdcall; abstract;
wäre meine Methode die Klasse zu erweitern... Geht aber nicht, wegen der oben angesprochenen AccessViolation, die auftritt, wenn das Plugin geladen werden soll.

Ja, ich hab ShareMem eingebunden, in die DLL und in mein Projekt. Die INI stimmt auch... Die Borland DLL ist auch vorhanden...

Und nu?

sakura 21. Mai 2003 11:41

Hast Du die ShareMem Unit auch als erste Unit in die Projekt uses-Klausel von Anwendung und DLL genommen? Wenn ja, zeige mal die PlugIn-Klasse der DLL.

...:cat:...

MichaelK 21. Mai 2003 11:45

ich poste einfach mal die komplette DLL (ist noch nicht soo lange)

Code:
library Aboutplg;

uses
  ShareMem,
  SysUtils,
  Classes,
  Windows,
  Forms,
  PluginDef in '..\Shared\PluginDef.pas',
  frmPlugAbout in 'frmPlugAbout.pas' {AboutBox};

{$R *.res}

type
  TPluginAbout = class (TPlugIn)
  private
    FPicFilename, FProductname, FCopyright, FVersion, FComments: string;
  public
    constructor Create(aParent: THandle);
    procedure SubmitPicutre(Filename: string); override; stdcall;
    procedure SubmitProductname(Productname: string); override; stdcall;
    procedure SubmitVersion(Version: string); override; stdcall;
    procedure SubmitCopyright(Copyright: string); override; stdcall;
    procedure SubmitComments(Comments: string); override; stdcall;
    // information strings
    function GetName: string; override; stdcall;
    function GetAuthor: string; override; stdcall;
    function GetComment: string; override; stdcall;
    // menu data
    function GetMenuText: string; override; stdcall;
    function GetEnabled: Boolean; override; stdcall;
    // launch the Expert
    procedure Execute; override; stdcall;
    // event handler
    function EventHandler(EventNotification: TEventNotification): TEventAction;
        override; stdcall;
  end;

procedure TPluginAbout.SubmitPicutre(Filename: string); stdcall;
begin
  FPicFilename := Filename;
end;

procedure TPluginAbout.SubmitProductname(Productname: string); stdcall;
begin
  FProductname := Productname;
end;

procedure TPluginAbout.SubmitVersion(Version: string); stdcall;
begin
  FVersion := Version;
end;

procedure TPluginAbout.SubmitCopyright(Copyright: string); stdcall;
begin
  FCopyright := Copyright;
end;

procedure TPluginAbout.SubmitComments(Comments: string); stdcall;
begin
  FComments := Comments;
end;


constructor TPluginAbout.Create(aParent: THandle);
begin
  inherited Create(aParent);
  FProductname := 'Aboutplg.dll';
  FVersion := '1.0';
  FCopyright := 'Copyright(C) 2003 by Michael Kirches';
  FComments := 'This is a test plugin';
end;


// information strings
function TPluginAbout.GetName: string; stdcall;
begin
  result := 'About Plugin';
end;

function TPluginAbout.GetAuthor: string; stdcall;
begin
  result := 'Michael Kirches';
end;

function TPluginAbout.GetComment: string; stdcall;
begin
  result := 'This plugin creates and handles an aboutbox';
end;
// menu data
function TPluginAbout.GetMenuText: string; stdcall;
begin
  result := 'About';
end;

function TPluginAbout.GetEnabled: Boolean; stdcall;
begin
  result := True;
end;
// launch the Expert
procedure TPluginAbout.Execute; stdcall;
begin
//  MessageBox(Parent, 'This is Plugin No. 1 calling.','Info',0);
  //Now we've got something todo...
  try
    Aboutbox := TAboutbox.Create(Application);
    if FPicFilename <> '' then Aboutbox.ProgramIcon.Picture.LoadFromFile(FPicFilename);
    Aboutbox.ProductName.Caption := FProductname;
    Aboutbox.Version.Caption := FVersion;
    Aboutbox.Copyright.Caption := FCopyright;
    Aboutbox.Comments.Caption := FComments;
    Aboutbox.Rescale;
    Aboutbox.ShowModal;
  finally
    Aboutbox.Free;
  end;
end;
// event handler
function TPluginAbout.EventHandler(EventNotification: TEventNotification): TEventAction;
    stdcall;
begin
  result := evnContinue;
end;

function LoadPlugin(Parent: THandle; var PlugIn: TPlugIn): Boolean; export;
begin
  try
    PlugIn := TPluginAbout.Create(Parent);
    Result := True;
  except
    Result := False;
  end;
end;

exports
  LoadPlugIn name 'LoadPlugIn';

begin
end.
Da fehlt noch eine Prozedur, die dann die Aboutbox updaten soll, aber das kriege ich dann schon hin, wenn ich weiß, was ich falsch gemacht habe...

Ach ja: ShareMem ist in beiden Projekten die erste Unit in der uses-clause


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:02 Uhr.
Seite 1 von 2  1 2      

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