在网上搜索了很多示例,都重复,也不怎么令人满意。
哪位自己做过的?可以发示例给我吗?分数最多给解决问题者,只给一到两个人。email:[email protected]
哪位自己做过的?可以发示例给我吗?分数最多给解决问题者,只给一到两个人。email:[email protected]
解决方案 »
- Dephi 如何制作作何控件????
- 取得sata硬盘序列号的方法和IDE硬盘方法一样吗?
- 请教:使用disconnect方法后,Server端资源没有释放,积累一定数量后Client无法连接的问题
- 怎样使点击DBNavigator的Delete按钮时显示中文对话框
- procedure Tform.FormKeyPress(Sender: TObject; var Key: Char);
- QQ即时通开发讨论(UDP协议)~~~!
- 98下用D5写的程序在2000下运行为何有些字体的位置走样?
- 又一个白给分的问题!
- 我的一个表中有一个字段是DATE型的! 现在用SQL想来实现查询!!!怎么写~!~!
- 那里有关于delphi的书,,下载!!!!
- 动态数组和指针操作为什么出错?
- 求一控件
用Delphi制作DLL
一 Dll的制作一般步骤
二 参数传递
三 DLL的初始化和退出清理[如果需要初始化和退出清理]
四 全局变量的使用
五 调用静态载入
六 调用动态载入
七 在DLL建立一个TForM
八 在DLL中建立一个TMDIChildForM
九 示例:
十 Delphi制作的Dll与其他语言的混合编程中常遇问题:
十一 相关资料一 Dll的制作一般分为以下几步:
1 在一个DLL工程里写一个过程或函数
2 写一个Exports关键字,在其下写过程的名称。不用写参数和调用后缀。
二 参数传递
1 参数类型最好与window C++的参数类型一致。不要用DELPHI的数据类型。
2 最好有返回值[即使是一个过程],来报出调用成功或失败,或状态。成功或失败的返回值最好为1[成功]或0[失败].一句话,与windows c++兼容。
3 用stdcall声明后缀。
4 最好大小写敏感。
5 无须用far调用后缀,那只是为了与windows 16位程序兼容。三 DLL的初始化和退出清理[如果需要初始化和退出清理]
1 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);
2 如Form上有TdcomConnection组件,就Uses Activex,在初始化时写一句CoInitialize (nil);
3 在退出时一定保证DcomConnection.Connected := False,并且数据集已关闭。否则报地址错。四 全局变量的使用
在widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。虽然DLL在内存中是一份,但变量是在各进程的地址空间中,因此你不能借助dll的全局变量来达到两个应用程序间的数据传递,除非你用内存映像文件。五 调用静态载入
1 客户端函数声名:
1)大小写敏感。
2)与DLL中的声明一样。
如: showform(form:Tform);Far;external'yproject_dll.dll';
3)调用时传过去的参数类型最好也与windows c++一样。
4)调用时DLL必须在windows搜索路径中,顺序是:当前目录;Path路径;windows;widows\system;windows\ssystem32;六 调用动态载入
1 建立一种过程类型[如果你对过程类型的变量只是一个指针的本质清楚的话,你就知道是怎么回事了]。如:
type
mypointer=procedure(form:Tform);Far;external;
var
Hinst:Thandle;
showform:mypointer;
begin
Hinst:=loadlibrary('yproject_dll');//Load一个Dll,按文件名找。
showform:=getprocaddress(Hinst,'showform');//按函数名找,大小写敏感。如果你知道自动化对象的本质就清楚了。
showform(application.mainform);//找到函数入口指针就调用。
Freelibrary(Hinst);
end;七 在DLL建立一个TForM
1 把你的Form Uses到Dll中,你的Form用到的关联的单元也要Uses进来[这是最麻烦的一点,因为你的Form或许Uses了许多特殊的单元或函数]
2 传递一个Application参数,用它建立Form.八 在DLL中建立一个TMDIChildForM
1 Dll中的MDIForm.FormStyle不用为fmMDIChild.
2 在CreateForm后写以下两句:
function ShowForm(mainForm:TForm):integer;stdcall
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);//先把dll的MainForm句柄保存起来,也无须释放,只不过是替换一下
ptr^:=LongInt(mainForm);//用主调程序的mainForm替换DLL的MainForm。MainForm是特殊的WINDOW,它专门管理Application中的Forms资源.
//为什么不直接Application.MainForm := mainForm,因为Application.MainForm是只读属性
Form1:=TForm1.Create(mainForm);//用参数建立
end;
备注:参数是主调程序的Application.MainForm九 示例:
DLL源代码:
library Project2;uses
SysUtils,
Classes,
Dialogs,
Forms,
Unit2 in 'Unit2.pas' {Form2};{$R *.RES}
var
ccc: Pchar;procedure OpenForm(mainForm:TForm);stdcall;
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);
ptr^:=LongInt(mainForm);
Form1:=TForm1.Create(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 Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}
procedure OpenForm(mainForm:TForm);stdcall;External'project2.dll';
procedure ShowCCC;stdcall;External'project2.dll';
procedure InputCCC(Text: Pchar);stdcall;External'project2.dll';procedure TForm1.Button1Click(Sender: TObject);
var
Text: Pchar;
begin
Text := Pchar(Edit1.Text);
// OpenForm(Application.MainForm);//为了调MDICHILD
InputCCC(Text);//为了实验DLL中的全局变量是否在各个应用程序间共享
end;procedure TForm1.Button2Click(Sender: TObject);
begin
ShowCCC;//这里表明WINDOWS 32位应用程序DLL中的全局变量也是在应用程序地址空间中,16位应用程序或许不同,没有做实验。
end;十 Delphi制作的Dll与其他语言的混合编程中常遇问题:
1 与PowerBuilder混合编程
在定义不定长动态数组方面在函数退出清理堆栈时老出现不可重现的地址错,原因未明,大概与PB的编译器原理有关,即使PB编译成二进制代码也如此。
在TYPE下面定义一个函数对象,包含你要动态调用的DLL里面的参数和返回值procedure TForm1.Button2Click(Sender: TObject);
var
LibH:THandle;
ShowRep:TShowRepXml; //声明的函数变量
begin
t1.SaveToFile('F:\xml²âÊÔ\aaa.xml');
LibH:= LoadLibrary('E:\GetReport\GetRep.dll'); //获得库的指针
try
if Libh = 0 then
begin
ShowMessage('tuichu');
Exit;
end;
@ShowRep:= GetProcAddress(LibH,'ShowRepXml'); //取得要执行的函数,ShowRepXml是发布的函数名
if not (@ShowRep = nil) then
begin
ShowRep(Application.Handle,'e:\Patients.xml','234');
end;
finally
FreeLibrary(LibH);
end;
end;
再不懂我也就没办法了。
var
yourpro:Tyourpro;
使用:
Phandl:=loadlibrary('your_dll.dll');//Load一个Dll,按文件名找。
@yourpro:=getprocaddress(Phandl,'yourpro');//按函数名找,
Tyourpro(yourpro);//找到函数入口指针就调用。
Freelibrary(Phandl);
[ok]最好用try ..finally..end
YouDll=procedure(xobject:TObject);external;
var
Hinst:Thandle;
youpointer:pointer;
begin
Hinst:=loadlibrary('youdll.dll');
@youpointer:=getprocaddress(Hinst,'showform');
if youpointer<>0 then
begin
end;
Freelibrary(Hinst);
end;
大概是这样,没有环境,不能试。
楼上的这部分,我也类似地做过,
LibH:= LoadLibrary('E:\GetReport\GetRep.dll'); //获得库的指针
try
if Libh = 0 then
begin
ShowMessage('tuichu');
Exit;
end;
@ShowRep:= GetProcAddress(LibH,'ShowRepXml'); //取得要执行的函数,ShowRepXml是发布的函数名
if not (@ShowRep = nil) then
begin
ShowRep(Application.Handle,'e:\Patients.xml','234');
end;
finally
FreeLibrary(LibH);
end;为什么执行到
if not (@ShowRep = nil) then
begin
ShowRep(Application.Handle,'e:\Patients.xml','234');
end;
的时候,我的程序总是不执行 ShowRep(Application.Handle,'e:\Patients.xml','234');
是什么原因?
///////////////////////////////////////////////
LibH:= LoadLibrary('E:\GetReport\GetRep.dll'); //获得库的指针
try
if Libh = 0 then
begin
ShowMessage('tuichu');
Exit;
end;
@ShowRep:= GetProcAddress(LibH,'ShowRepXml'); //取得要执行的函数,ShowRepXml是发布的函数名
if not (@ShowRep = nil) then
begin
ShowRep(Application.Handle,'e:\Patients.xml','234');
end;
finally
FreeLibrary(LibH);
end;
/////////////////////////////////////////////////
为什么执行到
////////////////////
if not (@ShowRep = nil) then
begin
ShowRep(Application.Handle,'e:\Patients.xml','234');
end;
/////////////////////
的时候,我的程序总是不执行
////////////
ShowRep(Application.Handle,'e:\Patients.xml','234');
////////////////
是什么原因?
一、DLL的窗口。library DLLpassPro;{ 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,
DLLPass in 'DLLPass.pas' {Form1};{$R *.res}
exports
OutDll,
CloseDLLWindows,
TestDLLRe;
begin
end.
//这是我以前写的写的,好久了,原来发来的。EXPORTS有三个:
OUTDLL是窗子的建立。
CLOSE是关闭和句柄释放
TESTDLLRE是回调。这个是一个简单的回显,不过你可以作为参考unit DLLPass;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls;type
Tfunct = function (iCo: integer):LongInt;stdcall;
UserMessage = packed record
UseName: string[80];
UsePass: string[11];
end;
TForm1 = class(TForm)
Label1: TLabel;
ComboBox1: TComboBox;
Label2: TLabel;
Edit1: TEdit;
Button1: TButton;
Label3: TLabel;
Timer1: TTimer;
Label4: TLabel;
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
UserMesRec: array of UserMessage; //住处数组
UserString: TStrings; //相关的唯一信息
UserCurTime: integer; //记时变量
bResult: Boolean;
bCheck: Boolean; procedure ReadPassFile(); { Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
FormInt: LongInt; //用来存贮窗口信息
iCountP: Integer; function OutDll(AHandle: THandle):Longint;stdcall;
procedure CloseDLLWindows(AFormRef: Longint);stdcall;
procedure TestDLLRe(iCount: integer; Aproc: TFarProc);stdcall;
implementation
{$R *.dfm}function OutDll(AHandle: THandle):Longint;
Var
Form1: TForm1;
begin Application.Handle := AHandle;
Form1 := TForm1.Create(Application);
FormInt := LongInt(Form1);
//创建窗口
Form1.Timer1.Enabled := True;
//开始记数
Form1.ShowModal;
Form1.ReadPassFile;
if Form1.bResult = False then Result := 0
else
Result := FormInt;
Form1.Free;end;procedure CloseDLLWindows(AFormRef: Longint);
begin
if AFormRef > 0 then
TForm1(AFormRef).Release; //销毁窗口
end;
procedure TestDLLRe(iCount: integer; Aproc: TFarProc);
var
i: integer;
begin
for i := 0 to 99 do
begin
inc(iCountP); sleep(100); if Aproc <> nil then
Tfunct(Aproc)(iCountP);
end;
end;
procedure TForm1.ReadPassFile;
var
strEdit: string;
begin
strEdit := Edit1.Text;
bResult := False;
case ComboBox1.ItemIndex of
0:
if strEdit = '7411272'then bResult := True;
1 :
if strEdit = 'Police' then bResult := True;
2:
if strEdit = 'admi' then bResult := True;
3:
if strEdit = '123456' then bResult := True;
else
// showmessage('你输入的用户名有误!请联系管理人员!');
end;
end;procedure TForm1.Timer1Timer(Sender: TObject);
begin
inc (UserCurTime);
if UserCurTime >= 10 then
begin
UserCurTime := 0 ;
close;
end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
strEdit :string;
begin
ReadPassFile;
if bResult = False then
begin
Form1.Free;
Close;
MessageDlg ('密码或用户名出错!', mtConfirmation , [mbYes] , 0);
end;
Label3.Font.Color := clBlue;
Label3.Caption := '密码正确,正在调入数据库,请稍候.....';
UserCurTime := 8;end;procedure TForm1.FormCreate(Sender: TObject);
begin
ComboBox1.Text := ComboBox1.Items[3];
ComboBox1.ItemIndex := 3;
end;end.
//作用就是对输入的东西进行对比了。很简单的,慢慢看看。下面是调用:unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
ProgressBar1: TProgressBar;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
function OutDll(AHandle: THandle):Longint;stdcall;external 'F:\zhanjiajun\book\程序资料\Delphi Code\校验码\Bin\DLLpassPro.dll'
procedure CloseDLLWindows(AFormRef: Longint);stdcall;external 'F:\zhanjiajun\book\程序资料\Delphi Code\校验码\Bin\DLLpassPro.dll'
function FrmGetDLL(iCon: integer):Longint;stdcall;
procedure TestDLLRe(iCount: integer; Aproc: TFarProc);stdcall; external 'F:\zhanjiajun\book\程序资料\Delphi Code\校验码\Bin\DLLpassPro.dll'
//静态的。你可以改的。implementation
{$R *.dfm}
function FrmGetDLL(iCon: integer):Longint;
begin
Form1.ProgressBar1.Position := iCon;
end;procedure TForm1.Button1Click(Sender: TObject);
var
test: Longint;
begin test := OutDll(Application.Handle);
showmessage(IntToStr(test));end;procedure TForm1.Button2Click(Sender: TObject);
begin
TestDLLRe(123, @FrmGetDLL);//这个是回调。
end;end.
还不清楚就加我QQ:52258388
Google上N多的