不知道为什么,这个DEMO编译出来报错,运行不了,在QDAC群里问了一下也没人响应。

效果如下

主程序代码如下

unit Frm_Main;

interface

uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs,
Vcl.Menus,
QPlugins,
qplugins_params,
qplugins_formsvc,
qplugins_vcl_formsvc,
qplugins_loader_lib; { 注意使用 MDI 子窗体做为插件,宿主和插件都必需同时引用rtl/vcl运行时包 } type
TForm_Main = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure File1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
FOpenChildren: array of IQFormService;
procedure DoFormClosed(AForm: IQFormService; var Action: TCloseAction);
procedure DoFormFree(AForm: IQFormService);
public
{ Public declarations }
end; var
Form_Main: TForm_Main; implementation {$R *.dfm} procedure TForm_Main.DoFormClosed(AForm: IQFormService; var Action: TCloseAction);
var
I: Integer;
begin
// 方法1:设置Action为caFree,然后由DoFormFree事件来处理清理服务
// Action := caFree;
// 方法2:直接释放引用就可以,优点是不用处理 OnFree 事件了
for I := to High(FOpenChildren) do
begin
if FOpenChildren[I] = AForm then
begin
Delete(FOpenChildren, I, );
Break;
end;
end;
end; procedure TForm_Main.DoFormFree(AForm: IQFormService);
var
I: Integer;
begin
// 直接释放引用就可以
for I := to High(FOpenChildren) do
begin
if FOpenChildren[I] = AForm then
begin
Delete(FOpenChildren, I, );
Break;
end;
end;
end; // 菜单_新建
procedure TForm_Main.File1Click(Sender: TObject);
var
AService: IQFormService;
// 窗体事件
AEvents: TQFormEvents;
begin
if Supports(PluginsManager.ByPath('/Services/Forms/MDI/MDITest'), IQFormService, AService) then
begin
// 设置窗体事件
FillChar(AEvents, SizeOf(AEvents), );
// 替换窗体的关闭和释放事件
AEvents.OnClose := DoFormClosed;
AEvents.OnFree := DoFormFree;
AService.HookEvents(AEvents);
AService.Show;
// FOpenChildren数组长度+1,为了添加一个AService
SetLength(FOpenChildren, Length(FOpenChildren) + );
FOpenChildren[High(FOpenChildren)] := AService;
end;
end; procedure TForm_Main.FormClose(Sender: TObject; var Action: TCloseAction);
var
I: Integer;
AEvents: TQFormEvents;
begin
// 在直接关闭前,要先移除事件关联,否则在服务释放时,回调DoFormFree时会出错
FillChar(AEvents, SizeOf(AEvents), );
// 遍历移除替换的窗体事件
for I := to High(FOpenChildren) do
begin
FOpenChildren[I].HookEvents(AEvents);
end;
// 清空
SetLength(FOpenChildren, );
end; // 创建
procedure TForm_Main.FormCreate(Sender: TObject);
begin
with PluginsManager do
begin
// 加载同目录下dll文件
Loaders.Add(TQDLLLoader.Create(ExtractFilePath(Application.ExeName), '.dll'));
// 启动服务
Start;
end;
end; end.

DLL代码如下

unit Frm_Mdi;

interface

uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs; type
TForm_Mdi = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end; var
Form_Mdi: TForm_Mdi; implementation uses
QPlugins,
qplugins_vcl_formsvc;
{$R *.dfm} initialization // 注册一个单实例服务
RegisterFormService('/Services/Forms/MDI', 'MDITest', TForm_Mdi); finalization // 注销
UnregisterServices('/Services/Forms/MDI', ['MDITest']); end.

014.Delphi插件之QPlugins,MDI窗口的更多相关文章

  1. 015.Delphi插件之QPlugins,FMX插件窗口

    内嵌FMX的插件窗口,效果还是很可以的.退出时,会报错,很诡异啊. 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messa ...

  2. 012.Delphi插件之QPlugins,多实例内嵌窗口服务

    这个DEMO中主要是在DLL中建立了一个IDockableControl类,并在DLL的子类中写了具体的实现方法. 在主程序exe中,找到这个服务,然后调用DLL的内嵌方法,把DLL插件窗口内嵌到主程 ...

  3. 013.Delphi插件之QPlugins,模块化代码示例

    这个DEMO的是一个定义了一个窗体插件接口,把其他窗口注册到这个窗体插件接口中.主程序运行起来,就遍历一下窗体插件接口,把每个窗体内嵌到对话框中 运行效果如下 主窗口代码如下 unit Frm_Mai ...

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

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

  5. 005.Delphi插件之QPlugins,IQNotify通知

    演示的界面如下,拖动滚动条,百分比圆和进度条也是会跟着动的 主程序的代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messages ...

  6. 004.Delphi插件之QPlugins,参数传递

    界面如下 插件框架中大量使用了接口的东西,看的眼花缭乱,很多地方只做了申明,具体的实现是在另外的子类. DLL的代码如下 unit ParamTest; interface uses classes, ...

  7. 003.Delphi插件之QPlugins,菜单插件加强

    相比上一篇的菜单插件,这个在创建和销毁时候,做了增强,同时做了2个菜单对应的窗口 unit MenuSvc; interface uses windows, classes, SysUtils, Gr ...

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

    安装QPlugins里面的Demo,复制粘贴着写了一个最简单的插件,看看好不好用 EXE代码如下: unit Main_Frm; interface uses Winapi.Windows, Wina ...

  9. 011.Delphi插件之QPlugins,延时加载服务

    这个DEMO是是把DLL插件的相关信息做成了一个配置文件,主程序加载这个配置文件,从而起到延时加载的作用 主程序代码如下 unit Frm_Main; interface uses Winapi.Wi ...

随机推荐

  1. 用IDEA创建项目时没有Spring类型的项目模板

    使用的版本:2019.2.2 Community 解决方法:File=>Setting=>Plugins=>搜索Spring,安装Spring Assistant=>重启IDE ...

  2. 《Java Spring框架》Spring IOC 源码分析

    1.下载源码 源码部署:https://www.cnblogs.com/jssj/p/11631881.html 并不强求,最好是有源码(方便理解和查问题). 2. 创建子项目 Spring项目中创建 ...

  3. 解题报告:luogu P5543 [USACO19FEB]The Great Revegetation S

    题目链接:P5543 [USACO19FEB]The Great Revegetation S 好坑啊,都身败名裂了. 思路一: 考虑染色法,跑一遍搜所就好了,不给代码了. 思路二: 考虑并查集,我想 ...

  4. 「AHOI2008」紧急集合/聚会

    题目描述 这次也是很长的题面啊\(qwq\) 题目大意如下: 给定一棵\(N\)个节点的树以及\(M\)次询问,每次询问给出\(x,\ y,\ z\)三个节点,程序需要在树上找一个点\(p\) 使得\ ...

  5. Python - 列表与字符串的相互转换

    1. 列表转换成字符串,用''.join() # 创建一个列表 list1 = ['a','b','c'] # 将列表的元素拼接为字符串 print(''.join(list1)) # 将列表的元素通 ...

  6. C 如何判断编译器是否支持C90 C99?

    参考:<C Primer Plus>,Stephen Prata著,姜佑译. ANSI/ISO C标准 美国ANSI成立委员会X3J11,于89/90年,99年,11年,发布C标准:C89 ...

  7. C++11并发编程1------并发介绍

    也许有人会觉得多线程和并发难用,复杂,还会让代码出现各种各样的问题,不过,其实它是一个强有力的工具,能让程序充分利用硬件资源,让程序运行得更快. 何谓并发: 两个或更多独立得活动同时发生.计算机中就是 ...

  8. 二 Mybatis架构&MybatisDao的两种开发方式(原始Dao,接口动态代理)

    MyBatis架构图 三个对象: SqlSessionFactoryBuilder.SqlSessionFactory.SqlSession SqlSessionFactoryBuilder:主要用来 ...

  9. 如何:使用 as 和 is 运算符安全地进行强制转换(C# 编程指南)

    如何:使用 as 和 is 运算符安全地进行强制转换(C# 编程指南) 由于对象是多态的,因此基类类型的变量可以保存派生类型.若要访问派生类型的方法,需要将值强制转换回该派生类型.不过,在这些情况下, ...

  10. LIS问题

    LIS定义LIS(Longest Increasing Subsequence)最长上升子序列 .一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的. ...