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 ...
随机推荐
- CSS选择器整理
基本选择器 标签选择器:直接写标签名 id选择器:#id名 class选择器:.class名 通配选择器:* 组合选择器 交集:ABCDEFG...... 并集:E, F, G, ...... 关系选 ...
- PAT A1091 Acute Stroke
对于坐标平面的bfs模板题~ #include<bits/stdc++.h> using namespace std; ; ][][]={false}; ][][]; int n,m,l, ...
- 学习笔记(13)- decaNLP训练WikiSQL
将自然语言转为sql语句,达到对话查询报表的效果. 参考资料 参考1 https://mp.weixin.qq.com/s/i7WAFjQHK1NGVACR8x3v0A 语义解析.SQL查询生成与语义 ...
- input文本框自适应文本内容宽度
input文本框自适应文本内容宽度 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...
- Java - 实现双向链表
熟悉一下Java... package ChianTable; import java.util.Scanner; /** * Created by Administrator on 2018/3/2 ...
- redhat 7.6 网络配置
网卡配置目录 /etc/sysconfig/network-scripts/ 关闭网卡 $$ 打开网卡 ifdown ensp8 && ifup ensp8 重启网卡服务 servic ...
- SignalR Connection has not been fully initialized
在使用 SignalR 过程中遇到 SignalR: Connection has not been fully initialized. Use .start().done() or .start( ...
- Python开发之Anconda环境搭建
Python的强大之处在于它的应用范围广泛,遍及人工智能.科学计算.web开发.系统运维.大数据及云计算等,实现其强大功能的前提,就是Python具有数量庞大且功能相对完善的标准库和第三方库.通过对库 ...
- .Net后台实现微信APP支付
上一节分享了微信小程序支付的后台,这一节来分享一下微信APP支付的后台.微信APP支付和微信小程序差别不大,微信APP支付后台不需要微信登录凭证.后台下单时交易类型(trade_type)不再是&qu ...
- Flask - 多APP应用(不太重要)
1. 多APP应用 请求进来时,可以根据URL的不同,交给不同的APP处理.一般用蓝图也可以实现.一般不写多app应用. from werkzeug.wsgi import DispatcherMid ...