安装QPlugins里面的Demo,复制粘贴着写了一个最简单的插件,看看好不好用
EXE代码如下:
unit Main_Frm; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, qplugins_vcl_formsvc, qplugins_loader_lib, qstring, qplugins_base, QPlugins, qplugins_params, qplugins_vcl_messages, qplugins_formsvc, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls; type TMain_Form = class(TForm) GroupBox1: TGroupBox; PageControl1: TPageControl; Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private {Private declarations} procedure DoPageDoubleClick(ASender: TObject); procedure DockPage(AFormService: IQFormService; AHoldNeeded: Boolean = False); procedure DoDockChildFree(AForm: IQFormService); public {Public declarations} end; var Main_Form: TMain_Form; implementation {$R *.dfm} type // Page控件页面双击事件 THackedPageControl = class(TPageControl) public property OnDblClick; end; // 程序关闭时,释放所有标签 procedure TMain_Form.DoDockChildFree(AForm: IQFormService); var I: Integer; begin for I := 0 to PageControl1.PageCount - 1 do begin // 如果标签tag储存的是一个对话框 if PageControl1.Pages[I].Tag = IntPtr(AForm) then begin // 释放 AForm.UnhookEvents; FreeObject(PageControl1.Pages[I]); Break; end; end; end; // 双击Page标签事件 procedure TMain_Form.DoPageDoubleClick(ASender: TObject); var AService: IQFormService; begin // 双击关闭当前窗体 if PageControl1.PageCount > 0 then begin // 当前页面 AService := IQFormService(PageControl1.ActivePage.Tag); // 关闭并移除到服务关联事件的监听 AService.Close; AService.UnhookEvents; // 释放 FreeObject(PageControl1.ActivePage); if PageControl1.PageCount > 0 then PageControl1.ActivePageIndex := 0; end; end; // 创建 procedure TMain_Form.FormCreate(Sender: TObject); var APath: string; begin // 查看内存泄露 // ReportMemoryLeaksOnShutdown := True; // 路径 APath := ExtractFilePath(Application.ExeName); // 加载DLL PluginsManager.Loaders.Add(TQDLLLoader.Create(APath, ‘.dll‘)); // 加载BPL PluginsManager.Loaders.Add(TQBPLLoader.Create(APath, ‘.bpl‘)); // 启动所有的加载器加载支持的插件 PluginsManager.Start; PageControl1.ControlStyle := PageControl1.ControlStyle + [csClickEvents, csDoubleClicks]; // 替换Page控件页面双击事件,用于双击页签关闭某一页 THackedPageControl(PageControl1).OnDblClick := DoPageDoubleClick; end; // 销毁 procedure TMain_Form.FormDestroy(Sender: TObject); var I: Integer; AFormService: IQFormService; begin // 循环释放窗口 for I := 0 to PageControl1.PageCount - 1 do begin // IQFormService为窗体服务的接口 AFormService := IQFormService(PageControl1.Pages[I].Tag); // 移除到服务关联事件的监听 AFormService.UnhookEvents; end; end; // 嵌入窗体 procedure TMain_Form.DockPage(AFormService: IQFormService; AHoldNeeded: Boolean); var APage: TTabSheet; AEvents: TQFormEvents; begin // 创建页签 APage := TTabSheet.Create(PageControl1); APage.PageControl := PageControl1; // 设置页签名 APage.Caption := (AFormService as IQService).Name; // 储存AFormService APage.Tag := IntPtr(AFormService); // 嵌入窗体到父窗口的特定的位置 AFormService.DockTo(APage.Handle, TFormAlign(1)); FillChar(AEvents, SizeOf(AEvents), 0); // 窗口释放事件 AEvents.OnFree := DoDockChildFree; // 挂接服务关联的窗口事件 AFormService.HookEvents(AEvents); // 创建 TQInterfaceHolder if AHoldNeeded then begin HoldByComponent(APage, AFormService); end; end; // 创建实例 procedure TMain_Form.Button1Click(Sender: TObject); var I: Integer; AParent: IQServices; AFormService: IQFormService; begin // Supports函数返回对象是否支持指定的接口 if Supports(PluginsManager.ByPath(‘/Services/Docks/Forms‘), IQServices, AParent) then begin for I := 0 to AParent.Count - 1 do begin if Supports(AParent[I], IQFormService, AFormService) then begin if not AFormService.IsMultiInstance then begin // 嵌入窗体 DockPage(AFormService); end; end; end; // 激活窗口 if PageControl1.PageCount > 0 then begin PageControl1.ActivePageIndex := 0; end; end; // 创建的是单实例的,所以不应重复创建 Button1.Enabled := False; end; end.
DLL代码如下:
unit Frm_Dll; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm_Dll = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form_Dll: TForm_Dll; implementation {$R *.dfm} uses qstring, QPlugins, qplugins_vcl_formsvc; // 释放自己 procedure TForm_Dll.Button1Click(Sender: TObject); begin FreeObject(Self); end; initialization // 注册一个单实例服务 RegisterFormService(‘/Services/Docks/Forms‘, ‘DLL_Static‘, TForm_Dll, False); finalization // 取消一组服务的注册 UnregisterServices(‘/Services/Docks/Forms‘, [‘DLL_Static‘]); end.
初步感受了一下,插件用着还可以。