- •Розділ 1. Об’єктно-орієнтоване програмування
- •Тема 1.1. Візуальне програмування.
- •Тема 1.2. Приклади та застосування інкапсуляції, успадкування, поліморфізму.
- •Тема 1.3. Бібліотека візуальних компонентів vcl та її базові класи.
- •1. Клас tWinControl.
- •2. Клас tСustomControl.
- •3. Клас tGraphicControl.
- •Тема 1.4. Обробка виняткових ситуацій.
- •1. Використовування виняткових ситуацій.
- •2. Протоколювання виняткових ситуацій.
- •3. Коди помилок у виняткових ситуаціях.
- •4. Виняткова ситуація eAbort. Функція Assert.
- •Розділ 2. Мова програмування Object Pascal.
- •Тема 2.1. Середовище Delphi.
- •Тема 2.2. Елементи мови Object Pascal.
- •1. Коментарі.
- •2. Логічні вирази.
- •Тема 2.3. Типи даних, процедури та функції.
- •1. Вказівники та динамічна пам'ять. Динамічна пам'ять
- •Вказівники
- •Виділення і звільнення динамічної пам'яті
- •Процедури і функції для роботи з динамічною пам'яттю
- •Тема 2.4. Управляючі структури Object Pascal.
- •Розділ 3. Програмування в середовищі Delphi.
- •Тема 3.1. Застосування списків. Способи запису/читання зі списків.
- •Є списком CheckBox елементів.
- •Тема 3.2. Масиви.
- •1. Пошук мінімального (максимального) елементу масиву.
- •2. Пошук в масиві заданого елементу.
- •Тема 3.3. Робота з файлами.
- •Тема 3.4. Типи даних визначені програмістом.
- •1. Показники.
- •2. Динамічні змінні.
- •Тема 3.5. Графічні програми.
- •1. Бітові образи.
- •2. Мультиплікація.
- •Властивості компоненту Timer
- •Тема 3.6. Приклади застосування анімацій у Delphi.
- •Тема 3.7. Рекурсія.
- •1. Крива Гільберта.
- •2. Пошук шляху.|колії|
- •Значення властивостей компоненту stringGrid1
- •3. Пошук найкоротшого шляху.|колії|
- •Тема 3.8. Компоненти для інтернету. Компонента tSocketConnection
- •Розділ 4. Бази даних.
- •Тема 4.1. Види баз даних. Структура та зв’язки між таблицями. Бази даних
- •Класифікація баз даних
- •Структура бази даних
- •Модель бази даних в Delphi
- •Тема 4.2. Модифікація структури таблиці в bde.
- •1. Зміна структури таблиці.
- •2. Встановлення перевірок правильності даних.
- •3. Завдання вторинних індексів.
- •Тема 4.3. Об’єкти відображення даних бази даних Delphi.
- •1. Класифікація компонентів відображення даних.
- •2. Елемент керування тdbGrid.
- •3. Компонент tdbEdit.
- •4. Компонент tdNavigator.
- •Тема 4.4. Обчислювальні поля і поля підстановки в Delphi.
- •1. Створення поля підстановки (поля синхронного перегляду).
- •2. Обчислювальні поля.
- •Тема 4.5. Компонента tdbEdit.
- •Тема 4.6. Переміщення по записам таблиці. Набір методів і властивостей tDataSet. Огляд
- •Клас tDataSet
- •Відкриття і закриття DataSet
- •Тема 4.7. Налаштування фільтрів.|
- •Тема 4.8. Приклади застосування пошуку.
- •Тема 4.9. Поєднання різних видів пошуку.
- •Тема 4.10. Типи даних та пошук в діапазоні.
- •Список літератури
2. Протоколювання виняткових ситуацій.
Часто потрібно мати докладний матеріал для аналізу причин виникнення ВС. Розумно було б записувати всі дані про них у файл, щоб потім прогнозувати ситуацію. Такий підхід важливий для програм, які так чи інакше будуть відчужені від розробника: у разі виникнення непередбаченої ситуації це дозволить відповісти на питання "хто винуватий?" і "що робити?". В наступному прикладі запропонований варіант реалізації протоколювання ВС.
const LogName : string = 'с:\appexc.log';
procedure LogException;
var fs: TFileStream; m : word;buf : array[0..511] char;
begin
if FileExists(LogName) then m := fmOpenReadWrite else m := fmCreate;
fs := TFileStream.Create(LogName,m);
fs.Seek(0,soFromEnd);
StrPCopy(Buf,DateTimeToStr(Mow)+' . ');
ExceptionErrorMessage
(ExceptObject,ExceptAddr,@buf[StrLenfbuf)]
SizeOf(Buf)-StrLen(buf));
StrCat(Buf,#13#10);
fs.WriteBuffer (Buf, StrLer. ;buf) ) ;
fs.Free;
end;
procedure TForml.ButtonlClick(Sender: TObject);
var х,у,z: real;
begin
try
try
х:=1.0;у:=0.0;
z := х/у;
except
LogException;
raise;
end;
except
on E:EIntError do ShowMessage('ІntError');
on E:EMathError do ShowMessage('MathError');
end;
end;
Тут задачу запису інформації про ВС вирішує процедура LogException. Вона відкриває файловий потік і пише туди інформацію, що відформатувала за допомогою вже згадуваної функції ExceptionErrorMessage.
Як її параметрів виступають значення функцій Exceptobject і ExceptAddr. До сформованого рядка додається час виникнення ВС. Для кожного блоку коду, що захищається створюються дві вкладені конструкції try. .except. Перша, внутрішня – для вас; в ній ВС протоколюється і просувається далі. Зовнішня – для користувача; саме в ній проводиться аналіз типу ВС і готується повідомлення.
В Object Pascal існує і розширений варіант вживання оператора raise:
raise екземпляр об'єкту типу Exception> [at <адрес>]
Природно, об'єктний тип повинен бути породжений від Exception. Це, що в такому типі нічого не перевизначено, не таке важливо – головне, що в обробнику ІС можна відстежити саме цей тип.
ELoginError = class (Exception);
If LoginAttemptsNo > MaxAttempts then raise ELoginError.Create('Помилка реєстрації користувача');
Конструкція at <адрес> використовується для того, щоб змінити адресу, до якої прив'язується виникла ВС, в межах одного блоку обробки ВС.
3. Коди помилок у виняткових ситуаціях.
Якщо ваш додаток вже готується до продажу, якщо ви плануєте його технічну підтримку, то пора задуматися про привласнення числових кодів
Помилкам, що виникають в ньому. Повідомлення типу "Exception EZeroDivide in module MyNiceProgram at addr $0781BABO" годиться для розробника, користувача ж воно повергне в повний ступор. Якщо він подзвонить у вашу службу техпідтримки, то, швидше за все, не зможе нічого пояснити. Набагато грамотніше дати йому вже "розжовану" інформацію і, у тому числі, числовий код.
Один з шляхів рішення цієї проблеми – розміщення повідомлень про помилки в ресурсах програми. Якщо ж ви ще робите і декілька національних версій програми на різних мовах, то цей шлях – єдиний.
"Класичний" спосіб помістити текст у файл ресурсів – 3-етапний:
1. Створюється початковий файл ресурсів з розширенням res, в який поміщаються необхідні рядки з потрібними номерами.
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'с:\myfile.txt", fmOpenRead) = INVALID HANDLE VALUE then
raise EMyException.CreateRes(FileOpenError) ;
Таким чином, вирішена половина проблеми: можливим винятковим ситуаціям привласнені номери, їм у відповідність поставлений текст. Тепер про другу половину - як в обробнику ІС цей номер використовувати.
Ясно, що потрібно оголосити свій клас ІС, що включає властивість-код помилки.
EExceptionWithCode = class(Exception)
private
ErrCode : 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));
Результат обробки показаний на мал.
Результат обробки ІС типу EExceptionWithCode
