安装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 := to PageControl1.PageCount - 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 > then
begin
// 当前页面
AService := IQFormService(PageControl1.ActivePage.Tag);
// 关闭并移除到服务关联事件的监听
AService.Close;
AService.UnhookEvents;
// 释放
FreeObject(PageControl1.ActivePage);
if PageControl1.PageCount > then
PageControl1.ActivePageIndex := ;
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 := to PageControl1.PageCount - 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());
FillChar(AEvents, SizeOf(AEvents), );
// 窗口释放事件
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 := to AParent.Count - do
begin
if Supports(AParent[I], IQFormService, AFormService) then
begin
if not AFormService.IsMultiInstance then
begin
// 嵌入窗体
DockPage(AFormService);
end;
end;
end;
// 激活窗口
if PageControl1.PageCount > then
begin
PageControl1.ActivePageIndex := ;
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,一个最简单的插件的更多相关文章

  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. element-ui的el-table的表头与列不对齐

    最好加到全局样式中: body .el-table th.gutter{ display: table-cell!important; }

  2. Chrome 浏览器新功能:共享剪贴板

    导读 Chrome 79 在桌面版和 Android 版浏览器中添加了一项新的功能,名为“共享剪贴板”(shared clipboard). 简单来说,就是可以实现在电脑端复制,手机端粘贴.有了这项功 ...

  3. Java中正确使用hashCode和equals方法

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...

  4. kubernetes 1.5.2 部署kube-dns 踩过的坑

    看了kubernetes 权威指南 遇见了dns这一块.于是便按照书上的方式部署了一下. 书上使用的方式是:kube2sky+etcd+skydns的方式.按照书上的yaml写了一遍,发现无论如何都无 ...

  5. Java知识总结:Java反射机制(用实例理解)

    概念理解: 反射是指一类应用,它们能够自描述和自控制.也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能 ...

  6. Keras入门——(2)卷积神经网络CNN

    前期准备工作参考:https://www.cnblogs.com/ratels/p/11144881.html 基于CNN算法利用Keras框架编写代码实现对Minst数据分类识别: from ker ...

  7. JS 一键复制插件应用 和 原生实现

    一.目前来说复制功能 clipboard.js基本可以兼容所有浏览器,可以任意复制文本,官方地址 https://clipboardjs.com/ 1.进入官方网站下载 然后引入 <script ...

  8. laravel-url去掉public

    把laravel/server.php改名为index.php 并且将public目录下的.htaccess拷贝到Larvael根目下 Ok了 but why? 自己查去吧

  9. mysql#自定义序列

    原文 mysql主键不用自增数字的时候,可以参考如下方式,我抄来的. -- 创建公共的序列表 DROP TABLE IF EXISTS t_common_sequence; CREATE TABLE ...

  10. ng之邮箱校验

    $scope.sendMail = function () { // console.log($scope.inputValue.inputEmail); //校验邮箱格式是否正确 if (!$sco ...