//-----------------------------------------
//Name: FreeDLLForm
//Func: DLL插件调用出口函数
//Para: AHandle 挂靠程序句柄
//Rtrn: true/false
//Auth: CST
//Date: 2005-6-11
//-----------------------------------------
function FreeDLLForm(AHandle: THandle; ACaption: string; AUserID: string):boolean;
begin
Application.Handle:=AHandle; //挂靠到主程序容器
if DLL_Form.Showing then DLL_Form.Close; //如果窗口打开先关闭,触发FORM.CLOSEQUERY可取消关闭过程
if not DLL_Form.Showing then
begin
DLL_Form.Free;
result:=true;
end //仍然打开状态,说明CLOSEQUERY.CANCLOSE=FALSE
else
begin
result:=false;
end;
end;
end.
DLL工程文件代码如下:
| library Official; { Important note about DLL memory management: ShareMem must be the first unit in your library’s USES clause AND your project’s (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. } uses SysUtils, Classes, UnitOfficialDetailForm in ’UnitOfficialDetailForm.pas’ {FormOfficialDetail}, UnitOfficialMainForm in ’UnitOfficialMainForm.pas’ {FormOfficialMain}, UnitOfficeEntrance in ’UnitOfficeEntrance.pas’, UnitOfficialClass in ’..\..\Public\Library\UnitOfficialClass.pas’, UnitMyDataAdatper in ’..\..\Public\Library\UnitMyDataAdatper.pas’, UnitMyHeaders in ’..\..\Public\Library\UnitMyHeaders.pas’; {$R *.res} exports ShowDLLForm,FreeDLLForm; //接口函数 begin end. |
插件程序一旦调用了DLL窗口,窗口实例将会保持在HALL窗口的上层,因此不用担心遮挡的问题。
容器程序的实现
1、接口函数的引入
调用DLL库中的函数有显式和隐式两种方式,显式调用更灵活,因此我们使用显示调用。在Delphi中需要为接口函数申明函数类型,然后实例化函数类型的实例,该实例实际是一个指向函数的指针,通过指针我们可以访问到函数并传递参数、获取返回值。在单元文件的Interface部分加入函数类的申明:
| type //定义接口函数类型,接口函数来自DLL接口 TShowDLLForm = Function(AHandle:THandle; ACaption: String; AUserID:string):Boolean;stdcall; TFreeDLLForm = Function(AHandle:THandle; ACaption: String; AUserID:string):boolean;stdcall; |
显示调用库函数需要如下几个步骤:
1) 载入DLL库文件
2) 获得函数地址
3) 执行函数
4) 释放DLL库
接下来我们将详细讨论这几个步骤。
2、载入DLL库文件
通过调用API函数LoadLibrary可以将DLL库载入到内存中,在此我们不讨论DLL对内存管理的影响。LoadLibrary的参数是DLL文件的地址路径,如果载入成功会返回一个CARDINAL类型的变量作为DLL库的句柄;如果目标文件不存在或其他原因导致载入DLL文件失败会返回一个0。
3、实例化接口函数
获得接口函数指针的API函数为GetProcAddress(库文件句柄,函数名称),如果找到函数则会返回该函数的指针,如果失败则返回NIL。
使用上文定义的函数类型定义函数指针变量,然后使用@操作符获得函数地址,这样就可以使用指针变量访问函数。主要代码如下:
| …… var ShowDLLForm: TShowDLLForm; //DLL接口函数实例 FreeDLLForm: TFreeDLLForm; begin try begin APlugin.ProcAddr := LoadLibrary(PChar(sPath)); APlugin.FuncFreeAddr := GetProcAddress(APlugin.ProcAddr,’FreeDLLForm’); APlugin.FuncAddr := GetProcAddress(APlugin.ProcAddr ,’ShowDLLForm’); @ShowDLLForm:=APlugin.FuncAddr ; @FreeDLLForm:=APlugin.FuncFreeAddr; if ShowDllForm(Self.Handle, APlugin.Caption , APlugin.UserID) then Result:=True …… |
4、一个具体的实现方法
为了结构化管理插件,方便今后的系统扩充,我们可以结合数据库记录可用的DLL信息,然后通过查询数据库记录动态访问DLL程序。
1) 系统模块表设计
上一篇:DELPHI异常处理机制 下一篇:Delphi 中智能对象的实现






评论列表