014.Delphi插件之QPlugins,MDI窗口

不知道为什么,这个DEMO编译出来报错,运行不了,在QDAC群里问了一下也没人响应。

效果如下

 

主程序代码如下

unit Frm_Main;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.Menus,
  QPlugins,
  qplugins_params,
  qplugins_formsvc,
  qplugins_vcl_formsvc,
  qplugins_loader_lib;

{ 注意使用 MDI 子窗体做为插件,宿主和插件都必需同时引用rtl/vcl运行时包 }

type
  TForm_Main = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure File1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    FOpenChildren: array of IQFormService;
    procedure DoFormClosed(AForm: IQFormService; var Action: TCloseAction);
    procedure DoFormFree(AForm: IQFormService);
  public
    { Public declarations }
  end;

var
  Form_Main: TForm_Main;

implementation

{$R *.dfm}

procedure TForm_Main.DoFormClosed(AForm: IQFormService; var Action: TCloseAction);
var
  I: Integer;
begin
  // 方法1:设置Action为caFree,然后由DoFormFree事件来处理清理服务
  // Action := caFree;
  // 方法2:直接释放引用就可以,优点是不用处理 OnFree 事件了
  for I := 0 to High(FOpenChildren) do
  begin
    if FOpenChildren[I] = AForm then
    begin
      Delete(FOpenChildren, I, 1);
      Break;
    end;
  end;
end;

procedure TForm_Main.DoFormFree(AForm: IQFormService);
var
  I: Integer;
begin
  // 直接释放引用就可以
  for I := 0 to High(FOpenChildren) do
  begin
    if FOpenChildren[I] = AForm then
    begin
      Delete(FOpenChildren, I, 1);
      Break;
    end;
  end;
end;

// 菜单_新建
procedure TForm_Main.File1Click(Sender: TObject);
var
  AService: IQFormService;
  // 窗体事件
  AEvents: TQFormEvents;
begin
  if Supports(PluginsManager.ByPath('/Services/Forms/MDI/MDITest'), IQFormService, AService) then
  begin
    // 设置窗体事件
    FillChar(AEvents, SizeOf(AEvents), 0);
    // 替换窗体的关闭和释放事件
    AEvents.OnClose := DoFormClosed;
    AEvents.OnFree := DoFormFree;
    AService.HookEvents(AEvents);
    AService.Show;
    // FOpenChildren数组长度+1,为了添加一个AService
    SetLength(FOpenChildren, Length(FOpenChildren) + 1);
    FOpenChildren[High(FOpenChildren)] := AService;
  end;
end;

procedure TForm_Main.FormClose(Sender: TObject; var Action: TCloseAction);
var
  I: Integer;
  AEvents: TQFormEvents;
begin
  // 在直接关闭前,要先移除事件关联,否则在服务释放时,回调DoFormFree时会出错
  FillChar(AEvents, SizeOf(AEvents), 0);
  // 遍历移除替换的窗体事件
  for I := 0 to High(FOpenChildren) do
  begin
    FOpenChildren[I].HookEvents(AEvents);
  end;
  // 清空
  SetLength(FOpenChildren, 0);
end;

// 创建
procedure TForm_Main.FormCreate(Sender: TObject);
begin
  with PluginsManager do
  begin
    // 加载同目录下dll文件
    Loaders.Add(TQDLLLoader.Create(ExtractFilePath(Application.ExeName), '.dll'));
    // 启动服务
    Start;
  end;
end;

end.

DLL代码如下

unit Frm_Mdi;


interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs;

type
  TForm_Mdi = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form_Mdi: TForm_Mdi;

implementation

uses
  QPlugins,
  qplugins_vcl_formsvc;
{$R *.dfm}

initialization

// 注册一个单实例服务
RegisterFormService('/Services/Forms/MDI', 'MDITest', TForm_Mdi);

finalization

// 注销
UnregisterServices('/Services/Forms/MDI', ['MDITest']);

end.

 

posted @ 2019-09-11 09:55  像一棵海草海草海草  阅读(384)  评论(0编辑  收藏  举报