zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    搜索
    c++ map与unordered_map区别及使用
    01BFS
    宇智波程序笔记55-Flutter 混合开发】嵌入原生View-iOS
    宇智波程序笔记54-解Bug之路-记一次线上请求偶尔变慢的排查
    宇智波程序笔记53-从红黑树的本质出发,彻底理解红黑树!
    宇智波程序笔记52-最受欢迎的微服务框架概览
    宇智波程序笔记51-JDK 15安装及新特性介绍
    宇智波程序笔记50-解Bug之路-记一次线上请求偶尔变慢的排查
    宇智波程序笔记49-link JDBC Connector:Flink 与数据库集成最佳实践
  • 原文地址:https://www.cnblogs.com/tianpan2019/p/11494781.html
Copyright © 2011-2022 走看看