既然有这么多的朋友关注PlugIn技术,那我干脆贴出来请各位指教了!
其实我是在一个《工厂模拟运作系统》中采用PlugIn技术的,现在把其中的薪资管理模块的源代码提取出来。
顺便提一下,《工厂》的PlugIn参考了网络上的几篇关于插件的技术文档,在此,向他们表示感谢!
需要说明的是:先建立PMP目录,存放界面代码,PMP中还有PlugIn目录,不用说了,当然是放插件的。
//*******************
以下是界面源代码
//*******************
program PMP;
uses
Forms,
mainUnit in 'mainUnit.pas' {MainForm},
PlugInMagUnit in 'PlugInMagUnit.pas' {PlugInMagForm};
{$R *.RES}
begin
Application.Initialize;
Application.Title:='严力电子';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
//****************
unit mainUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, ComCtrls, ToolWin, ExtCtrls, Buttons, StdCtrls;
type
TMainForm = class(TForm)
MainMenu: TMainMenu;
mnuFile: TMenuItem;
mnuDateLogIn: TMenuItem;
mnuDateDefend: TMenuItem;
mnuSystemConfig: TMenuItem;
mnuPay: TMenuItem;
mnuHelp: TMenuItem;
mnuQuit: TMenuItem;
StatusBar1: TStatusBar;
CoolBar1: TCoolBar;
mnuTotal: TMenuItem;
mnu: TMenuItem;
mnuPlugInMag: TMenuItem;
procedure mnuQuitClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure mnuClick(Sender: TObject);
procedure mnuPlugInMagClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
private
{ Private declarations }
procedure LoadPlugIns;
procedure FreePlugIns;
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses
PlugInMagUnit;
var PlugIns: TList;
type
TPmpPlugIn=class
Name: string;
InsertMenu:string;
OwnerMenu: string;
Version: string;
Description: string;
Address: Integer;
Call: Pointer;
end;
GetNameFunction=function: PChar;
Initalize=procedure(AHandle: THandle);
var
StopSearch: Boolean;
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+'*.dll',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;
{$R *.DFM}
procedure TMainForm.LoadPlugIns;
var
Files: TStrings;
i: Integer;
PmpPlugIn: TPmpPlugIn;
newMenu: TMenuItem;
MenuID: integer;
begin
Files:=TStringList.Create;
PlugIns:=TList.Create;
SearchFileExt(ExtractFilePath(Application.Exename)+'/PlugIn/','.dll',Files);
//edit1.Text:=inttostr(files.count);
for i:=0 to Files.Count-1 do
begin
try
PmpPlugIn:=TPmpPlugIn.Create;
PmpPlugIn.Address:=LoadLibrary(Pchar(Files));
PmpPlugIn.Name:=GetNameFunction(GetProcAddress(PmpPlugIn.Address,'GetName'));
PmpPlugIn.InsertMenu:=GetNameFunction(GetProcAddress(PmpPlugIn.Address,'GetInsertMenu'));
PmpPlugIn.OwnerMenu:=GetNameFunction(GetProcAddress(PmpPlugIn.Address,'GetOwnerMenu'));
PmpPlugIn.Version:=GetNameFunction(GetProcAddress(PmpPlugIn.Address,'GetVersion'));
PmpPlugIn.Description:=GetNameFunction(GetProcAddress(PmpPlugIn.Address,'GetDescription'));
PmpPlugIn.Call:=GetProcAddress(PmpPlugIn.Address,'Initalize');
PlugIns.Add(PmpPlugIn);
NewMenu:=TMenuItem.Create(self);
NewMenu.Caption:=PmpPlugIn.OwnerMenu;
NewMenu.OnClick:=mnuClick;
NewMenu.Tag:=i;
for MenuId:=0 to mainmenu.Items.Count-1 do
if mainmenu.Items[menuID].Name=PmpPlugIn.InsertMenu then
mainmenu.Items[menuID].Add(NewMenu);
//=====================================
PlugInMagForm.StringGrid1.RowCount:=PlugInMagForm.StringGrid1.RowCount+1;
PlugInMagForm.StringGrid1.Cells[0,i+1]:=PmpPlugIn.Name;
PlugInMagForm.StringGrid1.Cells[1,i+1]:=PmpPlugIn.Version;
PlugInMagForm.StringGrid1.Cells[2,i+1]:=PmpPlugIn.Description;
except
//on EAccessViolation do messagedlg('加载无效插件',mterror,[mbOK],0);
end;
end;
Files.Free;
end;
procedure TMainForm.FreePlugIns;
var
i: Integer;
begin
for i:=0 to PlugIns.Count-1 do
begin
FreeLibrary(TPmpPlugIn(PlugIns).Address);
end;
end;
procedure TMainForm.mnuQuitClick(Sender: TObject);
begin
close;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
PlugInMagForm:=TPlugInMagForm.Create(self);
PlugInMagForm.stringgrid1.Cols[0].Text:='插件名称';
PlugInMagForm.stringgrid1.Cols[1].Text:='版本';
PlugInMagForm.stringgrid1.Cols[2].Text:='功能说明';
//==============================
LoadPlugIns;
//=================
end;
procedure TMainForm.mnuClick(Sender: TObject);
begin
Initalize(TPmpPlugIn(PlugIns[TMenuItem(Sender).Tag]).Call)(Application.Handle);
end;
procedure TMainForm.mnuPlugInMagClick(Sender: TObject);
begin
PlugInMagForm.ShowModal;
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
freeplugins;
end;
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if application.MessageBox('你确定要退出系统吗?','退出系统',MB_ICONQUESTION+MB_YESNO)=IDYES then
CanClose:=true
else CanClose:=false;
end;
end.
//************************
unit PlugInMagUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, Grids, DBGrids;
type
TPlugInMagForm = class(TForm)
BitBtn1: TBitBtn;
StringGrid1: TStringGrid;
private
{ Private declarations }
public
{ Public declarations }
end;
var
PlugInMagForm: TPlugInMagForm;
implementation
{$R *.DFM}
end.
//*********************
以下是插件模板
//*********************
library temptle;
uses
SysUtils,
Classes,
Windows,
Messages,
Forms,
TemptleUnit in 'TemptleUnit.pas' {TemptleForm};
function GetName: Pchar; far;
begin
Result := '模板';
end;
function GetInsertMenu: PChar;far;
begin
Result:='mnuHelp';
end;
function GetOwnerMenu: PChar;far;
begin
Result:='模板';
end;
function GetVersion: PChar;far;
begin
Result:='V1.00';
end;
function GetDescription: PChar;far;
begin
Result:='插件模板';
end;
procedure Initalize(AppHandle: THandle); far;
begin
try
Application.Handle:=AppHandle;
TemptleForm:=TTemptleForm.Create(application);
TemptleForm.ShowModal;
except
end;
end;
exports
GetName,GetInsertMenu,GetOwnerMenu,GetVersion,GetDescription,Initalize;
begin
end.
//*****************
unit TemptleUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TTemptleForm = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
TemptleForm: TTemptleForm;
implementation
{$R *.DFM}
end.
//***********************
以上在Delphi5.0中编译成功,不完善的地方,还请各位网友指教,我的Email: sunrace2000@163.com
蒋卫军
2001/5/18