{ 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,
Unit1 in 'Unit1.pas' {Form1};
type
TForm1 = class(TForm)
Label1: TLabel;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
//打开本窗口
function ShowDLLForm(AHandle: THandle; ACaption: string): Boolean; stdcall;
//输出标题
function GetCaption: Pchar; stdcall;
implementation
{$R *.dfm}
function GetCaption: Pchar; stdcall;
begin
Result := '插件演示NO1';
end;
function ShowDLLForm(AHandle: THandle; ACaption: string): boolean;
begin
result := true;
application.Handle := aHandle;
with TForm1.Create(application) do
begin
try
caption := ACaption;
showmodal;
finally
free;
end;
end;
end;
//通用过程,查找指定扩展名的文件,并存于Files中
procedure SearchFileExt(const Dir, Ext: string; Files: TStrings);
var
found: TSearchRec;
i: integer;
Dirs: TStrings;
Finished: integer;
begin
StopSearch := false;
Dirs := tstringlist.create;
finished := findfirst(dir + '*.*', 63, Found);
while (finished = 0) and not (StopSearch) do
begin
if Found.Name[1] <> '.' then
begin
if (found.attr and faDirectory = faDirectory) then
dirs.add(dir + found.name) //加入到目录列表
else
if POS(UpperCase(Ext), UpperCase(found.name)) > 0 then
files.add(dir + found.name);
end;
finished := findnext(found);
end;
findclose(found);
if not StopSearch then
for i := 0 to dirs.count - 1 do
searchfileext(Dirs, Ext, Files);
Dirs.Free;
end;
//装载插件
procedure TFrmMain.loadPlugins;
var
files: tstrings; //存放文件查找结果的文件列表
i: integer;
MyPlugin: TMyPlugin; //存放插件信息的自定义的变量
NewMenu: TMenuItem;
GetCaption: TGetCaption; //获取插件标题的过程引用
begin
//文件列表
files := tstringlist.Create;
//建立指针列表
Plugins := tlist.Create;
//查找当前目录的子目录plugins下扩展名为.dll的文件,并存于 "files 文件列表"中
SearchFileExt(Extractfilepath(application.ExeName) + 'Plugins/', '.dll', files);
//从文件列表中加载找到的DLL
for i := 0 to files.Count - 1 do
begin
myPlugin := TMyPlugin.Create;
myPlugin.Address := loadlibrary(pchar(files)); //装载DLL,返回句柄
if myplugin.Address = 0 then
showmessage('加载' + files + '失败!')
else begin
try
@GetCaption := GetProcAddress(myPlugin.Address, 'GetCaption');
myPlugin.Caption := GetCaption(application.Handle);
myPlugin.Call := GetProcAddress(myPlugin.Address, 'ShowDLLForm');
Plugins.Add(myPlugin);
//创建菜单,并将菜单标题OnClick事件赋值
NewMenu := TMenuItem.Create(self);
NewMenu.Caption := myplugin.Caption;
newmenu.OnClick := PluginsClick;
NewMenu.Tag := i;
plugins1.Add(newMenu);
except
showmessage('初始化失败!');
raise;
end;
end;
end;
files.Free;
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
self.LoadPlugins;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
self.FreePlugins;
end;
procedure TFrmMain.FreePlugins;
var
i: integer;
begin
for i := 0 to plugins.Count - 1 do
begin
//按DLL的句柄释放内存
freelibrary(tmyplugin(plugins).Address);
end;
plugins.free;
end;