Объектно-ориентированное программирование Инкапсуляция Полиморфизм Библиотека визуальных компонентов Кроссплатформенное программирование Визуальные стили Примеры скриптовАрхитектура приложений баз данных ввод/вывод

Коды ошибок в исключительных ситуациях

Если ваше приложение уже готовится к продаже, если вы планируете его техническую поддержку, то пора задуматься о присвоении числовых кодов ошибкам, возникающим в нем. Сообщение типа "Exception EZeroDivide in module MyNiceProgram at addr $0781BABO" годится для разработчика, пользователя же оно повергнет в полный ступор. Если он позвонит в вашу службу техподдержки, то, скорее всего, не сможет ничего объяснить. Гораздо грамотнее дать ему уже "разжеванную" информацию и, в том числе, числовой код.

Один из путей решения этой проблемы — размещение сообщений об ошибках в ресурсах программы. Если же вы еще делаете и несколько национальных версий программы на разных языках, то этот путь — единственный.

"Классический" способ поместить текст в файл ресурсов — 3-этапный:

1. Создается исходный файл ресурсов с расширением гс, в который помещаются необходимые строки с нужными номерами.

2. Файл обрабатывается компилятором ресурсов brcc32.exe (находится в папке bin в структуре папок Delphi). На выходе образуется одноименный файл с расширением res.

3. Файл включается в программу указанием директивы $R, например

{$R mystrings.res}.

Чтобы совместно использовать константы-номера ошибок в файле ресурсов и в коде на Delphi, вынесем их в отдельный включаемый файл с расширением inc:

const

IOError = 1000;

 FileOpenError = IOError + 1; 

FileSaveError = IOError + 2; 

InternetError = 2000;

NoConnecticnError = InternetError + 1; 

ConnectionAbortedError = InternetError + 2;

Взглянув на файл, вы увидите, что ошибки в нем сгруппированы по категориям. Советуем вам поступить так же, разделив константы категорий промежутком в 1000 или даже 10 000.

Сам файл ресурсов может выглядеть так:

#include "strids.inc" STRINGTABLE

{

FileOpenError, "File Open Error"

FileSaveError, "File Save Error"

NoConnectionError, "No Connection"

ConnectionAbortedError, "Connection Aborted"

}

"Вытащить" строку из ресурсов можно несколькими способами, но самый простой из них — просто по числовому идентификатору, переданному в функцию Loadstr (модуль SysUtils). Код

ShowMessage(LoadStr(NoConnectionError) ) ;

покажет сообщение "NO connection".

Если же строка используется при возбуждении ИС, то место идентификатору—в перекрываемом конструкторе Exception.createRes, один из вариантов которого работает подобно функции Loadstr:

if FileOpent'c:\myfile.txt", fmOpenRead) = INVALID_HANDLE_VALUE then 

raise EMyException.CreateRes(FileOpenError) ;

Таким образом, решена половина проблемы: возможным исключительным ситуациям присвоены номера, им в соответствие поставлен текст. Теперь о второй половине — как в обработчике ИС этот номер использовать.

Ясно, что нужно объявить свой класс ИС, включающий в себя свойство-код

ошибки.

EExceptionWithCode = class(Exception)

 private

 FErrCode : Integer;

public

constructor CreateResCode(ResStringRec: PResStringRec);

property ErrCode: Integer read FErrCode write FErrCode;

 end;

Тогда любой обработчик сможет к нему обратиться:

if E is EExceptionWithCode then

ShowMessage('Error code: ' + IntToStr(EExceptionWithCode(E).ErrCode) +

#13*10

+ 'Error text: ' + E.Message);

Присвоить свойству ErrCode значение можно двумя способами:

1. Добавить к классу ИС еще один конструктор, содержащий код в качестве дополнительного параметра:

constructor EExceptionWithCode.CreateResCode(Ident: Integer); 

begin

FErrCode := Ident;

inherited CreateRes(Ident);

 end;

2. Присвоить значение свойства в промежутке между созданием объекта ИС и его возбуждением:

var E: EExceptionWithCode; begin

E := EExceptionWithCode.CreateRes(NoConnectionError);

E.ErrCode := NoConnectionError;

Raise E;

 end;

Вот, казалось бы, последний штрих. Но как быть тем, кто заранее не заготовил файл ресурсов, а работает со строками, описанными в PAS-файлах? Если вы используете оператор resourcestring, то помочь вам можно.

Начнем с рассмотрения ключевого слова resourcestring. Вслед за ним описываются текстовые константы. Но, в отличие от ключевого слова const, эти константы размещаются не в сегменте данных программы, а в ресурсах, и подгружаются оттуда по мере необходимости. Каждая такая константа воспринимается и обрабатывается как обычная строка. Но за каждой из них на самом деле стоит такая структура:

PResStringRec = ^TResStringRec;

 TResStringRec = packed record 

Module: ^Cardinal;

 Identifier: Integer;

 end;

Если вы еще раз посмотрите на список конструкторов объекта Exception, вы увидите, что те из них, которые работают с ресурсами, имеют перегружаемую версию с параметром типа pResstringRec. Вы угадали правильно: они — для строк из resourcestring. А взглянув на приведенную выше структуру, вы увидите в ней поле identifier. Это то, что нам надо.

Чтобы у программиста, пользующегося resourcestring, голова не болела об уникальных идентификаторах ресурсных строк, среда Delphi берет на себя заботу об этом. Номера назначаются компилятором, начиная от 65 535 (SmallInt (-D) и ниже (если рассматривать номер как тип (SmallInt, то выше): 65 534, 65 533 и т. п. Сначала в этом списке идут несколько сотен resourcestring-констант, описанных в VCL (из модулей, чье имя заканчивается на const или consts: sysconst, DBConsts и т. п.). Затем очередь доходит до пользовательских констант (рис. 3.3).

С одной стороны, отсутствие лишних забот — это большой плюс; с другой стороны, разработчик не может задать строкам те номера, какие хочет.

Все остальное почти ничем не отличается от работы с "самодельными" ресурсами. Так выглядит перегружаемая версия конструктора нашего объекта EExceptionWithCode:

constructor EExceptionWithCode.CreateResCode(ResStringRec:

PResStringRec);

begin

FErrCode := ResStringRec^.Identifier;

inherited CreateRes(ResStringRec); 

end;

А так — возбуждение самой ИС:

resourcestring sErrorl = 'Error  1';

Raise EExceptionWithCode.CreateResCode

(PResStringRec(@sErrorl));

 Результат обработки показан на рис. 3.3.

Рис. 3.3. Результат обработки ИС типа EExceptionWithCode

  От Delphi 4 к Delphi 5 Даже если вы не знаете английского языка и не изучали основ программирования, Delphi поможет вам. В процессе работы, называя английские слова вначале на китайский лад, вы не нанесете себе вреда. Главное во время написания программного кода соблюдать правописание, иначе получите сообщение об ошибке. Пишите без ошибок. Если вы решились принять участие в увлекательном процессе самостоятельного обучения для создания сотвенных программ с использованием Delphi, вы сделали правильный выбор. Надеюсь, что предложенный материал с примерами написания отдельных фрагментов программ окажет вам неоценимую помощь.

Пределы Интегралы Вычисление двойного интеграла Изменить порядок интегрирования Объектно-ориентированное программирование Архитектура приложений баз данных Примеры скриптов Высшая математика