zoukankan      html  css  js  c++  java
  • 001.Delphi插件之QPlugins,一个最简单的插件

    安装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.

    初步感受了一下,插件用着还可以。

    不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢。

  • 相关阅读:
    各种现代方法和技术在储集层研究中的运用
    “汇报能力”的要求和构建
    个人核心竞争力的构建
    “盐荒”子孙的悲哀
    对数据及数据库的理解
    浅谈大学综合素质培养的重要性
    我看兴趣爱好
    Access数据库连接字符串
    常用css缩略语
    中文与韩、日文混排出现在Gb2312编码的Aspx的处理方法
  • 原文地址:https://www.cnblogs.com/tianpan2019/p/11488940.html
Copyright © 2011-2022 走看看