热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

001.Delphi插件之QPlugins,一个最简单的插件

安装QPlugins里面的Demo,复制粘贴着写了一个最简单的插件,看看好不好用EXE代码如下:unitMain_Frm;interfaceusesWinapi.Windows,W

安装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)哦,谢谢。

001.Delphi插件之QPlugins,一个最简单的插件


推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
author-avatar
丰田高耗能妨功害能侠盗飞车_948
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有