• 插件框架


    {*******************************************************}
    {                                                       }
    {       插件管理                                        }
    {                                                       }
    {       版权所有 (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.

  • 相关阅读:
    android从资源文件中读取文件流显示
    Android利用Bundle实现Activity间消息的传递
    MyEclipse 9本地安装插件的方法
    XXE漏洞利用详解
    批处理编写
    初见提权
    个人对ip的理解
    业务逻辑漏洞利用
    NTFS安全权限
    Windows系统管理
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/2940904.html
Copyright © 2020-2023  润新知