AGB  ·  Datenschutz  ·  Impressum  







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

Plugins selbst gemacht?

Ein Thema von MichaelK · begonnen am 13. Mai 2003 · letzter Beitrag vom 21. Mai 2003
Antwort Antwort
Seite 1 von 2  1 2      
MichaelK

Registriert seit: 8. Mai 2003
10 Beiträge
 
#1

Plugins selbst gemacht?

  Alt 13. Mai 2003, 14:30
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?
  Mit Zitat antworten Zitat
Alexander

Registriert seit: 28. Aug 2002
Ort: Oldenburg
3.513 Beiträge
 
Turbo Delphi für .NET
 
#2
  Alt 13. Mai 2003, 14: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.
Alexander
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#3
  Alt 14. Mai 2003, 14:47
Für die unter Euch, welche den Thread beobachten, hier ein Link zum aktuellen Tutorial: http://www.delphipraxis.net/viewtopic.php?t=5390

......
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
MichaelK

Registriert seit: 8. Mai 2003
10 Beiträge
 
#4
  Alt 20. Mai 2003, 17: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
  Mit Zitat antworten Zitat
MichaelK

Registriert seit: 8. Mai 2003
10 Beiträge
 
#5
  Alt 20. Mai 2003, 17:43
OK, Sorry, vergesst es: ich habe vergessen die Unit SHAREMEM in das projekt einzubinden... Ohne die kann es nicht funzen
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#6
  Alt 20. Mai 2003, 22:06
Zitat von MichaelK:
@sakura (falls du das lesen solltest): du wirst den code erkennen
Natürlich habe ich das gelesen Aber Du hast den Fehler ja gefunden.

......
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
MichaelK

Registriert seit: 8. Mai 2003
10 Beiträge
 
#7
  Alt 21. Mai 2003, 12:01
taj ja, manchmal sollte man vorher denken, bevor man das Forum bemüht *leicht-selbst-kristitsch-bemerk*

anyway - plugins sind cool
  Mit Zitat antworten Zitat
MichaelK

Registriert seit: 8. Mai 2003
10 Beiträge
 
#8
  Alt 21. Mai 2003, 12: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?
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#9
  Alt 21. Mai 2003, 12: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.

......
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
MichaelK

Registriert seit: 8. Mai 2003
10 Beiträge
 
#10
  Alt 21. Mai 2003, 12: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
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 22:19 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