004.Delphi插件之QPlugins,参数传递
界面如下

插件框架中大量使用了接口的东西,看的眼花缭乱,很多地方只做了申明,具体的实现是在另外的子类。
DLL的代码如下
unit ParamTest; interface uses
classes,
sysutils,
types,
QPlugins,
qstring,
qplugins_base,
qplugins_params; type
// 和主窗口一样的接口
IList = interface
['{6D1A9CAB-9284-42DC-95C0-342DC72FAC03}']
function Add(Item: Pointer): Integer;
procedure Clear;
procedure Delete(Index: Integer);
procedure Exchange(Index1, Index2: Integer);
function ExtractItem(Item: Pointer; Direction: TDirection): Pointer;
function First: Pointer;
function IndexOf(Item: Pointer): Integer;
function IndexOfItem(Item: Pointer; Direction: TDirection): Integer;
procedure Insert(Index: Integer; Item: Pointer);
function Last: Pointer;
procedure Move(CurIndex, NewIndex: Integer);
function Remove(Item: Pointer): Integer;
function RemoveItem(Item: Pointer; Direction: TDirection): Integer;
procedure Pack;
procedure Sort(Compare: TListSortCompare);
procedure SortList(const Compare: TListSortCompareFunc);
end; // 和主窗口中一样的参数测试服务接口
IParamTestService = interface
['{FB9443D9-EF9A-43F2-9F8D-9B838981AEBE}']
procedure ObjectTest(AList: IList);
procedure ArrayTest(AParams: IQParams);
procedure StreamTest(AParams: IQParams);
procedure StandTest(AParams: IQParams);
end; // 参数测试服务接口,各函数的具体实现
TParamTestService = class(TQService, IParamTestService)
public
procedure ObjectTest(AList: IList);
procedure ArrayTest(AParams: IQParams);
procedure StreamTest(AParams: IQParams);
procedure StandTest(AParams: IQParams);
end; // Log接口,
ILogService = interface
['{C45581C0-C290-4A9A-BF9E-AC2D814593FE}']
procedure Log(S: PWideChar);
end; implementation { TParamTestService } // 数组参数测试
procedure TParamTestService.ArrayTest(AParams: IQParams);
var
ALog: ILogService;
// 主界面传过来的参数
procedure LogParams(AParent: IQParams);
var
I: Integer;
AParam: IQParam;
S: QStringW;
begin
S := '参数共 ' + IntToStr(AParent.Count) + ' 个';
ALog.Log(PWideChar(S));
// 判断主界面传过来的参数,有多少个成员
for I := to AParent.Count - do
begin
AParam := AParent[I];
// 取出每次循环的名字和类型
S := AParam.Name;
// 判断参数类型
if AParam.ParamType = ptArray then
begin
S := S + ' 是一个数组,遍历其元素:';
ALog.Log(PWideChar(S));
LogParams(AParam.AsArray);
S := '子参数枚举结束';
ALog.Log(PWideChar(S));
end
else
ALog.Log(PWideChar(S + ' 的值为:' + AParam.AsString.Value));
end;
end; begin
ALog := PluginsManager as ILogService;
// 神奇!插件中ALog是没有实体的,实体部分是在主程序实现,在插件中的函数调用的也是主程序中的方法
LogParams(AParams);
end; // 对象参数测试
procedure TParamTestService.ObjectTest(AList: IList);
var
I: Integer;
begin
// 从主程序传入一个空的AList,在插件中处理这个AList
for I := to do
begin
AList.Add(Pointer(I));
end;
end; // 标准参数测试
procedure TParamTestService.StandTest(AParams: IQParams);
var
ALog: ILogService;
// 主界面传过来的参数
procedure LogParams(AParent: IQParams);
var
I: Integer;
AParam: IQParam;
S: QStringW;
begin
S := '参数共 ' + IntToStr(AParent.Count) + ' 个';
ALog.Log(PWideChar(S));
// 判断主界面传过来的参数,有多少个成员
for I := to AParent.Count - do
begin
AParam := AParent[I];
// 取出每次循环的名字和类型
S := AParam.Name;
if AParam.ParamType = ptArray then
begin
S := S + ' 是一个数组,遍历其元素:';
ALog.Log(PWideChar(S));
LogParams(AParam.AsArray);
S := '子参数枚举结束';
ALog.Log(PWideChar(S));
end
else
begin
// 输出
ALog.Log(PWideChar(S + ' 的值为:' + AParam.AsString.Value));
end;
end;
end; begin
// 输出函数是实体是在主窗口实现的
ALog := PluginsManager as ILogService;
// 神奇!插件中ALog是没有实体的,实体部分是在主程序实现,在插件中的函数调用的也是主程序中的方法
ALog.Log('曾经沧海难为水!');
LogParams(AParams);
end; // 流参数测试
procedure TParamTestService.StreamTest(AParams: IQParams);
var
AStream: TQStream;
S: QStringW;
begin
// 读取插件流内容
AStream := TQStream.Create(AParams[].AsStream);
try
S := '这是从插件中返回的内容。';
AStream.Size := ;
// 写入内容
AStream.WriteBuffer(PWideChar(S)^, Length(S) shl );
finally
FreeObject(AStream);
end;
end; initialization // 单元初始化时,注册Params服务插件
RegisterServices('Services', [TParamTestService.Create(IParamTestService, 'Params')]); finalization // 注销Params服务插件
UnregisterServices('Services', ['Params']); end.
EXE代码如下
unit Frm_Main; interface uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
Types,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs,
qstring,
QPlugins,
Vcl.StdCtrls,
Vcl.ExtCtrls,
qplugins_base,
qplugins_params,
qplugins_loader_lib; type
// 这个演示如何将对象进行封装,做为参数在服务间传递
// IList接口,具体都是在子方法中实现
IList = interface
['{6D1A9CAB-9284-42DC-95C0-342DC72FAC03}']
function Add(Item: Pointer): Integer;
procedure Clear;
procedure Delete(Index: Integer);
procedure Exchange(Index1, Index2: Integer);
function ExtractItem(Item: Pointer; Direction: TDirection): Pointer;
function First: Pointer;
function IndexOf(Item: Pointer): Integer;
function IndexOfItem(Item: Pointer; Direction: TDirection): Integer;
procedure Insert(Index: Integer; Item: Pointer);
function Last: Pointer;
procedure Move(CurIndex, NewIndex: Integer);
function Remove(Item: Pointer): Integer;
function RemoveItem(Item: Pointer; Direction: TDirection): Integer;
procedure Pack;
procedure Sort(Compare: TListSortCompare);
procedure SortList(const Compare: TListSortCompareFunc);
function GetCount: Integer;
function GetItem(Index: Integer): Pointer;
end; // 参数测试服务,对应的4个方法
IParamTestService = interface
['{FB9443D9-EF9A-43F2-9F8D-9B838981AEBE}']
procedure ObjectTest(AList: IList);
procedure ArrayTest(AParams: IQParams);
procedure StreamTest(AParams: IQParams);
procedure StandTest(AParams: IQParams);
end; // 对上面的接口进行封装,以便在服务间传递
TListWrap = class(TQInterfacedObject, IList)
protected
FList: TList;
public
constructor Create; override;
destructor Destroy; override;
function Add(Item: Pointer): Integer;
procedure Clear;
procedure Delete(Index: Integer);
procedure Exchange(Index1, Index2: Integer);
function ExtractItem(Item: Pointer; Direction: TDirection): Pointer;
function First: Pointer;
function IndexOf(Item: Pointer): Integer;
function IndexOfItem(Item: Pointer; Direction: TDirection): Integer;
procedure Insert(Index: Integer; Item: Pointer);
function Last: Pointer;
procedure Move(CurIndex, NewIndex: Integer);
function Remove(Item: Pointer): Integer;
function RemoveItem(Item: Pointer; Direction: TDirection): Integer;
procedure Pack;
procedure Sort(Compare: TListSortCompare);
procedure SortList(const Compare: TListSortCompareFunc);
function GetCount: Integer;
function GetItem(Index: Integer): Pointer;
end; // 输出接口,只定义,子类实现
ILogService = interface
['{C45581C0-C290-4A9A-BF9E-AC2D814593FE}']
procedure Log(S: PWideChar);
end; TLogService = class(TQService, ILogService)
public
// 输出接口的实现
procedure Log(S: PWideChar);
end; TForm1 = class(TForm)
Panel1: TPanel;
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations } end; var
Form1: TForm1; implementation {$R *.dfm}
{ TListWrap } function TListWrap.Add(Item: Pointer): Integer;
begin
Result := FList.Add(Item);
end; procedure TListWrap.Clear;
begin
FList.Clear;
end; constructor TListWrap.Create;
begin
inherited;
FList := TList.Create;
end; procedure TListWrap.Delete(Index: Integer);
begin
FList.Delete(Index);
end; destructor TListWrap.Destroy;
begin
FreeAndNil(FList);
inherited;
end; procedure TListWrap.Exchange(Index1, Index2: Integer);
begin
FList.Exchange(Index1, Index2);
end; function TListWrap.ExtractItem(Item: Pointer; Direction: TDirection): Pointer;
begin
Result := FList.ExtractItem(Item, Direction);
end; function TListWrap.First: Pointer;
begin
Result := FList.First;
end; function TListWrap.GetCount: Integer;
begin
Result := FList.Count;
end; function TListWrap.GetItem(Index: Integer): Pointer;
begin
Result := FList[Index];
end; function TListWrap.IndexOf(Item: Pointer): Integer;
begin
Result := FList.IndexOf(Item);
end; function TListWrap.IndexOfItem(Item: Pointer; Direction: TDirection): Integer;
begin
Result := FList.IndexOfItem(Item, Direction);
end; procedure TListWrap.Insert(Index: Integer; Item: Pointer);
begin
FList.Insert(Index, Item);
end; function TListWrap.Last: Pointer;
begin
Result := FList.Last;
end; procedure TListWrap.Move(CurIndex, NewIndex: Integer);
begin
FList.Move(CurIndex, NewIndex);
end; procedure TListWrap.Pack;
begin
FList.Pack;
end; function TListWrap.Remove(Item: Pointer): Integer;
begin
Result := FList.Remove(Item);
end; function TListWrap.RemoveItem(Item: Pointer; Direction: TDirection): Integer;
begin
Result := FList.RemoveItem(Item, Direction);
end; procedure TListWrap.Sort(Compare: TListSortCompare);
begin
FList.Sort(Compare);
end; procedure TListWrap.SortList(const Compare: TListSortCompareFunc);
begin
FList.SortList(Compare);
end; // 按钮_对象作为参数
procedure TForm1.Button1Click(Sender: TObject);
var
AList: IList;
AService: IParamTestService;
I: Integer;
begin
Memo1.Lines.Add('【通过接口传递对象演示】');
// 定义一个接口,子类创建,拥有子类的各种属性
AList := TListWrap.Create;
// 通过路径获取指定的服务接口实例
AService := PluginsManager.ByPath('Services/Params') as IParamTestService;
// 如果插件对象存在
if Assigned(AService) then
begin
// 从主程序传入一个空的AList,在插件中处理这个AList
AService.ObjectTest(AList);
for I := to AList.GetCount - do
begin
Memo1.Lines.Add(IntToStr(I) + ' - ' + IntToHex(IntPtr(AList.GetItem(I)), SizeOf(Pointer) shl ));
end;
end;
end; // 按钮_流做为参数
procedure TForm1.Button2Click(Sender: TObject);
var
AParams: IQParams;
AService: IParamTestService;
AStream: TQStream;
S: QStringW;
begin
Memo1.Lines.Add('【流做为参数传递演示】');
// 创建参数类
AParams := TQParams.Create;
// 类型设置成流
AStream := QStream(AParams.Add('Stream', ptStream).GetAsStream);
S := 'Hello,world';
AStream.WriteBuffer(PWideChar(S)^, Length(S) shl );
// 通过路径获取指定的服务接口实例
AService := PluginsManager.ByPath('Services/Params') as IParamTestService;
// 如果插件对象存在
if Assigned(AService) then
begin
// 调用插件中的StreamTest实例,执行之后AStream文本内容变成了插件反馈的内容
AService.StreamTest(AParams);
// 输出
AStream.Position := ;
S := LoadTextW(AStream, teUnicode16LE);
Memo1.Lines.Add(Format('新的流内容:"%s" ', [S]));
end;
FreeAndNil(AStream);
end; // 按钮_二维参数
procedure TForm1.Button3Click(Sender: TObject);
var
AParams, ASubParams: IQParams;
AService: IParamTestService;
begin
Memo1.Lines.Add('【二维参数演示】');
AParams := TQParams.Create;
ASubParams := AParams.Add('Subs', ptArray).AsArray;
ASubParams.Add('Name', ptUnicodeString).AsString := NewString('QDAC');
ASubParams.Add('Version', ptUInt8).AsInteger := ;
Memo1.Lines.Add('原始参数');
Memo1.Lines.Add(AParams.AsString.Value);
// 通过路径获取指定的服务接口实例
AService := PluginsManager.ByPath('Services/Params') as IParamTestService;
// 如果插件对象存在
if Assigned(AService) then
begin
// 调用插件中的ArrayTest实例
AService.ArrayTest(AParams);
end;
end; // 按钮_普通参数
procedure TForm1.Button4Click(Sender: TObject);
var
AParams: IQParams;
AService: IParamTestService;
begin
Memo1.Lines.Add('【常规参数传递演示】');
// 给参数添加2个不同类型的成员
AParams := TQParams.Create;
AParams.Add('Int', ptInt32).AsInteger := ;
AParams.Add('DT', ptDateTime).AsFloat := Now;
// 通过路径获取指定的服务接口实例
AService := PluginsManager.ByPath('Services/Params') as IParamTestService;
// 如果插件对象存在
if Assigned(AService) then
begin
// 调用插件中的StandTest实例
AService.StandTest(AParams);
end;
end; procedure TForm1.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutDown := True;
// 注册Log日志接口,其实就是下面的一个输出函数
RegisterServices('/Services', [TLogService.Create(ILogService, 'Log')]);
// 加载同目录的DLL
PluginsManager.Loaders.Add(TQDLLLoader.Create(ExtractFilePath(Application.ExeName), '.DLL'));
// 启动所有的加载器加载支持的插件
PluginsManager.Start;
end; { TLogService } // 输出接口的实现
procedure TLogService.Log(S: PWideChar);
begin
//具体实现,就是一个输出函数
Form1.Memo1.Lines.Add(S);
end; end.
004.Delphi插件之QPlugins,参数传递的更多相关文章
- 015.Delphi插件之QPlugins,FMX插件窗口
内嵌FMX的插件窗口,效果还是很可以的.退出时,会报错,很诡异啊. 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messa ...
- 014.Delphi插件之QPlugins,MDI窗口
不知道为什么,这个DEMO编译出来报错,运行不了,在QDAC群里问了一下也没人响应. 效果如下 主程序代码如下 unit Frm_Main; interface uses Winapi.Windows ...
- 013.Delphi插件之QPlugins,模块化代码示例
这个DEMO的是一个定义了一个窗体插件接口,把其他窗口注册到这个窗体插件接口中.主程序运行起来,就遍历一下窗体插件接口,把每个窗体内嵌到对话框中 运行效果如下 主窗口代码如下 unit Frm_Mai ...
- 012.Delphi插件之QPlugins,多实例内嵌窗口服务
这个DEMO中主要是在DLL中建立了一个IDockableControl类,并在DLL的子类中写了具体的实现方法. 在主程序exe中,找到这个服务,然后调用DLL的内嵌方法,把DLL插件窗口内嵌到主程 ...
- 011.Delphi插件之QPlugins,延时加载服务
这个DEMO是是把DLL插件的相关信息做成了一个配置文件,主程序加载这个配置文件,从而起到延时加载的作用 主程序代码如下 unit Frm_Main; interface uses Winapi.Wi ...
- 010.Delphi插件之QPlugins,遍历服务接口
这个DEMO注意是用来看一个DLL所拥有的全部服务接口 演示效果如下 代码如下: unit Frm_Main; interface uses Winapi.Windows, Winapi.Messag ...
- 009.Delphi插件之QPlugins,服务的热插拔
这个DEMO用来演示服务的替换,用起来总是怪怪的感觉,效果图如下 代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messages, ...
- 007.Delphi插件之QPlugins,插件的卸载和重新加载
效果图如下,可以反复卸载和重新加载.QPlugins这个插件,还没弄明白,摸索着跟着DEMO写 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows ...
- 005.Delphi插件之QPlugins,IQNotify通知
演示的界面如下,拖动滚动条,百分比圆和进度条也是会跟着动的 主程序的代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messages ...
随机推荐
- CSP2019 滚粗记
目录 CSP 2019 游记 DAY 0 DAY 1 DAY 2 CSP总结 自测之后 CSP 2019 游记 坐标:GD,GZ 人物:hyf 组别:J和S 任务:划水 目标:划水 任务奖励:退役证书 ...
- nginx 加工上游服务器返回的内容,并返回给客户端
禁用上游响应头部功能 Syntax: proxy_ignore_headers field ...; Default: — Context: http, server, location 功能介绍:某 ...
- 了解 Fetch API与Fetch+Async/await
背景 提及前端与服务器端的异步通信,离不开 Ajax (Asynchronous JavaScript and XML).实际上我们常说的 Ajax 并非指某一项具体的技术,它主要是基于用脚本操作 H ...
- Python学习笔记011
多行注释 '''字符串 ''' 除了用来多行注释还可以用来打印多行
- 图解JVM--(二)垃圾回收
垃圾回收 1.如何判断对象可以回收 1.1 引用计数 在对象中添加一个引用计数器,每当有一个地方引用它,计数器值就加一,当引用失效时,计数器值就减一,任何时刻计数器为零的对象就不可能再被使用的,就可以 ...
- Maven项目-jar包冲突:MyServlet is not a Servlet解决方法
异常显示:运行时jar包冲突异常 问题所在: jar包冲突,自己导入的jar包与tomcat中的jar包相同. 解决方法: 对(servlet,jsp)jar包设置作用域. 再次启动项目,问题已解决.
- Python 基础之模块之os os.path 及os与shutil对比
一: os 对系统进行操作 #注:以下操作都在linux环境下操作,且很多运行之前需要做好相关条件import os#(1)system() 在python总执行系统命令#os.system(&quo ...
- Linux系统监控 zabbix-agent 主机添加的操作页面
#!/bin/bash#设置解析#安装zabbix源.aliyun YUM源# rpm -ivh http://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zab ...
- 常用WinAPI函数整理------------转载
常用WinAPI函数整理原创 玩撕你 发布于2019-09-04 20:06:55 阅读数 101 收藏展开 之前的博客写了很多关于Windows编程的内容,在Windows环境下的黑客必须熟练掌握底 ...
- java异常处理动手动脑问题解决和课后总结
动手动脑 一.问题:请阅读并运行AboutException.java示例,然后通过后面的几页PPT了解Java中实现异常处理的基础知识. 1.源代码 import javax.swing.*; cl ...