插件框架

{*******************************************************}
{                                                       }
{       插件管理                                        }
{                                                       }
{       版权所有 (C) 2008 咏南工作室(陈新光)            }
{                                                       }
{*******************************************************}

unit untMPlg;

interface
uses
  Classes,Windows, Messages, SysUtils, Variants,
   Graphics, Controls, Inifiles,Forms,menus,dialogs;
Type

  PDescPlg = ^TDescPlg;
  TDescPlg = record
    MName:pchar;      //菜单名
    PMItemName:pchar;      //父菜单名
    MForm:integer; //模式窗体?
  end;

  TPlgDesc = function :Pointer;stdcall;
  TShowPlgForm = function(AHandle:THandle;mForm:integer;AOwner:TWinControl):Pointer;stdcall;
  TClosePlgForm = procedure(AForm:Pointer);stdcall;

  { 插件状态保存 }
  TPlgHolder = class(TObject)
  private
    FDllHandle:integer;   //插件DLL地址
    FPForm:Pointer;       //Form的地址
    FMForm:integer;       //模式窗体
    FPlgName:string;       //插件名(即在菜单上显示的名字)
    FHostHandle:THandle;
    FOwner:TWinControl;   // 非模式窗体的父控件
  public
    procedure ClickHandler(Sender: TObject);
  published
    property DLLHandle:integer read  FDllHandle write FDllHandle;
    property MForm:integer read FMForm write FMForm;
    property PlgName:string read FPlgName write FPlgName;
    property HostHandle:THandle read FHostHandle write FHostHandle;
    property FormOwner:TWinControl read FOwner write FOwner;
  end;

  { 插件管理 }
  TMplg = class(TObject)
  private
     FPlgForms:TStrings;
     FMenu: TMenu;
     FMPlgHostHandle:THandle;
     FMplgFormOwner:TWinControl;
  public
    Constructor Create;
    destructor Destory;
    procedure GetPlgLists;
    procedure LoadPlugin(sr: TSearchRec);
  published
    property menu: TMenu read  FMenu write FMenu;
    property MplgHostHandle:THandle read FMPlgHostHandle write FMPlgHostHandle;
    property MplgFormOwner:TWinControl read FMplgFormOwner write FMplgFormOwner;
  end;

var
  Mplg :TMplg;
 
implementation

uses untMain;

{ TMplg }

procedure TMplg.GetPlgLists;
var
 sr:     TSearchRec;
 path:   string;
 Found:  Integer;
begin
 path := ExtractFilePath(Application.Exename);
  try
   Found := FindFirst(path + 'Plugins/*.dll', 0, sr);
    while Found = 0 do begin
      LoadPlugin(sr);
      Found := FindNext(sr);
    end;
  finally
   FindClose(sr);
  end;
end;

procedure TMplg.LoadPlugin(sr: TSearchRec);
var
  DescribeProc: TPlgDesc;
  DLLhandle :integer;
  i:integer;
  APlgHolder:TPlgHolder;
  MItem : TMenuItem;
    { 包自描述内容 }
  MName:pchar;      //菜单名
  PMItemName:pchar;      //父菜单名
  MForm:integer; //模式窗体?
begin
  DLLHandle := LoadLibrary(PChar('Plugins/'+(sr.Name)));
  if DLLHandle <> 0 then
  begin
    // 查找 DescribePlugin.
    DescribeProc := GetProcAddress(DLLHandle, 'PlgDesc');
    if Assigned(DescribeProc) then
    begin
      PMItemName := PDescplg(DescribeProc)^.PMItemName;
      MForm := PDescplg(DescribeProc)^.MForm;
      MName := PDescplg(DescribeProc)^.MName;

      APlgHolder := TPlgHolder.Create;
      APlgHolder.DLLHandle := DLLhandle;
      APlgHolder.MForm := MForm ;
      APlgHolder.PlgName := MName;
      AplgHolder.HostHandle := FMPlgHostHandle;
      APlgHolder.FormOwner := FMplgFormOwner;
      { 动态创建菜单 }
      MItem := TMenuItem.Create(nil);
      MItem.OnClick :=  APlgHolder.ClickHandler;
      MItem.Caption := APlgHolder.PlgName;

      for i:=0 to FMenu.Items.Count-1 do
      begin
        if FMenu.Items[i].name = PMItemName  then
        begin
          FMenu.items[i].Add(MItem);
          break;
        end;
      end;
     FPlgForms.AddObject(APlgHolder.PlgName,APlgHolder);
    end;
  end;
end;

constructor TMplg.Create;
begin
  FPlgForms := TStringList.Create;
end;

destructor TMplg.Destory;
var
  i:integer;
  APlgHolder:TPlgHolder;
  ClosePlgForm:TClosePlgForm;
begin
  for  i := 0  to FPlgForms.Count-1 do
  begin
    APlgHolder := TPlgHolder(FPlgForms.Objects[i]);
    if APlgHolder.MForm = 0 then    // 非模式窗体释放
    begin
      ClosePlgForm := GetProcAddress(APlgHolder.DLLHandle,'ClosePlgForm');
      if assigned(ClosePlgForm) then
      begin
        if assigned(APlgHolder.FPForm) then
        begin
          ClosePlgForm(APlgHolder.FPForm);
          ClosePlgForm := nil;
        end;
      end;
    end;
    FreeLibrary(APlgHolder.DLLHandle);
  end;
end;

{ THolder }

procedure TPlgHolder.ClickHandler(Sender: TObject);
var
  ShowPlgForm :TShowPlgForm;
begin
  ShowPlgForm :=  GetProcAddress(FDllHandle, 'ShowPlgForm');
  if assigned(FPForm) then
    showmessage('ss');
  FPForm := ShowPlgForm(HostHandle,FMForm,FOwner);
   if assigned(FPForm) then
    showmessage(IntToStr(Integer(FPForm)));

end;

end. 

//主窗口获取插件
procedure TfrmMain.Button2Click(Sender: TObject);
begin
  Mplg.GetPlgLists;

end;

procedure TfrmMain.FormShow(Sender: TObject);
begin
  Mplg := TMplg.Create;
  MPlg.menu := mmMain;
  MPlg.MplgHostHandle :=   Application.MainForm.Handle;
  MPlg.MplgFormOwner := tabsheet4;
end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
     MPlg.Destory;
end;

library plgAdd;

uses
  SysUtils,
  Classes,forms,Controls,
  untPlgView in 'untPlgView.pas' {frmPlgView};

{$R *.res}

type
  PDescPlg = ^TDescPlg;
  TDescPlg = record
    MName:pchar;      //菜单名
    PMItemName:pchar;      //父菜单名
    MForm:integer; //模式窗体?
  end;

var
  Desc:TDescPlg;
 
function ShowPlgForm(AHandle:THandle;mForm:integer;AOwner:TWinControl):Pointer;stdcall;
var
  clientForm:TfrmPlgView;
begin
  Application.Handle := AHandle;
  clientForm := TfrmPlgView.create(Application);
  case mForm of
    1:begin              //模式窗体
        try
          clientForm.ShowModal;
        finally
          freeandnil(clientForm);
        end;
    end;
    0:begin            //非模式窗体
      clientForm.Parent := AOwner;
      clientForm.Align := alClient;
      clientForm.BorderStyle := bsNone;
      clientForm.show;
    end;
  end;
  Result := Pointer(clientForm);
end;

procedure ClosePlgForm(AForm:Pointer);stdcall;
begin
  if assigned(AForm) then TfrmPlgView(AForm).close;
end;

function PlgDesc:Pointer;stdcall;
begin
   desc.MName := '增加结点';
   desc.PMItemName := PChar('Plugin');
   desc.MForm := 1;
   Result := @desc;
end;

exports
   ShowPlgForm,ClosePlgForm,PlgDesc;
begin
end.

library plgView;

uses
  SysUtils,
  Classes,forms,Controls,
  untPlgView in 'untPlgView.pas' {frmPlgView};

{$R *.res}

type
  PDescPlg = ^TDescPlg;
  TDescPlg = record
    MName:pchar;      //菜单名
    PMItemName:pchar;      //父菜单名
    MForm:integer; //模式窗体?
  end;

var
  Desc:TDescPlg;
 
function ShowPlgForm(AHandle:THandle;mForm:integer;AOwner:TWinControl):Pointer;stdcall;
var
  clientForm:TfrmPlgView;
begin
  Application.Handle := AHandle;
  clientForm := TfrmPlgView.create(Application);
  case mForm of
    1:begin
        try
          clientForm.ShowModal;
        finally
          freeandnil(clientForm);
        end;
    end;
    0:begin
      clientForm.Parent := AOwner;
      clientForm.Align := alClient;
      clientForm.BorderStyle := bsNone;
      clientForm.show;
    end;
  end;
  Result := Pointer(clientForm);
end;

procedure ClosePlgForm(AForm:Pointer);stdcall;
begin
  //Desc := nil;
  if assigned(AForm) then TfrmPlgView(AForm).close;
end;

function PlgDesc:Pointer;stdcall;
begin
   desc.MName := '查看结点';
   desc.PMItemName := PChar('Plugin');
   desc.MForm := 0;
   Result := @desc;
end;

exports
   ShowPlgForm,ClosePlgForm,PlgDesc;
begin
end.

posted @ 2008-03-30 08:57  delphi中间件  阅读(545)  评论(0编辑  收藏  举报