005.Delphi插件之QPlugins,IQNotify通知

时间:2019-09-09
本文章向大家介绍005.Delphi插件之QPlugins,IQNotify通知,主要包括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.

原文地址:https://www.cnblogs.com/tianpan2019/p/11494781.html