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.
  • 相关阅读:
    线段树专辑—— pku 1436 Horizontally Visible Segments
    线段树专辑——pku 3667 Hotel
    线段树专辑——hdu 1540 Tunnel Warfare
    线段树专辑—— hdu 1828 Picture
    线段树专辑—— hdu 1542 Atlantis
    线段树专辑 —— pku 2482 Stars in Your Window
    线段树专辑 —— pku 3225 Help with Intervals
    线段树专辑—— hdu 1255 覆盖的面积
    线段树专辑—— hdu 3016 Man Down
    Ajax跨域访问
  • 原文地址:https://www.cnblogs.com/tianpan2019/p/11494781.html
Copyright © 2011-2022 走看看