现在位置:主页>资源共享> 文章内容

初探Delphi中的插件编程

我要投稿更新日期:2008-07-22 点击:

//-----------------------------------------
//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) 系统模块表设计


上一页 1 23 4 下一页
所有评论

评论列表


我也评论来评论! 点击此处参与本文评论

注意:本站采用匿名评论,请各位网友注意自己的言行