一 Dll的制作一般分为以下几步
在一个DLL工程里写一个过程或函数
写一个Exports关键字在其下写过程的名称不用写参数和调用后缀
二 参数传递
参数类型最好与window C++的参数类型一致不要用DELPHI的数据类型
最好有返回值[即使是一个过程]来报出调用成功或失败或状态成功或失败的返回值最好为[成功]或[失败]一句话与windows c++兼容
用stdcall声明后缀
最好大小写敏感
无须用far调用后缀那只是为了与windows 位程序兼容
三 DLL的初始化和退出清理[如果需要初始化和退出清理
DLLProc[SysUtils单元的一个Pointer]是DLL的入口在此你可用你的函数替换了它的入口但你的函数必须符合以下要求[其实就是一个回调函数]如下
procedure DllEnterPoint(dwReason: DWORD);far;stdcall;
dwReason参数有四种类型
DLL_PROCESS_ATTACH:进程进入时
DLL_PROCESS_DETACH进程退出时
DLL_THREAD_ATTACH 线程进入时
DLL_THREAD_DETACH 线程退出时
在初始化部分写:
DLLProc := @DLLEnterPoint;
DllEnterPoint(DLL_PROCESS_ATTACH);
如Form上有TdcomConnection组件就Uses Activex在初始化时写一句CoInitialize (nil);
在退出时一定保证DcomConnectionConnected := False并且数据集已关闭否则报地址错
四 全局变量的使用
在widnows 位程序中两个应用程序的地址空间是相互没有联系的虽然DLL在内存中是一份但变量是在各进程的地址空间中因此你不能借助dll的全局变量来达到两个应用程序间的数据传递除非你用内存映像文件
五 调用静态载入
客户端函数声名:
)大小写敏感
)与DLL中的声明一样
如 showform(form:Tform);Far;externalyproject_dlldll;
)调用时传过去的参数类型最好也与windows c++一样
)调用时DLL必须在windows搜索路径中顺序是当前目录Path路径windows;widows\system;windows\ssystem;
六 调用动态载入
建立一种过程类型[如果你对过程类型的变量只是一个指针的本质清楚的话你就知道是怎么回事了]如
type
mypointer=procedure(form:Tform);Far;external;
var
Hinst:Thandle;
showform:mypointer;
begin
Hinst:=loadlibrary(yproject_dll);//Load一个Dll按文件名找
showform:=getprocaddress(Hinstshowform);//按函数名找大小写敏感如果你知道自动化对象的本质就清楚了
showform(applicationmainform);//找到函数入口指针就调用
Freelibrary(Hinst);
end;
七 在DLL建立一个TForM
把你的Form Uses到Dll中你的Form用到的关联的单元也要Uses进来[这是最麻烦的一点因为你的Form或许Uses了许多特殊的单元或函数]
传递一个Application参数用它建立Form
八 在DLL中建立一个TMDIChildForM
Dll中的MDIFormFormStyle不用为fmMDIChild
在CreateForm后写以下两句
function ShowForm(mainForm:TForm):integer;stdcall
var
Form: TForm;
ptr:PLongInt;
begin
ptr:=@(ApplicationMainForm);//先把dll的MainForm句柄保存起来也无须释放只不过是替换一下
ptr^:=LongInt(mainForm);//用主调程序的mainForm替换DLL的MainFormMainForm是特殊的WINDOW它专门管理Application中的Forms资源
//为什么不直接ApplicationMainForm := mainForm因为ApplicationMainForm是只读属性
Form:=TFormCreate(mainForm);//用参数建立
end;
备注参数是主调程序的ApplicationMainForm
九 示例
DLL源代码
library Project;
uses
SysUtils
Classes
Dialogs
Forms
Unit in Unitpas {Form};
{$R *RES}
var
ccc: Pchar;
procedure OpenForm(mainForm:TForm);stdcall;
var
Form: TForm;
ptr:PLongInt;
begin
ptr:=@(ApplicationMainForm);
ptr^:=LongInt(mainForm);
Form:=TFormCreate(mainForm);
end;
procedure InputCCC(Text: Pchar);stdcall;
begin
ccc := Text;
end;
procedure ShowCCC;stdcall;
begin
ShowMessage(String(ccc));
end;
exports
OpenForm;
InputCCC
ShowCCC;
begin
end
调用方源代码
unit Unit;
interface
uses
Windows Messages SysUtils Classes Graphics Controls Forms Dialogs
StdCtrls;
type
TForm = class(TForm)
Button: TButton;
Button: TButton;
Edit: TEdit;
procedure ButtonClick(Sender: TObject);
procedure ButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form: TForm;
implementation
{$R *DFM}
procedure OpenForm(mainForm:TForm);stdcall;Externalprojectdll;
procedure ShowCCC;stdcall;Externalprojectdll;
procedure InputCCC(Text: Pchar);stdcall;Externalprojectdll;
procedure TFormButtonClick(Sender: TObject);
var
Text: Pchar;
begin
Text := Pchar(EditText);
// OpenForm(ApplicationMainForm);//为了调MDICHILD
InputCCC(Text);//为了实验DLL中的全局变量是否在各个应用程序间共享
end;
procedure TFormButtonClick(Sender: TObject);
begin
ShowCCC;//这里表明WINDOWS 位应用程序DLL中的全局变量也是在应用程序地址空间中位应用程序或许不同没有做实验
end;