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中的 ...
随机推荐
- java8函数式编程实例
什么是函数式编程 函数式编程是java8的一大特色,也就是将函数作为一个参数传递给指定方法.别人传的要么是基本数据类型,要么就是地址引用 ,我们要穿一个“动作”. Stream 说到函数式编程,就不得 ...
- js 模拟鼠标拖动
window.addEventListener('message', function (event) { if (event.source != window) return; if (event. ...
- python 基础之字符串方法
字符串 print('chenxi'*8) 测试 D:\python\python.exe D:/untitled/dir/for.py chenxichenxichenxichenxichenxic ...
- JavaWeb开发记录全过程--(1)环境配置
一. 开发工具:idea 理由:根据idea 如何连接服务器,可以直接在idea上连接服务器 安装:根据IntelliJ IDEA 下载安装(含注册码),进行非常规手段使用idea 二.分析问题: # ...
- 【PAT甲级】1034 Head of a Gang (30 分)
题意: 输入两个正整数N和K(<=1000),接下来输入N行数据,每行包括两个人由三个大写字母组成的ID,以及两人通话的时间.输出团伙的个数(相互间通过电话的人数>=3),以及按照字典序输 ...
- C++11 — lambda表达式(匿名函数)
C++11中lambda表达式的基本语法格式为: [capture](parameters) -> return_type { /* ... */ } 其中 [] 内为外部变量的传递方式: [] ...
- zookeeper和eureka的区别在哪?
zookeeper和eureka的区别在哪?传统的关系型数据库是ACID(原子性,一致性,独立性,持久性), nosql数据库是CAP(强一致性,可用性,分区容错性),分布式系统只能3进2,三个选两个 ...
- 设计模式课程 设计模式精讲 12-2 适配器模式coding
1 重要 1.1 类适配器和对象适配器最大的区别 2 代码演练 2.1 代码演练1(类适配器模式) 2.2 代码演练2(对象适配模式) 2.3 代码演练3(具体应用场景) 1 重要 1.1 类适配器和 ...
- Java生鲜电商平台-小程序或者APP拼团功能设计与架构实战
Java生鲜电商平台-小程序或者APP拼团功能设计与架构实战 说明:Java生鲜电商平台拼团是拉新引流的利器,将拼团运用到极致的就是拼多多,前期通过选取性价比高.实用性强的商品进行拼团,在社交圈(主要 ...
- Docker如何使用nginx搭建tomcat集群
首先创建tomcat的文件夹 , 为了方便docker的配置 我这里直接在根目录中创建 第一步:创建文件夹:发布文件夹 mkdir -p /docker/tomcat/webapp8081 mkdir ...