Текст програми

Після створення форми в вікно редактора коду, в секцію implementation слід помістити опис глобальних констант (розділ const) і змінних (розділ var). Потім можна приступити до створення процедур обробки подій.
Їх в програмі три: обробка події onActivate для стартової форми, обробка події Onclick для командної кнопки Buttoni і процедура обробки події onclick – одна, загальна для перемикачів вибору відповіді.
У лістингу 15.1 наведено повний текст програми.

Лістинг 15.1. Програма тестування
unit test1 _;
interface
uses
SysUtils, WinTypes, WinProcs, Messages,

Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class (TForm) // питання

Label3: TLabel; // альтернативні відповіді

Label1: TLabel; Label2: TLabel;

Label3: TLabel; Label4: TLabel;
// перемикачі вибору відповіді

RadioButton1: TRadioButton;

RadioButton2: TRadioButton;

RadioButton3: TRadioButton;

RadioButton4: TRadioButton;
Image1: TImage; // область виведення ілюстрації

Button1: TButton; // кнопка Ok, Далі
RadioButtonS: TRadioButton; // "службова" кнопка
Panel1: ТPanel;
procedure FormActivate (Sender: TObject);
procedure ButtonlClick (Sender: TObject};
procedure RadioButtonClick (Sender: TObject);

private
{ Private declarations}

public
{ Public declarations}

end;
var
Form1: TForm1; // форма
implementation
const
N_LEV = 4; // чотири рівні оцінки

N_ANS = 4; // чотири варіанти відповідей
var
f: TextFile;
fn: string; // ім'я файлу питань
1evel: array [1..N_LEV] of integer;

// сума, що відповідає рівню

mes: array [1., N_LEV] of string;

// повідомлення, що відповідає рівню
score: array [1..N_ANS] of integer;

// бал за вибір відповіді
summa: integer; // набрано очок
vopros: integer; // номер поточного питання
n_otv: integer; // число варіантів відповіді
otv: integer; // номер обраного відповіді
// висновок початкової інформації про тест

procedure info (var f: TextFile; l: TLabel);

var
s, buf: string; begin
buf: = '';
repeat
readln (f, s); if s [l] <> '.'
then buf: = buf + s + '';

until s [l] = '.'; l.caption: = buf;

end;
// прочитати інформацію про оцінки за тест
Procedure GetLevel (var f: TextFile);
var
i: integer; buf: string;
begin // заповнюємо значення глобальних масивів

i: = l;

repeat
readln (f, buf); if buf [1] <> '.' then begin

mes [i]: = buf; readln (f, level [i]);

i: = i + 1;

end;
until buf [1] = '.';

end;
// масштабування ілюстрації
Procedure ScaleImage (Imagel: TImage);
var
w, h: integer; // максимально допустимі розміри картинки

scaleX: real; // коеф. масштабування по X

scaleY: real; // коеф. масштабування по Y

scale: real; // загальний коеф. масштабування
begin
// обчислити максимально допустимі розміри картинки

w: = Form1.ClientWidth-10;

h: = Form1.ClientHeight
- Form1.Panel1.Height -5
- Form1.Label5.Top
- Form1.Label5.Height - 5;

if Form1.Label1.Caption <> ''
then h: = h-Form1.Label1.Height-5;

if Form1.Label2.Caption <> ''
then h: = h-Form1.Label2.Height-5;

if Forml.Label3.Caption <> ''
then h: = h-Form1.Label3.Height-5;

if Forml.Label4.Caption <>
then h: = h-Form1.Label4.Height-5; // визначити масштаб

if w & gt; Imagel.Picture.Bitmap.Width

then scaleX: = l
else scaleX: = w / Imagel.Picture.Bitmap.Width;

if h > Imagel.Picture.Bitmap.Height

then scaleY: = l
else scaleY: = h / Image1.Picture.Bitmap.Height;

if ScaleY < ScaleX
then scale: = scaleY

else scale: = scaleX; // тут масштаб визначений
Image1.Top:=Form1.Label5.Top+Form1.Labels.Height+5;

Image1.Width: = Round (Image1.Picture.Bitmap.Width * scale);

Image1.Height: = Round (Image1.Picture.Bitmap.Height * scale);

end;
// висновок питання на екран
Procedure VoprosToScr (var f: TextFile; frm: TForm1; var vopros: integer)

var
i: integer;

code: integer;

s, buf: string;
ifn: string; // файл ілюстрації

begin
vopros: = vopros + l ;
str (vopros: 3, s) ;
frm. caption: = 'Питання' + s;
// виведемо текст питання
buf: = '';
repeat
readln (f, s);
if (S [l] <. '.') and (s [l] <> '\')
then buf: = buf + s + '';

until (s [l] = '.') or (s [l] = '\');

frm. labels.caption: = buf;
if s [1] <> '\'
then Form1.Image1.Tag: = 0 else

// до питання є ілюстрація

begin
Form1.Image1.Tag: = 1;
if n: = copy (s, 2, length (s));
try
Form1.Image1.Picture.LoadFromFile (ifn)

except
on E: EFOpenError do
frm.tag: = 0; end; // try end;
// читаємо варіанти відповідей
i: = l;
repeat
buf: = >;
repeat // читаємо текст варіанти відповіді

readln (f, s);

if (S [1] <> '.') and (s [l] про ',')
then buf: = buf + s + '';

until (s [l] = ',') or (s [1] = '.'); // прочитаний альтернативний відповідь

val (s [2], score [i], code);

case i of
1: frm.Label1.caption: = buf;

2: frm.Label2.caption: = buf;

3: frm.Label3.caption: = buf;

4: frm.Label4.caption: = buf;

end;
until s [l] = '.';

// тут прочитана ілюстрація і альтернативні відповіді

// текст питання вже виведений
if Forml.Image1.Tag = 1 // є ілюстрація до питання then

begin
Scalelmage (Form1.Image1); Form1.Image1.Visible: = TRUE;

end;
// висновок альтернативних відповідей

if Form1.Label1.Caption & lt; & gt; & Quot; then begin
if Forml.Image1.Tag = 1
then

frm.Label1.top:=frm.Imagel.Top+frm.Image1.Height+ 5

else

frm.Label1.top:=frm.Label5.Top+frm.Labels.Height+ 5;

frm.RadioButton1.top:=frm.Label1.top;

frm.Labell.visible: = TRUE;

frm.RadioButton1.visible: = TRUE;

end;
if Forml.Label2.Caption <> then begin
frm.Label2.top:=frm.Label1.top+ frm.Label1.height + 5;

frm.RadioButton2.top:=frm.Label2.top;

frm.Label2.visible: = TRUE;

frm.RadioButton2.visible: = TRUE;

end;
if Forml.Label3.Caption <> '' then begin
frm.Label3.top:=frm.Label2.top+ frm.Label2.height + 5;

frm.RadioButtonS.top:=frm.Label3.top;

frm.Label3.visible: = TRUE;

frm.RadioButtonS.visible: = TRUE;

end;
if Forml.Label4.Caption <> '' Then begin
frm.Label4.top:=frm.Label3.top+ frm.Label3.height + 5;

frm.RadioButton4. top: = frm.Label4.top;
frm.Label4.visible: = TRUE;

fm.Rad & plusmn; o8utton4.vis: tble: = TRUE]

end;

end;
Procedure ResetForm (frm: TForml);

begin
// зробити невидимими всі мітки і перемикачі
frm.Label1.Visible: = FALSE;
f rm.Label1.caption: = '';
frm.Label1.width: = frm.ClientWidth-frm.Label1.left-5;
frm.RadioButtonl.Visible: = FALSE;
frm.Label2.Visible: = FALSE;
frm.Label2.caption: = '';
frm.Label2.width: = frm.ClientWidth-frm.Label2.left-5;
frm.RadioButton2.Visible: = FALSE;
frm.Label3.Visible: = FALSE;
frm.Label3.caption: = '';
frm.Label3.width: = frm.ClientWidth-frm.Label3.left-5;
frm.RadioButton3.Visible: = FALSE;
frm.Label4.Visible: = FALSE;
frm.Label4.caption: = '';
frm.Label4.width: = frm.ClientWidth-frm.Label4.left-5;
f rm.RadioButton4.Visible: = FALSE;
frm.Label5.width: = frm.ClientWidth-frm.Labels.left-5;
frm. Image1.Visible: = FALSE;

end;
// визначення досягнутого рівня

procedure Itog (summa: integer; frmrTForml);

var
i: integer; buf: string;

begin
buf: ="";
str (summa: 5, buf);
buf: = 'Результати тестування '+ chr (13)
+ 'Всього балів: '+ buf; i: = 1;

while (summa < level [i]) and (i < N_LEV) do
i: = i + l;
buf: = buf + chr (13) + mes [ i]; frm.Labels.caption: = buf;

end;
{$ R * .DFM}

procedure TForm1.FormActivate (Sender: TObject);

begin
ResetForm (Form1);

if ParamCount = 0 then

begin
Labels.caption: = 'He заданий файл питань тесту.';

Button1.caption: = 'Ok';

Button1.tag: = 2; Button1.Enabled: = TRUE

end

else begin
fn : = ParamStr (1); assignfile (f, fn); {$ I-} reset (f);
{I +}
if IOResult = 0 then begin
Info (f, Label5);

// прочитати і вивести інформацію про тест

GetLevel (f); // прочитати інформацію про рівні оцінок

end;

end;

end;
procedure TForml.ButtonlClick (Sender: TObject); begin
case Button1.tag of 0: begin
Buttonl.caption: = 'Далі';

Buttonl.tag: = 1;

RadioButtonS.Checked: = TRUE; // вивід першого питання

Buttonl.Enabled: = False; ResetForm (Form1);

VoprosToScr (f, Forml, vopros}

end;
1: begin // висновок інших питань

summa: = summa + score [otv];

RadioButtonS.Checked: = TRUE;

Button1.Enabled: = False;

ResetForm (Form1);

if not eof (f)
then VoprosToScr (f, Forml, vopros) else
begin
suima: = Summa + score [otv];

closefile (f);

Buttonl.caption: = 'Ok';

Form1.caption: = 'Результат';

Button1.tag: = 2;

Button1.Enabled: = TRUE;

Itog (summa, Forml) ;

end;

end;

2: begin // завершення роботи
Forml.Close;

end;

end;

end;
procedure TForm1.RadioButtonClick (Sender: TObject);

begin
if sender = RadioButtonl

then otv: = l
else if sender = RadioButtonl

then otv: = 2
else if sender = RadioButton3

then otv: = 3 else otv: = 4;

Buttonl.enabled: = TRUE;

end;
end.

Після запуску програми і виведення на екран стартовою форми відбувається подія onActivate. процедура FormActivate спочатку викликає процедуру ResetForm, яка, привласнюючи значення False властивості visible, робить невидимими поля виведення альтернативних відповідей і перемикачі. Аналогічно робиться невидимої область ілюстрації. Крім того, процедура встановлює максимально можливу ширину полів міток альтернативних відповідей.
Після очищення форми перевіряється, чи зазначений при запуску програми параметр – ім’я тестового файлу.

Якщо параметр не зазначений (Значення paramCount в цьому випадку дорівнює нулю), то присвоєнням значення властивості caption мітки Label5 виводиться повідомлення: Чи не заданий файл питань тесту І властивості Tag кнопки Button1 присвоюється значення 2 (Button1.Tag: = 2;)
Якщо параметр заданий, то відкривається файл тесту.

Програма тестування отримує ім’я файлу тесту як результат функції Paramstr (l). Реалізація програми передбачає, що якщо ім’я файлу тесту задано без вказівки шляху доступу до нього, то файл тесту і файли з ілюстраціями знаходяться в тому ж каталозі, що і програма тестування. Якщо шлях доступу вказано, то файли з ілюстраціями повинні знаходитися в тому ж каталозі, що і файл тесту. Такий підхід дозволяє згрупувати всі файли одного тесту в одному каталозі.

Відкривається файл тесту звичайним чином. Спочатку зверненням до процедури AssignFile ім’я файлу зв’язується з файлової змінної, а потім викликається інструкція відкриття файлу для читання.
Після успішного відкриття файлу викликається процедура info, яка зчитує з файлу інформацію про тест і виводить її привласненням прочитаного тексту властивості Caption поля мітки Labels.

Потім викликається процедура GetLevei, яка зчитує з файлу тесту інформацію про рівні оцінки. ця процедура заповнює масиви level І mes.
Після виведення інформаційного повідомлення програма чекає, коли користувач натисне кнопку OK (Button1).
Командна кнопка Buttoni використовується для:

  • аварійного завершення роботи додатки (в разі, якщо не задано ім’я файлу тесту);
  • початку тестування (після прочитання інформаційного повідомлення);
  • переходу до наступного питання (Після вибору одного з відповідей);
  • завершення роботи програми (після прочитання результатів тестування).

Властивість Tag кнопки Buttoni використовується для ідентифікації поточного стану форми і вибору дії при натисканні на кнопці Buttoni.
Після виведення інформації про тест значення властивості Tag кнопки Button: дорівнює нулю. Тому в результаті першого клацання на кнопці Buttoni виконується та частина програми, яка забезпечує висновок першого питання, заміну знаходиться на кнопці тексту ОК на текст Далі, і встановлює в вибране стан перемикач RadioButton5, який закритий панеллю і тому не видно користувачеві. Крім того, привласненням значення False властивості Enabled кнопка Buttoni робиться недоступною, тим самим блокується перехід до наступного питання до тих пір, поки не буде обраний один з відповідей. Значенням властивості Button1.Tag присвоюється одиниця, тим самим виконується підготовка до обробки наступного клацання кнопки Button1.

Після вибору відповіді і натискання кнопки Далі (Buttoni) (в цьому випадку значення властивості Button1.Tag дорівнює одиниці) до набраної суми балів додається кількість балів за обраний відповідь. Потім, якщо не досягнуто кінець файлу, викликається процедура виведення чергового питання. Якщо досягнуто кінця файлу, то спочатку закривається файл тесту, змінюється текст на кнопці Buttoni і значення Button1. Tag, а потім за допомогою процедури Itog виводяться результати тестування.
Якщо значення Button1.Tag дорівнює двом, то застосуванням методу close до форми Form1 закривається вікно програми, в результаті чого програма завершує роботу.
Висновок питання і альтернативних відповідей виконує процедура VoprosToScr. Спочатку процедура збільшує лічильник питань vopros і присвоєнням значення властивості Caption форми виводить номер поточного питання в заголовок вікна. Потім процедура читає рядки з файлу тесту до тих пір, поки першим символом черговий прочитаної рядки не буде точка або “зворотна похила риска”.

Після перегляду тексту питання робиться перевірка: який символ використовується як ознака кінця питання. Якщо зворотна похила риска, що свідчить про те, що до питання є ілюстрація, то властивості Form1.image1.Tag присвоюється одиниця і з прочитаної рядки виділяється ім’я файлу ілюстрації.
Завантаження ілюстрації здійснюється застосуванням методу LoadFromFile до властивості image1. Picture. Однак після завантаження ілюстрація на екрані не виникає, так як значення властивості Image1. visible одно False.
Після зчитування ілюстрації процедура зчитує питання. Після обробки останнього питання, якщо була завантажена ілюстрація, викликом процедури ScaleImage обчислюється і встановлюється розмір області ілюстрації. Після цього установкою значення властивості Imagel.Top задається положення верхньої межі області ілюстрації, а привласненням значення True властивості image1. visible ілюстрація робиться видимою.

Так як кількість символів в тексті питання і число альтернативних відповідей від питання до питання можуть змінюватися, і, отже, на екрані вони можуть займати різну кількість рядків, то кожен раз перед виведенням тексту чергового відповідей встановлює значення властивості тор як відстань від нижньої межі попереднього альтернативного відповіді. Для поля виведення першого альтернативного відповіді (Label) значення тор обчислюється від нижньої межі поля питання (Labels) або, якщо до питання є ілюстрація, від нижньої межі поля ілюстрації (imagei).

Вибір відповіді користувач здійснює клацанням одного з перемикачів. Після виведення питання жоден з перемикачів, відповідних альтернативного відповіді, не є обраним. Вибраний тільки перемикач RadioButtonS, який знаходиться за панеллю Panel1 і тому не видно користувачеві.
Для обробки події onclick перемикачів RadioButton1,
RadioButton2, RadioButton3 і RadioButton4

У Програмі використовується загальна процедура-TForm1.RadioButtonciick. Ця процедура отримує в якості параметра об’єкт, на якому відбулася подія. Порівнюючи отримане значення з іменами об’єктів-кнопок вибору, процедура присвоює значення глобальної змінної otv, яка використовується процедурою VoprosToScr для збільшення набраної суми балів. Крім того, процедура TForm1.RadioButtonClick робить доступною кнопку переходу до наступного питання (Buttonl), яка після виведення чергового питання недоступна.
Процедура Itog, порівнюючи набрану суму балів summa зі значенням елементів масиву level, визначає, якого рівня досяг випробуваний, і виводить відповідне повідомлення присвоєнням значення властивості
Label5.Caption.