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 := 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,一个最简单的插件的更多相关文章
- WordPress插件制作教程(二): 编写一个简单的插件
上一篇说到了如何创建一个插件,我想大家看了之后一定会有所收获,这一篇简单给大家写一个插件样例,让大家有一个基本的印象.这个插件的样例就是当你激活这个插件后会在你的每篇文章中插入一段自己定义好的内容,比 ...
- JQuery自定义插件详解之Banner图滚动插件
前 言 JRedu JQuery是什么相信已经不需要详细介绍了.作为时下最火的JS库之一,JQuery将其"Write Less,Do More!"的口号发挥的极致.而帮助J ...
- Android 插件化开发(四):插件化实现方案
在经过上面铺垫后,我们可以尝试整体实现一下插件化了.这里我们先介绍一下最简单的实现插件化的方案. 一.最简单的插件化实现方案 最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下: 1). 合 ...
- 【ASP.NET 插件】zyUpload的HTML5上传插件
个人能力有限,只能网上找图片批量上传插件,看到一个还不错的插件zyUpload ,可以用来上传文件,但没有.NET 版本,特修改了下用以批量上传图片,效果图如下: update:2016年3月8日 有 ...
- 原生 JS实现一个简单分页插件
最近做的一个 PC端的需求,这个需求中有一个小点,页面底部有一块列表区域,这个列表的数据量比较大,需要进行分页控制,切换页码的时候,发送一个 ajax请求,在页面无刷新的情况下,实现列表数据的刷新,所 ...
- 007.Delphi插件之QPlugins,插件的卸载和重新加载
效果图如下,可以反复卸载和重新加载.QPlugins这个插件,还没弄明白,摸索着跟着DEMO写 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows ...
- OBS插件学习入门:一个非常简单的、调节音量的filter
一个非常简单的.调节音量的filter,非线性调节: #include <obs-module.h> #include <math.h> struct volume_data ...
- 对Raphael画图标的一个jquery简单封装
公司要做一个项目的demo,要求地图上可以插红旗,所以就用到了Raphael. 因为是个demo,所以地图就用了一张图片,效果如下: 所以为了更好的封装一下这个功能,就写了一个简单的插件:jquery ...
- [原]发布一个jQuery提示框插件,Github开源附主站,jquery.tooltips.js
一个简单精致的jQuery带箭头提示框插件 插件写好快一年了,和一个 弹出框插件(点击查看) 一起写的,一直没有整理出来,昨天得功夫整理并放到了github上,源码和网站均可在线看或下载. CSS中的 ...
随机推荐
- [蓝桥杯2015初赛]生命之树(树状dp)
在X森林里,上帝创建了生命之树.他给每棵树的每个节点(叶子也称为一个节点)上,都标了一个整数,代表这个点的和谐值.上帝要在这棵树内选出一个非空节点集S,使得对于S中的任意两个点a,b,都存在一个点列 ...
- 凤凰系统(Phoenix OS)PC版安装,电脑上体验功能丰富的安卓系统
PC版(X86版)ISO镜像下载地址:http://www.phoenixos.com/download_x86 下载完成后,可按照官方给出的安装教程进行安装. 凤凰系统帮助中心:http://www ...
- 学习笔记(4)- DQN
宋皓宇 张伟男刘挺. (2018). 基于DQN的开放域多轮对话策略学习. 中文信息学报, 32(7), 99. http://jcip.cipsc.org.cn/CN/abstract/articl ...
- (未解决)flume监控目录,抓取文件内容推送给kafka,报错
flume监控目录,抓取文件内容推送给kafka,报错: /export/datas/destFile/220104_YT1013_8c5f13f33c299316c6720cc51f94f7a0_2 ...
- 【PAT甲级】1037 Magic Coupon (25 分)
题意: 输入一个正整数N(<=1e5),接下来输入N个整数.再输入一个正整数M(<=1e5),接下来输入M个整数.每次可以从两组数中各取一个,求最大的两个数的乘积的和. AAAAAccep ...
- Python 基础之linux基础相关
一: python3.6.x在Ubuntu16.04下安装过程 #(1)保证网络正常连接 sudo add-apt-repository ppa:jonathonf/python-3.6 (如果超时 ...
- 题解 CF165D 【Beard Graph】
思路:将黑边标记为1,白边标记为100000,树链剖分 如果查询时ans超过100000,那就有白边,输出-1,不然直接输出ans #include<bits/stdc++.h> #def ...
- CF 1278C Berry Jam 题解
Forewords 说实话我是被图吸引进来的23333,图画的真的挺好看. 题意 你从一个梯子下到地下室,梯子左右两边各有 \(n\) 瓶果酱排成一排,果酱口味为草莓味或蓝莓味,你每次只能吃你左边或右 ...
- HTML相关知识点
标签: 块元素:可以设置宽高,div, 行内元素:不可以设置宽高,span,image, display:inline;//转换成行内元素 display:block;//转换成块元素 display ...
- 「CF650E」Clockwork Bomb
传送门 Luogu 解题思路 显然对于两棵树共有的边,我们不会动它. 考虑第二颗树中有和第一棵树不同的边怎么处理. 我们设 \(fa_1[u],fa_2[u]\) 分别代表 \(u\) 在两棵树中的父 ...