先来说一下我如何写我的Dll文件的。
先看代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
uses
SysUtils,
Classes,
Windows,
Forms,
Parameter_Object,
frm_LoginU in ' ..\公用库单元\frm_LoginU.pas ' { frm_Login } ,
pub_Event in ' ..\公用库单元\pub_Event.pas ' ,
Dll_LIB_ConstU in ' ..\公用库单元\Dll_LIB_ConstU.pas ' ;
var
DLLApp: TApplication;
{ begin-----------------------登录窗体相关------------------------- }
procedure Login( var mLoginParam: TLoginParam); export ;
begin
{ 获取调用窗体的Application,显而易见的功能是 能使你的窗体融合到调用程序中。通过它还能进行很多操作 }
Application : = mLoginParam.App; // 将DLL的Application转为App
if frm_Login = nil then
frm_Login : = Tfrm_Login.Create(mLoginParam.ParentForm);
frm_Login.DoLoginClick : = mLoginParam.DoLogin;
frm_Login.DoErrCatch: = mLoginParam.ErrDo;
frm_Login.E_User.Text: = mLoginParam.OldUser;
frm_Login.ShowModal;
end ;
procedure CloseLogin; export ;
begin
if frm_Login.Showing then
frm_Login.Close;
end ;
{ end-----------------------登录窗体相关------------------------- }
{ 重写Dll入口函数,否则程序会出错 }
procedure DLLUnloadProc(Reason: Integer); register ;
begin
{ DLL取消调用时,发送DLL_PROCESS_DETACH消息,此时将DLL的Application返回为本身 }
if Reason = DLL_PROCESS_DETACH then Application : = DLLApp;
end ;
exports
Login,CloseLogin;
begin
{ 在DLL入口预先储存DLL的Application }
DLLApp : = Application;
{ DllProc:DLL入口函数指针。Delphi定义为 DllProc: TDLLProc; }
{ 在此指向我们自己定义的函数 }
DLLProc : = @DLLUnloadProc;
end .
代码中都有注释了,这个不多说了,说一下Login的过程,我这里是直接传递对象指针进来。这个对象的定义在下面的代码中:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
调用DLL的参数对象类
}
interface
uses
pub_Event,Forms;
type
TDllFormParam = class (TObject)
public
App: TApplication;
ParentForm:TForm;
ErrDo:TExceptionEvent;
constructor CreateByObject( var mApp: TApplication; var mParentForm:TForm;mErrDo:TExceptionEvent);
end ;
TLoginParam = class (TDllFormParam)
public
DoLogin:TLoginClickEvent;
OldUser:String; // 上次登录的用户
constructor CreateByObject( var mApp: TApplication; var mParentForm:TForm;mErrDo:TExceptionEvent;mDoLogin:TLoginClickEvent;mUser: string = '' );
end ;
implementation
{ TLoginParam }
constructor TLoginParam.CreateByObject( var mApp: TApplication;
var mParentForm: TForm;mErrDo:TExceptionEvent; mDoLogin: TLoginClickEvent;mUser: string = '' );
begin
inherited CreateByObject(mApp,mParentForm,mErrDo);
DoLogin: = mDoLogin;
OldUser: = mUser;
end ;
{ TDllFormParam }
constructor TDllFormParam.CreateByObject( var mApp: TApplication;
var mParentForm: TForm;mErrDo:TExceptionEvent);
begin
App: = mApp;
ParentForm: = mParentForm;
ErrDo: = mErrDo;
end ;
end .
这样做的好处是不用那么多参数出现,也方便动态的调用方式。
还有一个不太重要的单元:
interface
uses
SysUtils;
type
// 点击登录按钮时触发外部检测帐号与密码是否正确
TLoginClickEvent = procedure (UserName, UserPW: string ) of object ;
implementation
end .
下面是这个登录传递的源码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, pub_Event;
type
Tfrm_Login = class (TForm)
E_User: TEdit;
E_PassWD: TEdit;
btn_Login: TButton;
btn_Exit: TButton;
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure btn_ExitClick(Sender: TObject);
procedure btn_LoginClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
DoLoginClick: TLoginClickEvent;
DoErrCatch:TExceptionEvent;
end ;
var
frm_Login: Tfrm_Login;
implementation
{ $R *.dfm }
procedure Tfrm_Login.FormKeyPress(Sender: TObject; var Key: Char);
begin
if key = # 13 then
begin
Key : = # 0 ;
Keybd_Event(VK_TAB, 0 , 0 , 0 );
end ;
end ;
procedure Tfrm_Login.btn_ExitClick(Sender: TObject);
begin
self.close;
end ;
procedure Tfrm_Login.btn_LoginClick(Sender: TObject);
begin
if Assigned(DoLoginClick) then
begin
try
DoLoginClick(trim(E_User.Text), Trim(E_PassWD.Text));
except on e:Exception do
DoErrCatch(sender,e);
end ;
end ;
end ;
procedure Tfrm_Login.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action: = caFree;
end ;
end .
全部都出来了,我说下我这个DLL的登录验证窗体的工作方式:把登录的验证方法放在主程序里面,因为,不同时期不同的开发项目,其登录验证方式都不一样,因此独立出主程序里,采用回调的方式来实现。由于登录窗体需要到数据库中去验证帐号和密码,因此,我特意把字段输错,这里所报的异常不会被主程序捕捉到,为何不会被主程序捕捉到?我猜是因为调用这个验证方法是一个DLL,而DLL毕竟不是主程序,因此,其错误消息是不会被主程序所捕捉到的,就算开始的时候把application传到了dll里面去也一样捕捉不到(如果能捕捉到的,请把方法告诉我,我找了很久都没找到相关的资料),在网上找了个资料,网址是:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3660866
根据这个提示,我把异常处理的方法也传进去了,这样,在验证登录方法时出错了,也能调用主程序中的捕捉异常的方法。
原创作品出自努力偷懒,转载请说明文章出处:http://www.cnblogs.com/kfarvid/