说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Delphi 插件创建、调试与使用应用程序扩展

HTML文档下载 WORD文档下载 PDF文档下载
Delphi 插件创建、调试与使用应用程序扩展

有没有使用过Adobe Photoshop如果用过,你就会对插件的概念比较熟悉。对外行人来说,插件仅仅是从外部提供给应用程序的代码块而已(举个例子来说,在一个DLL中)。一个插件和一个普通DLL之间的差异在于插件具有扩展父应用程序功能的能力。例如,Photoshop本身并不具备进行大量的图像处理功能。插件的加入使其获得了产生诸如模糊、斑点,以及其他所有风格的奇怪效果,而其中任何一项功能都不是父应用程序自身所具有的。

对于图像处理程序来说这很不错,可是为什么要花偌大的力气去完成支持插件的商业应用程序呢?假设,我们举个例子,你的应用程序要产生一些报表。你的客户肯定会一直要求更新或者增加新的报表。你可以使用一个诸如Report Smith的外部报表生成器,这是个不怎么样的解决方案,需要发布附加的文件,要对用户进行额外的培训,等等。你也可以使用QuickReport,不过这会使你身处版本控制的噩梦之中——如果每改变一次字体你就要Rebuild你的应用程序的话。

然而,只要你把报表做到插件中,你就可以使用它。需要一个新的报表吗?没问题,只要安装一个DLL,下次应用程序启动时就会看见它了。另外一个例子是处理来自外部设备(比如条形码扫描器)的数据的应用程序,为了给用户更多的选择,你不得不支持半打的各种设备。通过将每种设备接口处理例程写成插件,不用对父应用程序作任何变动就可以获得最大程度的可伸缩性。

入门

在开始写代码之前最重要的事情就是搞清楚你的应用程序到底需要扩展哪些功能。这是因为插件是通过一个特定的接口与父应用程序交互的,而这个接口将根据你的需要来定义。在本文中,我们将建立3个插件,以便展示插件与父应用程序相交互的几种方式。

我们将把插件制作成DLL。不过,在做这项工作之前,我们得先制作一个外壳程序来载入和测试它们。图1显示的是加载了第一个插件以后的测试程序。第一个插件没有完成什么大不了的功能,实际上,它所做的只是返回一个描述自己的字符串。不过,它证明了很重要的一点——不管有没有插件应用程序都可以正常运行。如果没有插件,它就不会出现在已安装的插件列表中,但是应用程序仍然可以正常的行使功能。

我们的插件外壳程序与普通应用程序之间的唯一不同就在于工程源文件中出现在uses子句中的Sharemem单元和加载插件文件的代码。任何在自身与子DLL之间传递字符串参数的应用程序都需要Sharemem单元,它是DelphiMM.dll(Delphi提供该文件)的接口。要测试这个外壳,需要将DelphiMM.dll文件从Delphi\Bin目录复制到path环境变量所包含的路径或者应用程序所在目录中。发布最终版本时也需要同时分发该文件。

插件通过LoadPlugins过程载入到这个测试外壳中,这个过程在主窗口的FormCreate事件中调用,见图2。该过程使用FindFirst和FindNext函数在应用程序所在目录中查找插件文件。找到一个文件以后,就使用图3所示的LoadPlugins过程将其载入。

{ 在应用程序目录下查找插件文件 }

procedure TfrmMain.LoadPlugins;

var

sr: TSearchRec;

path: string;

Found: Integer;

begin

path := ExtractFilePath(Application.Exename);

try

Found := FindFirst(path + cPLUGIN_MASK

0

sr);

while Found = 0 do begin

LoadPlugin(sr);

Found := FindNext(sr);

end;

finally

FindClose(sr);

end;

end;

{ 加载指定的插件 DLL. }

procedure TfrmMain.LoadPlugin(sr: TSearchRec);

var

Description: string;

LibHandle: Integer;

DescribeProc: TPluginDescribe;

begin

LibHandle := LoadLibrary(Pchar(sr.Name));

if LibHandle <> 0 then

begin

DescribeProc := GetProcAddress(LibHandle

cPLUGIN_DESCRIBE);

if Assigned(DescribeProc) then

begin

DescribeProc(Description);

memPlugins.Lines.Add(Description);

end

else

begin

MessageDlg(’File "’ + sr.Name + ’" is not a valid plug-in.’

mtInformation

[mbOK]

0);

end;

end

else

MessageDlg(’An error occurred loading the plug-in "’ +

sr.Name + ’".’

mtError

[mbOK]

0);

end;

LoadPlugin方法展示了插件机制的核心。首先,插件被写成DLL。其次,通过LoadLibrary API它被动态的加载。一旦DLL被加载,我们就需要一个访问它所包含的过程和函数的途径。API调用GetProcAddress提供这种机制,它返回一个指向所需例程的指针。在我们这个简单的演示中,插件仅仅包含一个名为DescribePlugin的过程,由常数cPLUGIN_DESCRIBE指定(过程名的大小写非常重要,传递到GetProcAddress的名称必须与包含在DLL中的例程名称完全一致)。如果在DLL中没有找到请求的例程,GetProcAddree将返回nil,这样就允许使用Assigned函数测定返回值。

为了以一种易用的方式存储指向一个函数的指针,有必要为用到的变量创建一个特定的类型。注意,GetProcAddress的返回值被存储在一个变量中,DescribeProc,属于TpluginDescribe类型。下面是它的声明:

type

TPluginDescribe = procedure(var Desc: string); stdcall;

由于过程存在于DLL内部,它通过标准调用转换编译所有导出例程,因此需要使用stdcall指示字。这个过程使用一个var参数,当过程返回的时候它包含插件的描述。

要调用刚刚获得的过程,只需要使用保存地址的变量作为过程名,后面跟上任何参数。就我们的例子而言,声明:

DescribeProc(Description)

将会调用在插件中获得的描述过程,并且用描述插件功能的字符串填充Description变量。

构造插件

我们已经创建好了父应用程序,现在该轮到创建我们希望加载的插件了。插件文件是一个标准的Delphi DLL,所以我们从Delphi IDE中创建一个新DLL工程,保存它。由于导出的插件函数将用到字符串参数,所以要在工程的uses子句中把Sharemen单元放在最前面。图4列出的就是我们这个简单插件的工程源文件。

uses

Sharemem

SysUtils

Classes

main in ’main.pas’;

{$E plg.}

exports

DescribePlugin;

begin

end.

虽然插件是一个DLL文件,但是没有必要一定要给它一个.DLL的扩展名。实际上,一个原因就足以让我们有理由改变扩展名:当父应用程序寻找要加载的文件时,新的扩展名可以作为特定的文件掩模。通过使用别的扩展名(我们的例子使用了*.plg),你可以在一定程度上确信应用程序只会载入相应的文件。编译指示字$X可以实现这个改变,也可以通过Project Options对话框的Application页来设置扩展名。

第一个例子插件的代码是很简单的。图5显示了包含在一个新单元中的代码。注意,DescribePlugin原型与外壳应用程序中的TpluginDescribe类型相一致,使用附加的export保留字指定该过程将被导出。被导出的过程名称也将会出现在主工程源代码的exports段中(在图4中列出)。

unit main;

interface

procedure DescribePlugin(var Desc: string);

export; stdcall;

implementation

procedure DescribePlugin(var Desc: string);

begin

Desc := ’Test plugin v1.00’;

end;

end.

在测试这个插件之前,要先把它复制到主应用程序的路径下。最简单的办法就是在主目录的子目录下创建插件,然后把输出路径设置为主路径(Project Options对话框的Directories/Conditionals也可以作这个设置)。

调试

现在介绍一下Delphi 3中一个较好的功能:从IDE中调试DLL的能力。在DLL工程中可以通过Run paramaters对话框指定某程序为宿主应用程序,这就是指向将调用DLL的应用程序的路径(在我们这个例子中,就是刚刚创建的测试外壳程序)。然后你就可以在DLL代码中设置断点并且按F9运行它——就像在一个普通应用程序中做的那样。Delphi会运行指定的宿主程序,并且,通过编译带有调试信息的DLL,把你指引到DLL代码内的断点处。

文本框中光标位置的获得-VB资料 无关联程序时开启“打开方式”窗口 -VB资料 显示 Combo 的下拉条 -VB资料 显示Windows系统的标准ABOUT窗口-VB资料 显示程序的版本 -VB资料 显示窗口的水平和垂直滚动条-VB资料 一劳永逸让VB自动改变控件大小 移动没有标题栏的窗口 -VB资料 隐藏Win95任务栏 -VB资料 VB用API函数打开 MS CommonDialog对话框 VB用MSGBOX函数设计版权信息: 用VB5 制作“闪烁标题栏”窗体 用VB5.0获取正在系统中运行的窗口标题 用VB实现浮动按钮 用VB5实现窗口图象缩放、滚动技巧 用VB6建立带光栅的超级开始菜单 用VB尝试新的界面风格 用VB建立字符界面的控制台程序 用VB快速读取TextBox第N行的数据 用VB 设计VCD播放器 用VB设计更好的用户界面 用VB设计聚焦框程序 用VB实现“ICQ”式的启动欢迎画面 用VB实现全屏幕图形界面及动态功能提示 用VB实现任务栏右下角的小图标 用VB制作常居上层的浮动工具箱 用VB制作即时动态按钮 用VB作浮动式图标提示按钮 用Visual Basic编写托盘程序 用Visual Basic窗体背景花纹的实现 用Visual Basic设计窗体背景花纹 aspimage注册问题 请问GetLocalTime()与GetSystemTime()的区别??? Visual Studio.Net RC2都出来N段时间了,为什么还不使?! 请教:如何将HDLC协议的数据流复原,即我接收到符合HDLC规程数据,怎样去掉0和标志,获取有用的数据? 求助:一个派生类问题 手机的软件测试分那几部分? 这段代码里表格为什么不会出现? 一个关于win2000advanced server升级sp2的问题。 怎么设置Listbox!急!急! 什么地方有关于j2ee的资料? 关于sqlplus的spool功能?(必给分) 关于System.net 浏览器下载怎样设置他不自动打开word,excel,servlet程序怎么写啊? *.iso是什么文件??虚拟光驱用的吗??如何运行?? 局域网内读取(只是读取)服务器内数据库(.MDB) 有什么可行的办法? 谁有aspedit 2001 build 29 的破解与 汉化 偶的win2000p打不开txt文件,说缺少prontpg.exe文件,怎么回事呢?//牛虻 如何更改对话框上的字体大小。。我好象在对话框的属性设置里没有看到关于字体的设置 怎样才能使我的QQ正常上网? 高手注意!!! 谁能精确的告诉我需要哪几个文件就可以在不同的机器(系统不同)上执行编译好的vb6.0程序 勇敢的警察!?!! 各位大侠,小妹问一个关于Property Sheet的问题,怎么把下面的“应用,帮助,取消“设置成不显示 用installshield express制作安装程序,程序有关于SQL Server的连接,应怎样处理? 各位侠士,vc中怎样读取DBGrid Control中的数据?怎样执行sql 语句?就向delphi中一样?拜托!拜托! 版本控制问题[Fatal Error]Internal Error: L519 如何在Exhcnage server 服务器上安装反病毒软件 apache服务器如何同tomcat4.0 结合起来. 字符串中怎么显示“”,例如要显示字符串-----"“ID”是必选字段"。 求助Applet Servlet CreateOleObject('ADODB.Connection')怎么用? 哪位有AIX下的cc,xlC,make的中文使用说明?我的英语太差,看系统的帮助头都大了。 谁有SHA1算法源代码的,给我一份,我很急,一定给分!有网址的,也给分? ODBC SQL SERVER DRIVER timeout expired错误,不知如何解决 请问那位大侠知道哪有北大出版社出版的WINDOWS程序设计这本书的电子版下载 如何控制session的有效时间? VBA下怎样实现...... 很简单的问题,如果得到OS是什么啊? VB怎样调用Oracle没有包的存贮过程? 哪位能提供AIX下的cc,xlC,make的中文使用说明?我的英语太差,看系统的帮助头都大了! 那位有用网叶通过servlet提交数据的例子,越简单越好 救命啊! ----关于漂浮的工具条的隐藏(按钮失踪了!)。 主题:为何我的机子只能进入DOS平台,无法再进入Windows界面? 请问什么地方有《UNIX环境高级编程》的随书源代码下载,谢谢!! 如果得到OS的类型啊?用什么API函数啊? 请问哪有Linux的源代码下载??? 作者如何获得他自己编写的程序的版权及著作权? SOS!!请高手速指点, 立刻要用到,谢谢!! 报表字段过长如何分行打印? 急。。。关于字体属性 Jbuilder5.0 注册码,那个想要,我这儿有!今天刚搞到! 有30千克糖果,每2分之4千克装一袋,现在已经装了总数的3分之2,已近装了多少袋? L与cm^3的换算是什么 一根钢材长5分之4米,重25分之2吨,这种钢材1米重多少吨 有一包糖,如果吃掉6分之1千克,还剩3分之2千克,这包糖原来有多少千克,如果吃掉这包糖的6分之1,还剩3分之2千克,这包糖原来有多少千克做成一个无盖的长方体水箱。做这个水箱至少要用铁皮 七(15)班同学上体育课,排成3行少1人,排成4行多3人,排成5行少1人,排成6行多5人.上体育的同学有多少名 一种钢材一米重20分之1吨2吨这样的钢材有多少米明天要交的 4/5米的钢柱质量为1/25吨,同样的钢柱4/5吨长()米 2.5μm=?m 科学计数法 83.4亿等于多少元?用科学计数法 dm代表什么长度单位 某班同学上体育课,如果每排3人,就多出1人,如果每排6人,就多出4人每排7人择多出5人快这个班至少有多少人 1s等于多少h,科学计数法 dm数学里代表什么? 用科学计数法表示1、银原子直径为0.0003微米,相当于多少米?2、350毫米^2的芯片上能集成5亿个元件,1个元件占多少平方毫米?3、1纳米相当于一根头发丝直径的六万分之一,一根头发丝的直径大约 1FEET等于多少个英尺 dm在数学表示什么长度单位? 七(15)班同学上体育课,排3行少1人,排4行多3人,排成5行少1人,排成6行多5人,问体育课最少有多少人? 买3千克茶叶和5千克糖,一共用去420元,买同样的2千克茶叶比5千克糖贵130元,茶叶和糖的单价各多少?用消去法解题,快, 长度单位里 dm表示什么 设有理数M,用科学计数法记为M=a×10×5,则M有几位整数? 买3千克茶叶和5千克糖需要420元,买同样的5千克茶叶和5千克糖,需要640元.每千克茶叶和每千克糖各多少元? "dm"是什么长度单位? 小红用160元买了棉花糖和果汁糖各5包.3包棉花糖的售价刚好是5包果汁糖的售价.棉花糖和果汁糖各售多少元请您用中合算式回答! 买三千克茶叶和5千克糖,用去420.4元,买同样的3千克茶叶和3千克糖用去384.6元,每千克茶叶多少元?要算式,不要设想, mil厚度单位1.6mil等于多少丝?急用! 小红用160元买了棉花糖和果汁糖各五包.三包棉花糖的售价刚好是五包果汁糖的售价 1.买3千克茶叶和5千克糖一共用去420元买2千克同样的茶叶比5千克糖贵130元,每千克茶叶和每千克糖各多少元2.一张数学试卷,只有25道选择题,做对一题得4分,做错或不做,一题倒扣1分.小敏得了80 mil是什么单位 小红用160元买了棉花糖和果汁糖各5包,3包棉花糖的售价刚好是5包果汁糖的售价.棉花糖和果汁糖每包各多少 7.5微米等于多少米 用科学计数法表示 把2米长的绳子平均分成3段,每段占全长的( ---- )每段长( )米 1"等于多少mil?如何换算? 小红拿了160元买棉花糖果汁糖个5包3包棉花糖等于5包果汁糖问果汁糖和棉花糖各多少元? 把2米长的绳了平均分成4段,每段长( ),每段占全长的( ),每段是2米的( ) mil与"的换算关系? 小红用160元买了棉花糖和果汁糖各5包.3包棉花糖的售价刚好是5包果汁糖 1cm等于多少微米 照片所有尺寸和cm的换算 一种钢材五分之四米重八分之七千克,这样的钢材1米重()千克,1千克这样的钢材长()米 长度单位1nm=10(-9次幂)则25100nm=-----m? 把8/13吨平均分成5份,求每份是多少就是求8/13吨的几分之几是多少?算式是( ). 五包茶叶和4包糖共重44千克5 - 离问题结束还有 14 天 23 小时4茶叶+1糖 =3糖+1茶叶 三围 36:24:36是个怎样的身材? 1 cm等于多少磅?1mm 等于多少磅? 五包茶和四包糖共四十四千克比糖轻把茶放一包到糖一边去糖放一包倒茶那边去两种相等,糖和茶各多重? 我1.67cm,三围是90 65 87可以吗 要算成36 24 34那样是多少 1mm=( )cm foot是什么 关于长度单位的数学日记怎么写? 1mm方等于多少cm^2 4个茶杯和5包茶叶的价格之和小于22元,而6个茶杯和3包茶叶价格之和大于24元,则2个茶杯与3包茶叶的价格比A 2个茶杯贵 B 3包茶叶贵 C 二者相同 D 无法确定 长度单位数学日记的写作 1微米=()米 用科学计数法吧! foot什么意思 写一则数学日记(要求带有长度单位和面积单位) 一微米等于多少米?科学计数法 FEET是什么长度单位? 写一篇数学日记内容是关于长度单位二年级 1毫米=1000微米,2.5微米可以用科学记数法表示为,(急用 feet是什么意思?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn