005.Delphi插件之QPlugins,IQNotify通知
演示的界面如下,拖动滚动条,百分比圆和进度条也是会跟着动的
主程序的代码如下
unit Frm_Main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, qstring, QPlugins, qplugins_base, qplugins_loader_lib, qplugins_params, qplugins_vcl_formsvc, qplugins_vcl_messages, qplugins_formsvc, Vcl.StdCtrls; type TForm_Main = class(TForm) TrackBar1: TTrackBar; Label1: TLabel; Button1: TButton; Button2: TButton; Button3: TButton; procedure TrackBar1Change(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Button3Click(Sender: TObject); private {Private declarations} FChangeNotifyId: Integer; public {Public declarations} end; var Form_Main: TForm_Main; FInterfaceList: TInterfaceList; // 保存窗体插件实例指针 implementation uses Frm_Show; {$R *.dfm} // 按钮_新建接收窗口 procedure TForm_Main.Button1Click(Sender: TObject); begin // 显示窗口 TForm_Show.Create(Application); end; // 按钮_新建DLL插件窗口 procedure TForm_Main.Button2Click(Sender: TObject); var // 窗体服务的接口 AFormService: IQFormService; begin // 加载DLL_MutiInstance的DLL插件窗口 if Supports(PluginsManager.ByPath('/Services/Docks/Forms/DLL_MutiInstance'), IQFormService, AFormService) then begin // 把这个服务窗口添加到接口列表中 FInterfaceList.Add(AFormService); // ShowMessage(ServiceSource(AFormService as IQService)); // 显示 AFormService.Show; end; end; // 按钮_显示参数 procedure TForm_Main.Button3Click(Sender: TObject); var AParams: TQParams; begin // 创建参数列表 AParams := TQParams.Create; // 向参数列表插入一波参数 AParams.Add('Id', 100); AParams.Add('Name', '高原'); AParams.Add('IsFemale', false); AParams.Add('Scale', 75.6); AParams.Add('Desc', '这是测试'#13#10'高原有很多种'); AParams.Add('Array', NewParams([100, 'QDAC', 3.45])); // 输出 ShowMessage((AParams as IQParams).AsString.Value); end; procedure TForm_Main.FormClose(Sender: TObject; var Action: TCloseAction); begin // 释放 FInterfaceList.Free; end; // 创建 procedure TForm_Main.FormCreate(Sender: TObject); var APath: string; begin ReportMemoryLeaksOnShutdown := True; // 取自己路径 APath := ExtractFilePath(Application.ExeName); // 加载同目录的DLL PluginsManager.Loaders.Add(TQDLLLoader.Create(APath, '.dll')); // 启动服务 PluginsManager.Start; // 找到名字为'Tracker.Changed'的通知 FChangeNotifyId := (PluginsManager as IQNotifyManager).IdByName('Tracker.Changed'); // 创建接口列表 FInterfaceList := TInterfaceList.Create; end; // 进度条被拖动事件 procedure TForm_Main.TrackBar1Change(Sender: TObject); begin // 触发调用DLL中的插件窗口 // IQNotifyManager.Send 投递一个通知并等待它被处理完成 (PluginsManager as IQNotifyManager).Send(FChangeNotifyId, NewParams([TrackBar1.Position])); end; end.
unit Frm_Show; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.StdCtrls, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Samples.Gauges, QPlugins, qplugins_base, qplugins_params; type // class需要继承IQNotify TForm_Show = class(TForm, IQNotify) Gauge1: TGauge; CheckBox1: TCheckBox; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure CheckBox1Click(Sender: TObject); private {Private declarations} FNotifyId: Integer; // 在通知发生时,通知响应函数接口。IQNotify接口中定义的函数,子类来实现这个函数 procedure Notify(const AId: Cardinal; AParams: IQParams; var AFireNext: Boolean); stdcall; public {Public declarations} end; {var Form_Show: TForm_Show;} implementation {$R *.dfm} {TForm2} procedure TForm_Show.CheckBox1Click(Sender: TObject); var AMgr: IQNotifyManager; begin AMgr := PluginsManager as IQNotifyManager; // 注册通知,事件的名称不需要特意注册,IdByName在名称不存在时,会自动注册并生成一个新的ID返回 // 多个不同的 Id 就多次订阅即可 FNotifyId := AMgr.IdByName('Tracker.Changed'); // if CheckBox1.Checked then begin // 订阅一个通知 AMgr.Subscribe(FNotifyId, Self) end else begin // 取消订阅通知 AMgr.unSubscribe(FNotifyId, Self); end; end; procedure TForm_Show.FormClose(Sender: TObject; var Action: TCloseAction); var AMgr: IQNotifyManager; begin AMgr := PluginsManager as IQNotifyManager; // 注册通知,事件的名称不需要特意注册,IdByName在名称不存在时,会自动注册并生成一个新的ID返回 // 多个不同的 Id 就多次订阅即可 FNotifyId := AMgr.IdByName('Tracker.Changed'); // 取消订阅通知 AMgr.unSubscribe(FNotifyId, Self); Action := caFree; end; procedure TForm_Show.FormCreate(Sender: TObject); var AMgr: IQNotifyManager; begin // IQNotifyManager通知管理器用于内部维护多个通知和订阅者队列 AMgr := PluginsManager as IQNotifyManager; // 注册通知,事件的名称不需要特意注册,IdByName在名称不存在时,会自动注册并生成一个新的ID返回 // 多个不同的 Id 就多次订阅即可 // IdByName返回指定名称的通知ID FNotifyId := AMgr.IdByName('Tracker.Changed'); // 订阅一个通知 AMgr.Subscribe(FNotifyId, Self); end; // 在通知发生时,通知响应函数接口。IQNotify接口中定义的函数,子类来实现这个函数 procedure TForm_Show.Notify(const AId: Cardinal; AParams: IQParams; var AFireNext: Boolean); begin // 多个通知关联到同一个对象时,通过AId进行进行区分 if AId = FNotifyId then begin // 接到通知,显示窗口 if not Visible then begin Show; end; // 显示图像百分比 Gauge1.Progress := AParams[0].AsInteger; end; 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, Vcl.ComCtrls, QString, QPlugins, qplugins_base, qplugins_vcl_formsvc, qplugins_params; type // class需要继承IQNotify TForm_Dll = class(TForm, IQNotify) CheckBox1: TCheckBox; ProgressBar1: TProgressBar; Label1: TLabel; Label2: TLabel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure CheckBox1Click(Sender: TObject); private {Private declarations} FNotifyId: Integer; // 在通知发生时,通知响应函数接口。IQNotify接口中定义的函数,子类来实现这个函数 procedure Notify(const AId: Cardinal; AParams: IQParams; var AFireNext: Boolean); stdcall; public {Public declarations} end; var Form_Dll: TForm_Dll; implementation {$R *.dfm} procedure TForm_Dll.CheckBox1Click(Sender: TObject); var AMgr: IQNotifyManager; begin AMgr := PluginsManager as IQNotifyManager; // 注册通知,事件的名称不需要特意注册,IdByName在名称不存在时,会自动注册并生成一个新的ID返回 // 多个不同的 Id 就多次订阅即可 FNotifyId := AMgr.IdByName('Tracker.Changed'); if CheckBox1.Checked then begin // 订阅一个通知 AMgr.Subscribe(FNotifyId, Self) end else begin // 取消订阅通知 AMgr.unSubscribe(FNotifyId, Self); end; end; // 创建 procedure TForm_Dll.FormCreate(Sender: TObject); var AMgr: IQNotifyManager; begin Label2.Caption := '实例创建时间:' + FormatDateTime('hh:nn:ss', Now); AMgr := PluginsManager as IQNotifyManager; // 注册通知,事件的名称不需要特意注册,IdByName在名称不存在时,会自动注册并生成一个新的ID返回 // 多个不同的 Id 就多次订阅即可 FNotifyId := AMgr.IdByName('Tracker.Changed'); AMgr.Subscribe(FNotifyId, Self); end; // 销毁 procedure TForm_Dll.FormDestroy(Sender: TObject); var AMgr: IQNotifyManager; begin AMgr := PluginsManager as IQNotifyManager; // 注册通知,事件的名称不需要特意注册,IdByName在名称不存在时,会自动注册并生成一个新的ID返回 // 多个不同的 Id 就多次订阅即可 FNotifyId := AMgr.IdByName('Tracker.Changed'); AMgr.unSubscribe(FNotifyId, Self); end; // 通知实现 procedure TForm_Dll.Notify(const AId: Cardinal; AParams: IQParams; var AFireNext: Boolean); begin // 多个通知关联到同一个对象时,通过AId进行进行区分 if AId = FNotifyId then begin // 接到通知,显示窗口 if not Visible then begin Show; end; // 显示图像百分比 ProgressBar1.Position := AParams[0].AsInteger; end; end; initialization // 注册 //RegisterServices('/Services/Docks/Forms', [TQVCLFormService.Create('DLL_Shared', TForm_Dll.Create(nil), nil)]);
RegisterServices('/Services/Docks/Forms', [TQVCLFormService.Create('DLL_MutiInstance', TForm_Dll)]); finalization // 注销 UnregisterServices('/Services/Docks/Forms', ['DLL_Shared', 'DLL_MutiInstance']); end.