不知道为什么,这个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.