zoukankan      html  css  js  c++  java
  • Delphi捕捉DLL执行所抛出的异常。

    先来说一下我如何写我的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-----------------------登录窗体相关-------------------------}

    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的过程,我这里是直接传递对象指针进来。这个对象的定义在下面的代码中:

    代码
    unit Parameter_Object;
    {
    调用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.

    这样做的好处是不用那么多参数出现,也方便动态的调用方式。

    还有一个不太重要的单元:

    unit pub_Event;

    interface
    uses
      SysUtils;

    type
      
    //点击登录按钮时触发外部检测帐号与密码是否正确
      TLoginClickEvent 
    = procedure(UserName, UserPW: stringof object;

    implementation

    end.

    下面是这个登录传递的源码:

    代码
    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, 
    000);
      
    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/

  • 相关阅读:
    IDEA出现There is no configured/running web-servers found! Please, run any web-configuration and hit the Refr
    国内加速访问Github的办法
    Sublime Text3常用插件汇总
    Qt的进度条设置
    Qt的Qss样式
    Qt中的事件
    QT 的信号与槽
    Qt使用QStackedWidget实现堆栈窗口
    Qt 窗口等设置
    Qt入门1---widget、mainwindow和Dialog区别
  • 原文地址:https://www.cnblogs.com/kfarvid/p/1794307.html
Copyright © 2011-2022 走看看