Skip to Content

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

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

После создания формы в окно редактора кода, в секцию implementation следует поместить описание глобальных констант (раздел const) и переменных (раздел var). Затем можно приступить к созданию процедур обработки событий.

Их в программе три: обработка события onActivate для стартовой формы, обработка события Onclick для командной кнопки Buttoni и процедура обработки события onclick — одна, общая для переключателей выбора ответа.

В листинге 15.1 приведен полный текст программы.

Листинг 15.1. Программа тестирования

  1. unit test1_;
  2. interface
  3.  
  4. uses
  5. SysUtils, WinTypes, WinProcs, Messages,
  6. Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls, ExtCtrls;
  8.  
  9. type
  10.  
  11. TForm1 = class(TForm) // вопрос
  12. Label3: TLabel; // альтернативные ответы
  13. Label1: TLabel; Label2: TLabel;
  14. Label3: TLabel; Label4: TLabel;
  15.  
  16. // переключатели выбора ответа
  17.  
  18. RadioButton1: TRadioButton;
  19. RadioButton2: TRadioButton;
  20. RadioButton3: TRadioButton;
  21. RadioButton4: TRadioButton;
  22. Image1: TImage; // область вывода иллюстрации
  23. Button1: TButton; // кнопка Ok, Дальше
  24. RadioButtonS: TRadioButton; // "служебная" кнопка
  25.  
  26. Panel1: ТPanel;
  27.  
  28. procedure FormActivate(Sender: TObject);
  29. procedure ButtonlClick(Sender: TObject};
  30. procedure RadioButtonClick(Sender: TObject);
  31.  
  32. private
  33. { Private declarations }
  34. public
  35. { Public declarations }
  36. end;
  37.  
  38. var
  39. Form1: TForm1; // форма
  40.  
  41. implementation
  42.  
  43. const
  44.  
  45. N_LEV=4; // четыре уровня оценки
  46. N_ANS=4; // четыре варианта ответов
  47.  
  48. var
  49.  
  50. f:TextFile;
  51. fn:string; // имя файла вопросов
  52. 1evel:array[1..N_LEV] of integer;
  53.  
  54. // сумма, соответствующая уровню
  55.  
  56. mes:array[1.,N_LEV] of string;
  57.  
  58. // сообщение, соответствующее уровню
  59.  
  60. score:array[1..N_ANS] of integer;
  61.  
  62. // балл за выбор ответа
  63.  
  64. summa:integer; // набрано очков
  65. vopros:integer; // номер текущего вопроса
  66. n_otv:integer; // число вариантов ответа
  67. otv:integer; // номер выбранного ответа
  68.  
  69. // вывод начальной информации о тесте
  70.  
  71. procedure info(var f:TextFile;l:TLabel);
  72. var
  73.  
  74. s,buf:string;
  75.  
  76. begin
  77.  
  78. buf:='';
  79.  
  80. repeat
  81.  
  82. readln(f,s);
  83.  
  84. if s[l] <> '.' then
  85. buf := buf + s+ ' ';
  86.  
  87. until s[l] ='.'; l.caption:=buf;
  88.  
  89. end;
  90.  
  91. // прочитать информацию об оценках за тест
  92.  
  93. Procedure GetLevel(var f:TextFile);
  94. var
  95.  
  96. i:integer;
  97. buf:string;
  98.  
  99. begin // заполняем значения глобальных массивов
  100.  
  101. i:=l;
  102.  
  103. repeat
  104.  
  105. readln(f,buf);
  106.  
  107. if buf[1] <> '.' then
  108. begin
  109.  
  110. mes[i]:=buf; readln(f,level[i]);
  111. i:=i+1;
  112.  
  113. end;
  114.  
  115. until buf[1]='.';
  116.  
  117. end;
  118.  
  119. // масштабирование иллюстрации
  120.  
  121. Procedure ScaleImage(Imagel:TImage);
  122. var
  123.  
  124. w,h:integer; // максимально допустимые размеры картинки
  125. scaleX:real; // коэф. масштабирования по X
  126. scaleY:real; // коэф. масштабирования по Y
  127. scale:real; // общий коэф. масштабирования
  128.  
  129. begin
  130.  
  131. // вычислить максимально допустимые размеры картинки
  132.  
  133. w:=Form1.ClientWidth-10;
  134. h:=Form1.ClientHeight
  135. - Form1.Panel1.Height -5
  136. - Form1.Label5.Top
  137. - Form1.Label5.Height - 5;
  138.  
  139. if Form1.Label1.Caption <> '' then
  140. h:=h-Form1.Label1.Height-5;
  141.  
  142. if Form1.Label2.Caption <> '' then
  143. h:=h-Form1.Label2.Height-5;
  144.  
  145. if Forml.Label3.Caption <> '' then
  146. h:=h-Form1.Label3.Height-5;
  147.  
  148. if Forml.Label4.Caption <> " then
  149. h:=h-Form1.Label4.Height-5; // определить масштаб
  150.  
  151. if w>Imagel.Picture.Bitmap.Width then
  152. scaleX:=l
  153.  
  154. else
  155.  
  156. scaleX:=w/Imagel.Picture.Bitmap.Width;
  157.  
  158. if h>Imagel.Picture.Bitmap.Height then
  159. scaleY:=l
  160.  
  161. else
  162.  
  163. scaleY:=h/Image1.Picture.Bitmap.Height;
  164.  
  165. if ScaleY<ScaleX then
  166. scale:=scaleY
  167.  
  168. else
  169.  
  170. scale:=scaleX; // здесь масштаб определен
  171.  
  172. Image1.Top:=Form1.Label5.Top+Form1.Labels.Height+5;
  173. Image1.Width:=Round(Image1.Picture.Bitmap.Width* scale);
  174. Image1.Height:=Round(Image1.Picture.Bitmap.Height*scale);
  175.  
  176. end;
  177.  
  178. // вывод вопроса на экран
  179.  
  180. Procedure VoprosToScr(var f:TextFile;frm:TForm1;var vopros:integer)
  181. var
  182.  
  183. i:integer;
  184. code:integer;
  185. s,buf:string;
  186. ifn:string; // файл иллюстрации
  187.  
  188. begin
  189.  
  190. vopros:=vopros+l ;
  191. str(vopros:3,s) ;
  192. frm. caption: = 'Вопрос' + s;
  193.  
  194. //выведем текст вопроса
  195.  
  196. buf:='';
  197.  
  198. repeat
  199.  
  200. readln(f, s) ;
  201.  
  202. if (s[l] <> '.') and (s[l] <>'\') then
  203. buf:=buf+s+' ';
  204.  
  205. until (s[l] ='.') or (s[l] = '\');
  206.  
  207. frm. labels.caption:=buf;
  208.  
  209. if s[1] <> '\' then
  210. Form1.Image1.Tag:=0
  211. else
  212.  
  213. // к вопросу есть иллюстрация
  214.  
  215. begin
  216.  
  217. Form1.Image1.Tag:=1;
  218.  
  219. if n:=copy(s,2,length(s));
  220.  
  221. try
  222.  
  223. Form1.Image1.Picture.LoadFromFile(ifn)
  224. except
  225.  
  226. on E:EFOpenError do
  227.  
  228. frm.tag:=0; end; // try end;
  229.  
  230. // читаем варианты ответов
  231.  
  232. i:=l;
  233.  
  234. repeat
  235.  
  236. buf: = ";
  237.  
  238. repeat // читаем текст варианта ответа
  239.  
  240. readln(f,s);
  241.  
  242. if (s[1]<>'. ') and (s[l] о ', ') then
  243. buf:=buf+s+' ';
  244.  
  245. until (s[l]=',')or(s[1]='.'); // прочитан альтернативный ответ
  246.  
  247. val(s[2],score[i],code);
  248.  
  249. case i of
  250.  
  251. 1: frm.Label1.caption:=buf;
  252. 2: frm.Label2.caption:=buf;
  253. 3: frm.Label3.caption:=buf;
  254. 4: frm.Label4.caption:=buf;
  255.  
  256. end;
  257.  
  258. until s[l]='.';
  259.  
  260. // здесь прочитана иллюстрация и альтернативные ответы
  261. // текст вопроса уже выведен
  262.  
  263. if Forml.Image1.Tag =1 then// есть иллюстрация к вопросу
  264. begin
  265.  
  266. Scalelmage(Form1.Image1);
  267. Form1.Image1.Visible:=TRUE;
  268.  
  269. end;
  270.  
  271. // вывод альтернативных ответов
  272.  
  273. if Form1.Label1.Caption <> " then
  274. begin
  275.  
  276. if Forml.Image1.Tag =1 then
  277. frm.Label1.top:=frm.Imagel.Top+frm.Image1.Height+5
  278.  
  279. else
  280.  
  281. frm.Label1.top:=frm.Label5.Top+frm.Labels.Height+5;
  282. frm.RadioButton1.top:=frm.Label1.top;
  283. frm.Labell.visible:=TRUE;
  284. frm.RadioButton1.visible:=TRUE;
  285.  
  286. end;
  287.  
  288. if Forml.Label2.Caption <> " then
  289. begin
  290.  
  291. frm.Label2.top:=frm.Label1.top+ frm.Label1.height+5;
  292. frm.RadioButton2.top:=frm.Label2.top;
  293. frm.Label2.visible:=TRUE;
  294. frm.RadioButton2.visible:=TRUE;
  295.  
  296. end;
  297.  
  298. if Forml.Label3.Caption <> '' then
  299. begin
  300.  
  301. frm.Label3.top:=frm.Label2.top+ frm.Label2.height+5;
  302. frm.RadioButtonS.top:=frm.Label3.top;
  303. frm.Label3.visible:=TRUE;
  304. frm.RadioButtonS.visible:=TRUE;
  305.  
  306. end;
  307.  
  308. if Forml.Label4.Caption <> '' then
  309. begin
  310.  
  311. frm.Label4.top:=frm.Label3.top+ frm.Label3.height+5;
  312. frm.RadioButton4. top:=frm.Label4.top;
  313. frm.Label4.visible:=TRUE;
  314. fm.Rad±o8utton4.vis:tble:=TRUE]
  315.  
  316. end;
  317. end;
  318.  
  319. Procedure ResetForm(frm:TForml);
  320. begin
  321.  
  322. // сделать невидимыми все метки и переключатели
  323.  
  324. frm.Label1.Visible:=FALSE;
  325. frm.Label1.caption: ='';
  326. frm.Label1.width:=frm.ClientWidth-frm.Label1.left-5;
  327. frm.RadioButtonl.Visible:=FALSE;
  328. frm.Label2.Visible:=FALSE;
  329. frm.Label2.caption:='';
  330. frm.Label2.width:=frm.ClientWidth-frm.Label2.left-5;
  331. frm.RadioButton2.Visible:=FALSE;
  332. frm.Label3.Visible:=FALSE;
  333. frm.Label3.caption:='';
  334. frm.Label3.width:=frm.ClientWidth-frm.Label3.left-5;
  335. frm.RadioButton3.Visible:=FALSE;
  336. frm.Label4.Visible:=FALSE;
  337. frm.Label4.caption:='';
  338. frm.Label4.width:=frm.ClientWidth-frm.Label4.left-5;
  339. frm.RadioButton4.Visible:=FALSE;
  340. frm.Label5.width:=frm.ClientWidth-frm.Labels.left-5;
  341. frm. Image1.Visible:=FALSE;
  342.  
  343. end;
  344.  
  345. // определение достигнутого уровня
  346.  
  347. procedure Itog(summa:integer;frmrTForml);
  348. var
  349.  
  350. i:integer;
  351. buf:string;
  352.  
  353. begin
  354.  
  355. buf: = ";
  356. str(summa:5,buf);
  357. buf:='Результаты тестирования'+chr(13)
  358. +'Всего баллов: '+buf; i:=1;
  359.  
  360. while (summa < level[i]) and (i<N_LEV) do
  361.  
  362. i:=i+l;
  363. buf:=buf+chr(13)+mes[ i ] ; frm.Labels.caption:=buf;
  364.  
  365. end;
  366.  
  367. {$R *.DFM}
  368.  
  369. procedure TForm1.FormActivate(Sender: TObject);
  370. begin
  371.  
  372. ResetForm(Form1);
  373.  
  374. if ParamCount = 0 then
  375. begin
  376.  
  377. Labels.caption:= 'He задан файл вопросов теста.';
  378. Button1.caption: ='Ok' ;
  379. Button1.tag:=2; Button1.Enabled:=TRUE
  380.  
  381. end
  382. else
  383. begin
  384.  
  385. fn := ParamStr(1);
  386. assignfile(f,fn);
  387.  
  388. {$I-}
  389. reset(f);
  390. {I+}
  391.  
  392. if IOResult=0 then
  393. begin
  394.  
  395. Info(f,Label5);
  396.  
  397. // прочитать и вывести информацию о тесте
  398.  
  399. GetLevel(f); // прочитать информацию об уровнях оценок
  400.  
  401. end;
  402. end;
  403. end;
  404.  
  405. procedure TForml.ButtonlClick(Sender: TObject); begin
  406.  
  407. case Button1.tag of
  408. 0:
  409. begin
  410.  
  411. Buttonl.caption:='Дальше';
  412. Buttonl.tag:=1;
  413. RadioButtonS.Checked:=TRUE; // вывод первого вопроса
  414. Buttonl.Enabled:=False; ResetForm(Form1);
  415. VoprosToScr(f,Forml,vopros}
  416.  
  417. end;
  418.  
  419. 1:
  420. begin // вывод остальных вопросов
  421.  
  422. summa:=summa+score[otv];
  423. RadioButtonS.Checked:=TRUE;
  424. Button1.Enabled:=False;
  425. ResetForm(Form1);
  426.  
  427. if not eof(f) then
  428. VoprosToScr(f,Forml,vopros)
  429.  
  430. else
  431. begin
  432.  
  433. suima: =summa+score [otv] ;
  434. closefile(f);
  435. Buttonl.caption:='Ok';
  436. Form1.caption: ='Результат';
  437. Button1.tag:=2;
  438. Button1.Enabled:=TRUE;
  439. Itog(summa,Forml);
  440.  
  441. end;
  442. end;
  443.  
  444. 2:
  445. begin // завершение работы
  446. Forml.Close;
  447.  
  448. end;
  449. end;
  450. end;
  451.  
  452. procedure TForm1.RadioButtonClick(Sender: TObject);
  453. begin
  454.  
  455. if sender = RadioButtonl then
  456. otv:=l
  457. else
  458.  
  459. if sender = RadioButtonl then
  460. otv:=2
  461. else
  462.  
  463. if sender = RadioButton3 then
  464. otv:=3 else otv:=4;
  465.  
  466. Buttonl.enabled:=TRUE;
  467.  
  468. end;
  469.  
  470. 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.



Delphi Для профессионалов &1   |    Delphi Для профессионалов &2   |    Delphi Для профессионалов &3   |    Иллюстрированный самоучитель &1   |    Иллюстрированный самоучитель &2