先來說一下我如何寫我的Dll文件的,。 先看代碼:
代碼
library pub_form; 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-----------------------登錄窗體相關(guān)-------------------------} procedure Login(var mLoginParam: TLoginParam); export; begin {獲取調(diào)用窗體的Application,,顯而易見的功能是 能使你的窗體融合到調(diào)用程序中,。通過它還能進(jìn)行很多操作} Application := mLoginParam.App; //將DLL的Application轉(zhuǎn)為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-----------------------登錄窗體相關(guān)-------------------------} {重寫Dll入口函數(shù),,否則程序會(huì)出錯(cuò)} procedure DLLUnloadProc(Reason: Integer); register; begin {DLL取消調(diào)用時(shí),,發(fā)送DLL_PROCESS_DETACH消息,,此時(shí)將DLL的Application返回為本身} if Reason = DLL_PROCESS_DETACH then Application := DLLApp; end; exports Login,CloseLogin; begin {在DLL入口預(yù)先儲(chǔ)存DLL的Application} DLLApp := Application; {DllProc:DLL入口函數(shù)指針。Delphi定義為 DllProc: TDLLProc;} {在此指向我們自己定義的函數(shù)} DLLProc := @DLLUnloadProc; end.
代碼中都有注釋了,,這個(gè)不多說了,,說一下Login的過程,我這里是直接傳遞對(duì)象指針進(jìn)來,。這個(gè)對(duì)象的定義在下面的代碼中:
代碼
unit Parameter_Object; { 調(diào)用DLL的參數(shù)對(duì)象類 } 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.
這樣做的好處是不用那么多參數(shù)出現(xiàn),,也方便動(dòng)態(tài)的調(diào)用方式。 還有一個(gè)不太重要的單元:
unit pub_Event; interface uses SysUtils; type //點(diǎn)擊登錄按鈕時(shí)觸發(fā)外部檢測(cè)賬號(hào)與密碼是否正確 TLoginClickEvent = procedure(UserName, UserPW: string) of object; implementation end.
下面是這個(gè)登錄傳遞的源碼:
代碼
unit frm_LoginU; 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.
全部都出來了,,我說下我這個(gè)DLL的登錄驗(yàn)證窗體的工作方式:把登錄的驗(yàn)證方法放在主程序里面,,因?yàn)椋煌瑫r(shí)期不同的開發(fā)項(xiàng)目,,其登錄驗(yàn)證方式都不一樣,,因此獨(dú)立出主程序里,采用回調(diào)的方式來實(shí)現(xiàn),。由于登錄窗體需要到數(shù)據(jù)庫中去驗(yàn)證賬號(hào)和密碼,,因此,我特意把字段輸錯(cuò),,這里所報(bào)的異常不會(huì)被主程序捕捉到,,為何不會(huì)被主程序捕捉到?我猜是因?yàn)檎{(diào)用這個(gè)驗(yàn)證方法是一個(gè)DLL,,而DLL畢竟不是主程序,,因此,其錯(cuò)誤消息是不會(huì)被主程序所捕捉到的,,就算開始的時(shí)候把a(bǔ)pplication傳到了dll里面去也一樣捕捉不到(如果能捕捉到的,,請(qǐng)把方法告訴我,我找了很久都沒找到相關(guān)的資料),,在網(wǎng)上找了個(gè)資料,,網(wǎng)址是: http://www./delphibbs/dispq.asp?lid=3660866 根據(jù)這個(gè)提示,,我把異常處理的方法也傳進(jìn)去了,這樣,,在驗(yàn)證登錄方法時(shí)出錯(cuò)了,,也能調(diào)用主程序中的捕捉異常的方法。 |
|