安装QPlugins里面的Demo,复制粘贴着写了一个最简单的插件,看看好不好用

EXE代码如下:

  1. unit Main_Frm;
  2.  
  3. interface
  4.  
  5. uses
  6. Winapi.Windows,
  7. Winapi.Messages,
  8. System.SysUtils,
  9. System.Variants,
  10. System.Classes,
  11. Vcl.Graphics,
  12. Vcl.Controls,
  13. Vcl.Forms,
  14. qplugins_vcl_formsvc,
  15. qplugins_loader_lib,
  16. qstring,
  17. qplugins_base,
  18. QPlugins,
  19. qplugins_params,
  20. qplugins_vcl_messages,
  21. qplugins_formsvc,
  22. Vcl.Dialogs,
  23. Vcl.StdCtrls,
  24. Vcl.ComCtrls;
  25.  
  26. type
  27. TMain_Form = class(TForm)
  28. GroupBox1: TGroupBox;
  29. PageControl1: TPageControl;
  30. Button1: TButton;
  31. procedure Button1Click(Sender: TObject);
  32. procedure FormCreate(Sender: TObject);
  33. procedure FormDestroy(Sender: TObject);
  34. private
  35. {Private declarations}
  36. procedure DoPageDoubleClick(ASender: TObject);
  37. procedure DockPage(AFormService: IQFormService; AHoldNeeded: Boolean = False);
  38. procedure DoDockChildFree(AForm: IQFormService);
  39. public
  40. {Public declarations}
  41. end;
  42.  
  43. var
  44. Main_Form: TMain_Form;
  45.  
  46. implementation
  47.  
  48. {$R *.dfm}
  49.  
  50. type
  51. // Page控件页面双击事件
  52. THackedPageControl = class(TPageControl)
  53. public
  54. property OnDblClick;
  55. end;
  56.  
  57. // 程序关闭时,释放所有标签
  58. procedure TMain_Form.DoDockChildFree(AForm: IQFormService);
  59. var
  60. I: Integer;
  61. begin
  62. for I := to PageControl1.PageCount - do
  63. begin
  64. // 如果标签tag储存的是一个对话框
  65. if PageControl1.Pages[I].Tag = IntPtr(AForm) then
  66. begin
  67. // 释放
  68. AForm.UnhookEvents;
  69. FreeObject(PageControl1.Pages[I]);
  70. Break;
  71. end;
  72. end;
  73. end;
  74.  
  75. // 双击Page标签事件
  76. procedure TMain_Form.DoPageDoubleClick(ASender: TObject);
  77. var
  78. AService: IQFormService;
  79. begin
  80. // 双击关闭当前窗体
  81. if PageControl1.PageCount > then
  82. begin
  83. // 当前页面
  84. AService := IQFormService(PageControl1.ActivePage.Tag);
  85. // 关闭并移除到服务关联事件的监听
  86. AService.Close;
  87. AService.UnhookEvents;
  88. // 释放
  89. FreeObject(PageControl1.ActivePage);
  90. if PageControl1.PageCount > then
  91. PageControl1.ActivePageIndex := ;
  92. end;
  93. end;
  94.  
  95. // 创建
  96. procedure TMain_Form.FormCreate(Sender: TObject);
  97. var
  98. APath: string;
  99. begin
  100. // 查看内存泄露
  101. // ReportMemoryLeaksOnShutdown := True;
  102. // 路径
  103. APath := ExtractFilePath(Application.ExeName);
  104. // 加载DLL
  105. PluginsManager.Loaders.Add(TQDLLLoader.Create(APath, '.dll'));
  106. // 加载BPL
  107. PluginsManager.Loaders.Add(TQBPLLoader.Create(APath, '.bpl'));
  108. // 启动所有的加载器加载支持的插件
  109. PluginsManager.Start;
  110. PageControl1.ControlStyle := PageControl1.ControlStyle + [csClickEvents, csDoubleClicks];
  111. // 替换Page控件页面双击事件,用于双击页签关闭某一页
  112. THackedPageControl(PageControl1).OnDblClick := DoPageDoubleClick;
  113. end;
  114.  
  115. // 销毁
  116. procedure TMain_Form.FormDestroy(Sender: TObject);
  117. var
  118. I: Integer;
  119. AFormService: IQFormService;
  120. begin
  121. // 循环释放窗口
  122. for I := to PageControl1.PageCount - do
  123. begin
  124. // IQFormService为窗体服务的接口
  125. AFormService := IQFormService(PageControl1.Pages[I].Tag);
  126. // 移除到服务关联事件的监听
  127. AFormService.UnhookEvents;
  128. end;
  129. end;
  130.  
  131. // 嵌入窗体
  132. procedure TMain_Form.DockPage(AFormService: IQFormService; AHoldNeeded: Boolean);
  133. var
  134. APage: TTabSheet;
  135. AEvents: TQFormEvents;
  136. begin
  137. // 创建页签
  138. APage := TTabSheet.Create(PageControl1);
  139. APage.PageControl := PageControl1;
  140. // 设置页签名
  141. APage.Caption := (AFormService as IQService).Name;
  142. // 储存AFormService
  143. APage.Tag := IntPtr(AFormService);
  144. // 嵌入窗体到父窗口的特定的位置
  145. AFormService.DockTo(APage.Handle, TFormAlign());
  146. FillChar(AEvents, SizeOf(AEvents), );
  147. // 窗口释放事件
  148. AEvents.OnFree := DoDockChildFree;
  149. // 挂接服务关联的窗口事件
  150. AFormService.HookEvents(AEvents);
  151. // 创建 TQInterfaceHolder
  152. if AHoldNeeded then
  153. begin
  154. HoldByComponent(APage, AFormService);
  155. end;
  156. end;
  157.  
  158. // 创建实例
  159. procedure TMain_Form.Button1Click(Sender: TObject);
  160. var
  161. I: Integer;
  162. AParent: IQServices;
  163. AFormService: IQFormService;
  164. begin
  165. // Supports函数返回对象是否支持指定的接口
  166. if Supports(PluginsManager.ByPath('/Services/Docks/Forms'), IQServices, AParent) then
  167. begin
  168. for I := to AParent.Count - do
  169. begin
  170. if Supports(AParent[I], IQFormService, AFormService) then
  171. begin
  172. if not AFormService.IsMultiInstance then
  173. begin
  174. // 嵌入窗体
  175. DockPage(AFormService);
  176. end;
  177. end;
  178. end;
  179. // 激活窗口
  180. if PageControl1.PageCount > then
  181. begin
  182. PageControl1.ActivePageIndex := ;
  183. end;
  184. end;
  185. // 创建的是单实例的,所以不应重复创建
  186. Button1.Enabled := False;
  187. end;
  188.  
  189. end.

DLL代码如下:

  1. unit Frm_Dll;
  2.  
  3. interface
  4.  
  5. uses
  6. Winapi.Windows,
  7. Winapi.Messages,
  8. System.SysUtils,
  9. System.Variants,
  10. System.Classes,
  11. Vcl.Graphics,
  12. Vcl.Controls,
  13. Vcl.Forms,
  14. Vcl.Dialogs,
  15. Vcl.StdCtrls;
  16.  
  17. type
  18. TForm_Dll = class(TForm)
  19. Button1: TButton;
  20. procedure Button1Click(Sender: TObject);
  21. private
  22. { Private declarations }
  23. public
  24. { Public declarations }
  25. end;
  26.  
  27. var
  28. Form_Dll: TForm_Dll;
  29.  
  30. implementation
  31.  
  32. {$R *.dfm}
  33.  
  34. uses
  35. qstring,
  36. QPlugins,
  37. qplugins_vcl_formsvc;
  38.  
  39. // 释放自己
  40. procedure TForm_Dll.Button1Click(Sender: TObject);
  41. begin
  42. FreeObject(Self);
  43. end;
  44.  
  45. initialization
  46.  
  47. // 注册一个单实例服务
  48. RegisterFormService('/Services/Docks/Forms', 'DLL_Static', TForm_Dll, False);
  49.  
  50. finalization
  51.  
  52. // 取消一组服务的注册
  53. UnregisterServices('/Services/Docks/Forms', ['DLL_Static']);
  54.  
  55. end.

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

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

001.Delphi插件之QPlugins,一个最简单的插件的更多相关文章

  1. WordPress插件制作教程(二): 编写一个简单的插件

    上一篇说到了如何创建一个插件,我想大家看了之后一定会有所收获,这一篇简单给大家写一个插件样例,让大家有一个基本的印象.这个插件的样例就是当你激活这个插件后会在你的每篇文章中插入一段自己定义好的内容,比 ...

  2. JQuery自定义插件详解之Banner图滚动插件

      前  言 JRedu JQuery是什么相信已经不需要详细介绍了.作为时下最火的JS库之一,JQuery将其"Write Less,Do More!"的口号发挥的极致.而帮助J ...

  3. Android 插件化开发(四):插件化实现方案

    在经过上面铺垫后,我们可以尝试整体实现一下插件化了.这里我们先介绍一下最简单的实现插件化的方案. 一.最简单的插件化实现方案 最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下: 1). 合 ...

  4. 【ASP.NET 插件】zyUpload的HTML5上传插件

    个人能力有限,只能网上找图片批量上传插件,看到一个还不错的插件zyUpload ,可以用来上传文件,但没有.NET 版本,特修改了下用以批量上传图片,效果图如下: update:2016年3月8日 有 ...

  5. 原生 JS实现一个简单分页插件

    最近做的一个 PC端的需求,这个需求中有一个小点,页面底部有一块列表区域,这个列表的数据量比较大,需要进行分页控制,切换页码的时候,发送一个 ajax请求,在页面无刷新的情况下,实现列表数据的刷新,所 ...

  6. 007.Delphi插件之QPlugins,插件的卸载和重新加载

    效果图如下,可以反复卸载和重新加载.QPlugins这个插件,还没弄明白,摸索着跟着DEMO写 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows ...

  7. OBS插件学习入门:一个非常简单的、调节音量的filter

    一个非常简单的.调节音量的filter,非线性调节: #include <obs-module.h> #include <math.h> struct volume_data ...

  8. 对Raphael画图标的一个jquery简单封装

    公司要做一个项目的demo,要求地图上可以插红旗,所以就用到了Raphael. 因为是个demo,所以地图就用了一张图片,效果如下: 所以为了更好的封装一下这个功能,就写了一个简单的插件:jquery ...

  9. [原]发布一个jQuery提示框插件,Github开源附主站,jquery.tooltips.js

    一个简单精致的jQuery带箭头提示框插件 插件写好快一年了,和一个 弹出框插件(点击查看) 一起写的,一直没有整理出来,昨天得功夫整理并放到了github上,源码和网站均可在线看或下载. CSS中的 ...

随机推荐

  1. [转]Mysql连表之多对多

    转自 回到顶部 连表多对多 可以理解成一夫多妻和一妻多夫. 男人表: nid name 1 xxx 2 yyy 3 zzz 女人表: nid name 1 aaa 2 bbb 3 ccc 要让两个表建 ...

  2. FormsAuthentication.HashPasswordForStoringInConfigFile方法再.net core中的替代代码

    FormsAuthentication.HashPasswordForStoringInConfigFile()这个加密方法再.net core中不存在了,可以用下面的方式达到一样的加密效果 usin ...

  3. CF 1073 E. Segment Sum

    https://codeforces.com/problemset/problem/1073/E 题意:[l,r]中,出现0—9数字的种类数不超过k的数的和 dp[i][j][0/1] 表示 dfs到 ...

  4. Linux centos7 VMware Apache访问日志不记录静态文件、访问日志切割、静态元素过期时间

    一.Apache访问日志不记录静态文件 网站大多元素为静态文件,如图片.css.js等,这些元素可以不用记录 vim /usr/local/apache2.4/conf/extra/httpd-vho ...

  5. SystemProperities

    SystemProperties与Settings.System 1 使用 SystemProperties.get 如果属性名称以“ro.”开头,那么这个属性被视为只读属性.一旦设置,属性值不能改变 ...

  6. nodejs的C++扩展中实现异步回调

    在nodejs的官方网站中有关于C++扩展的详细说明,其中包含了从"hello world"到对象封装的一系列示例.其中的“callback”节是关于回调函数的,美中不足的是,这个 ...

  7. 重识线段树——Let's start with the start.

    声明 本文为 Clouder 原创,在未经许可情况下请不要随意转载.原文链接 前言 一般地,这篇文章是给学习过线段树却仍不透彻者撰写的,因此在某些简单的操作上可能会一笔带过. 当然了,入门线段树后也可 ...

  8. SpringMVC 自定义类型转换

    类型转换可以将请求参数转换为指定的类型.指定的格式(数据的格式化),然后传给业务方法的参数. Spring MVC内置了常用的类型转换器.如果内置的类型转换器满足不了需求,可以使用自定义的类型转换. ...

  9. jeDate日期控件精确到秒

    案例下载 链接: https://pan.baidu.com/s/1m7eEW6K6Bt1t-0OjVY_Wxw 密码: xmei <script type="text/javascr ...

  10. OPCDA通信--工作在透明模式下的CISCO ASA 5506-X防火墙配置

    尊重原创,转发请声名 inside OPCSERVER 一台 outside OPCCLIENT 一台 route模式 配置没成功,放弃,采用透明模式 !----进入全局配置-- configure ...