M Y D E L P H I 7 . R U Самоучитель программирования  
 
  • Главная
  •  

     

    Использование исключительных ситуаций

    Если произошла ошибка и возбуждена исключительная ситуация, то она будет обрабатываться по такому алгоритму:

    1. Если ситуация возникла внутри блока try..except, то там она и будет обработана. Если ИС "продвинута" дальше при помощи оператора raise, а также если она возникла в блоке try. .finally, обработка продолжается.

    2. Если программистом определен обработчик события Application.onException, то он получит управление. Обработчик объявлен следующим образом:

    TExceptionEvent = procedure (Sender: TObject; E: Exception) of object;

    3. Если программист никак не определил реакцию на ИС, то будет вызван стандартный метод showException, который сообщит о классе и месте возникновения исключительной ситуации.

    Пункты 2 и 3 реализуются в методе TAppiication.HandieException. Собственно, выглядят они следующим образом:

    if not (ExceptObject is EAbort) then

     if Assigned(FOnException) then

      FOnException(Sender, Exception(ExceptObject))

    else

      ShcwExceptior. (Exception(ExceptObject));

    Обработчик onExceptiоn нужен, если требуется выполнять одно и то же действие в любой исключительной ситуации, возникшей в вашем приложении. К примеру, назвать себя, указать координаты для обращения или предупредить, что это еще бета-версия.

    program Project!;

    uses 

    Forms,

    SysUtils, //добавлено вручную — там описан класс Exception Dialogs, 

    Unitl in 'Unitl.pas' {Forml};

    {$R *.RES}

    type

    TExceptClass = class 

    public

     procedure GlobalExceptionHandler(Sender: TObject; E:Exception);

    end;

    procedure TExceptClass.GlobalExceptionHandler(Sender: TObject;

    E:Exception); 

    begin

    ShowMessage('Произошла исключительная ситуация ' + E.ClassName

    + ': ' + E.Message

    + #13#10'Свяжитесь с разработчиками по тел. 222-33-44');

    end; 

    begin

    with TExceptClass.Create do

     begin

    Application.OnException := GlobalExceptionHandler;

    Application.Initialize;

    Application.CreateFormfTForml, Forml);

    Application.Run;

    Free; 

    end;

      end.

    Здесь класс TExceptClass создается только для того, чтобы быть носителем метода GiobaiException. Обработчик любого события — метод, и он должен относиться к какому-либо объекту. Поскольку он здесь нужен еще до инициализации форм приложения и других его составных частей, то и объект класса TExceptClass создается первым. Теперь пользователь знает, что благодарить за неожиданности нужно по указанному в сообщении об ошибке телефону разработчиков.

    Примечание 

    Есть и более простой способ присвоить обработчик событию Application.OnException. Для этого поместите на форму компонент типа TApplicationEvents (страница Additional Палитры компонентов), роль которого — предоставление "визуального" доступа к свойствам невизуального объекта TApplication. Среди его событий есть и OnException.

    Но как "пощупать" переданный при исключительной ситуации объект? Обычная конструкция

    on EExceptionType do...

    указывает на класс объекта, но не на конкретный экземпляр. Если во время обработки требуется доступ к свойствам этого экземпляра, его нужно поименовать внутри on..do, указав перед именем класса некий идентификатор:

    on EZD: EZeroDivide do EZD.Message := 'Деление на ноль!';

    Здесь возникшее исключение выступает под именем EZD. Можно изменить его свойства и отправить дальше:

    var APtr : Pointer;

    Forml : TForm; 

    try

    APtr := Forml;

    with TObject(APtr) as TBitmap do; 

    except

    on EZD: EInvalidCast do EZD.Message :=. EZD.Message + 'xa-xa!';

    Raise;{ теперь обработка будет сделана в другом месте }

     end;

    Но как поименовать исключительную ситуацию, не попавшую ни в одну из директив on..do? Или, может быть, в вашем обработчике вообще нет on. .do, а поработать с объектом надо? Описанный выше путь здесь не подходит. Для этих случаев есть пара системных функций Exceptobject и ExceptAddr. К сожалению, эти функции инициализируются только внутри конструкции try..except; в try..finally работать с объектом— исключительной ситуацией не представляется возможным.