Отладка программы в Delphi

Блоксхема процедуры выбора точки маршрута

Рисунок 12.11. Блок-схема процедуры выбора точки маршрута


 Блоксхема процедуры выбора точки маршрута

Диалоговое окно Обзор папок появляется в результате щелчка на кнопке Папка

Рисунок 12.6. Диалоговое окно Обзор папок появляется в результате щелчка на кнопке Папка

Диалоговое окно Обзор папок появляется в результате щелчка на кнопке Папка
Основную работу выполняет рекурсивная функция Find. У функции Find один-единственный параметр — структура searchRec, которая используется функциями FindFirst и FindNext для поиска соответственнопервого и следующего файла, удовлетворяющего критерию поиска. Следует обратить внимание на то, как осуществляется перебор каталогов в текущем каталоге. Если текущий каталог не корневой, то помимо обычных, то есть имеющих имя, в каталоге есть еще два каталога: .. и ., которые обозначают каталог предыдущего уровня. Эти два каталога не обрабатываются, так как при входе в эти каталоги фактически выполняется выход (переход) в родительский каталог. Если этого не учесть, то программа зациклится.



Кривая Гильберта

Кривая Гильберта

Следующая программа вычерчивает в диалоговом окне кривую Гильберта. На Рисунок 12.7 приведены кривые Гильберта первого, второго и третьего порядков. Если присмотреться, то видно, что кривая второго порядка получается путем соединения прямыми линиями четырех кривых первого порядка. Аналогичным образом получается кривая третьего порядка, но при этом в качестве "кирпичиков" используются кривые второго порядка. Таким образом, чтобы нарисовать кривую третьего порядка, надо нарисовать четыре кривых второго порядка. В свою очередь, чтобы нарисовать кривую второго порядка, надо нарисовать четыре кривых первого порядка. Таким образом, алгоритм вычерчивания кривой Гильберта является рекурсивным.

Диалоговое окно программы Кривая Гильберта, в котором находится кривая пятого порядка, приведено на Рисунок 12.8, текст программы — в листинге 12.4.

Кривые Гильберта первого второго и третьего порядков

Рисунок 12.7. Кривые Гильберта первого, второго и третьего порядков


Кривые Гильберта первого второго и третьего порядков

Рекурсивная функция вычисления факториала

Листинг 12.1. Рекурсивная функция вычисления факториала

function factorial(n: integer): integer;
begin

if n <>
1

then factorials n * factorial(n-1)
// функция вызывает сама себя
else factorial := 1; // рекурсивный процесс закончен
end;

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

На Рисунок 12.1 приведен вид диалогового окна программы, которая для вычисления факториала числа использует рекурсивную функцию factorial. Текст программы приведен в листинге 12.2.

Использование рекурсивной функции

Листинг 12.2. Использование рекурсивной функции

unit factor ;

interface

uses

Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Label1: TLabel;

Edit1: TEdit;

Button1: TButton;

Label2: TLabel;

procedure ButtonlClick(Sender: TObject) ;
private

{ Private declarations } public

{ Public declarations } end;

var

Form1: TForm1;

implementation

{$R *.DFM}

// рекурсивная функция

function factorial(n: integer): integer;

begin

if n >
1


then factorial := n * factorial(n-1) // функция вызывает сама себя

else factorial:= 1; // факториал 1 равен 1
end;

procedure TForml.ButtonlClick(Sender: TObject);

var

k:integer; // число, факториал которого надо вычислить

f:integer; // значение факториала числа k
begin

k := StrToInt(Edit1.Text);


f := factorial(k);


label2.caption:='Факториал числа '+Edit1.Text

+ ' равен '+IntToStr(f);

end;

end.

На Рисунок 12.2 приведены два диалоговых окна. Результат вычисления факториала, представленный на Рисунок 12.2, а, соответствует ожидаемому.

Программа поиск файлов

Листинг 12.3. Программа поиск файлов

// поиск файла в указанном каталоге и его подкаталогах
// используется рекурсивная процедура Find
unit FindFile_;

interface

uses

Windows, Messages, SysUtils, Variants,
Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, FileCtr;
type

TForm1 = class(TForm)

Editl: TEdit; // что искать

Edit2: TEdit; // где искать

Memo1: TMemo; // результат поиска

Button1: TButton; // кнопка Поиск

Button2: TButton; // кнопка Папка

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

procedure Button1Click(Sender: TObject);


procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }
end;
var

Form1: TForm1;

implementation

{$R *.dfm}

var

FileName: string; // имя или маска искомого файла

cDir: string;

n: integer; // кол-во файлов, удовлетворяющих запросу

// поиск файла в текущем каталоге

procedure Find;

var

SearchRec: TSearchRec; // информация о файле или каталоге

begin

GetDir(0,cDir);
// получить имя текущего каталога
if cDir [length (cDir) ] <>
'V then cDir := cDir+'\';

if FindFirst(FileName, faArchive,SearchRec) = 0
then repeat

if (SearchRec.Attr and faAnyFile) = SearchRec.Attr
then begin

Form1.Memo1.Lines.Add(cDir + SearchRec.Name);

n := n + 1; end; until FindNext(SearchRec) <>
0;

// обработка подкаталогов текущего каталога
if FindFirst('*', faDirectory, SearchRec) = 0 then repeat

if (SearchRec.Attr and faDirectory) = SearchRec.Attr then begin

// каталоги .. и . тоже каталоги,
// но в них входить не надо .'.'.'
if SearchRec.Name[1] <>
'.' then begin

ChDir(SearchRec.Name);
// войти в каталог
Find; // выполнить поиск в подкаталоге
ChDir('..');
// выйти из каталога
end;
end;

until FindNext(SearchRec) <>
0;
end;

/ возвращает каталог, выбранный пользователем
function GetPath(mes: string):string;
var

Root: string; // корневой каталог
pwRoot : PWideChar; Dir: string;
begin

Root := '';

GetMem(pwRoot, (Length(Root)+1) * 2);

pwRoot := StringToWideChar(Root, pwRoot, MAX_PATH*2);

if SelectDirectory(mes, pwRoot, Dir) then

if length(Dir) =2 // пользователь выбрал корневой каталог
then GetPath := Dir+'\' else GetPath := Dir else

GetPath := '';
end;

щелчок на кнопке Поиск

procedure TForml.ButtonlClick(Sender: TObject);

begin

Memo1.Clear; // очистить поле Memol

Label4.Caption := '';

FileName := Edit1.Text; // что искать.

cDir := Edit2.Text; // где искать

n:=0; // кол-во найденных файлов

ChDir(cDir);
// войти в каталог начала поиска

Find; // начать поиск

if n = 0 then

ShowMessage('Файлов, удовлетворяющих критерию поиска нет.')
else Label4.Caption := 'Найдено файлов:' + IntToStr(n);

end;

// щелчок на кнопке Папка

procedure TForml.Button2Click (Sender: TObject);


var

Path: string; begin

Path := GetPath('Выберите папку');


if Path <>
''

then Edit2.Text := Path;
end;

end.

Кривая Гильберта

Листинг 12.4. Кривая Гильберта

unit gilbert_;

interface

uses

Windows, Messages, SysUtils,
Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, ComCtrls;

type

TForml = class(TForm)

procedure FormPaint(Sender: TObject);

private

{ Private declarations }
public

{ Public declarations }
end;

var

Form1: TForm1;

implementation {$R *.dfm}

var

p: integer =5; // порядок кривой
u: integer =7; // длина штриха

{ Кривую Гильберта можно получить путем
соединения элементов а,b,с и d.

Каждый элемент строит
соответствующая процедура. }
procedure a(i:integer; canvas: TCanvas);
forward;
procedure b(i:integer; canvas: TCanvas);
forward;
procedure с(i:integer; canvas: TCanvas);
forward;
procedure d(i:integer; canvas: TCanvas);
forward;

// Элементы кривой

procedure a(i: integer; canvas: TCanvas);

begin

if i >
0 then begin


d(i-l, canvas);

canvas.LineTo(canvas.PenPos.X+u,canvas.PenPos.Y);

a(i-l, canvas);

canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y+u);

a(i-l, canvas);

canvas.LineTo(canvas.PenPos.X-u,canvas.PenPos.Y);

с (i-1, canvas);

end;
end;

procedure b(i: integer; canvas: TCanvas);


begin

if i >
0 then begin


c(i-l, canvas);

canvas.LineTo(canvas.PenPos.X-u,canvas.PenPos.Y);

b(i-1, canvas);

canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y-u);

b(i-l, canvas);

canvas.LineTo(canvas.PenPos.X+u, canvas.PenPos.Y);

d(i-l, canvas);

end;
end;

procedure c(i: integer; canvas: TCanvas);

begin

if i >
0 then begin

b(i-1, canvas);

canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y-u);

с (i-1, canvas);

canvas.LineTo(canvas.PenPos.X-u,canvas.PenPos.Y);

c(i-1, canvas);

canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y+u);

a(i-1, canvas);

end;
end;

procedure d(i: integer; canvas: TCanvas);

begin

if i >
0 then begin

a(i-1, canvas);

canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y+u);

d(i-1, canvas);

canvas.LineTo(canvas.PenPos.X+u,canvas.PenPos. Y) ;
d(i-1, canvas);

canvas.LineTo(canvas.PenPos.X,canvas.PenPos.Y-u);

b(i-1, canvas);

end;
end;

procedure TForml.FormPaint(Sender: TObject);

begin

Form1.Canvas.MoveTo(u, u) ;

a(5,Form1.Canvas);
// вычертить кривую Гильберта
end;

end.

Следует обратить внимание на следующую особенность реализации программы. Процедура, которая вычерчивает элемент а, помимо самой себя (для вычерчивания элемента а кривой более низкого порядка) вызывает процедуры d и ь, описание (текст) которых в тексте программы находится после процедуры а. Чтобы компилятор не вывел сообщение об ошибке, в текст программы помещено объявление процедуры с ключевым словом forward, означающим, что это только объявление, а описание (реализация) находится дальше. Таким образом, уже в процессе компиляции процедуры а, компилятор "знает", что имена ь и d означают процедуры.

Поиск маршрута

Листинг 12.5. Поиск маршрута

unit road_;

interface

uses

Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids;

type

TForml = class(TForm)

StringGridl: TStringGrid;

Edit1: TEdit;

Edit2: TEdit;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Button1: TButton;

Label4: TLabel;

procedure FormActivate(Sender: TObject);


procedure ButtonlClickfSender: TObject);

private

{ Private declarations } public

{ Public declarations } end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure TForml.FormActivate(Sender: TObject);

var

i:integer; begin

// нумерация строк
for i:=1 to 10 do

StringGridl.Cells[0,i]:=IntToStr(i);
// нумерация колонок

for i:=l to 10 do

StringGridl.Cells[1,0]:=IntToStr(i);

// описание предопределенной карты StringGridl.Cells[1,2]:='1' StringGridl.Cells[2,l]:='1'
StringGridl.Cells[1,3]:='1'
StringGridl.Cells[3,1]:='1'
StringGridl.Cells[1,4]:='1'
StringGridl.Cells[4,1]:='1'
StringGridl.Cells[3,7]:='1'
StringGridl.Cells[7,3]:='1'
StringGridl.Cells[4,6]:='1'
StringGridl.Cells[6,4]:='1'
StringGridl.Cells[5,6]:='1'
StringGridl.Cells[6,5]:='1'
StringGridl.Cells[5,7]:='1'
StringGridl.Cells[7,5]:='1'
StringGridl.Cells[6,7]:='1'
StringGridl.Cells[7,6]:='1'
end;

procedure TForml.ButtonlClick(Sender: TObject);

const

N=10;// кол-во вершин графа var

map:array[1..N,1..N]of integer; // Карта.map[i,j]ne 0,

// если точки i и j соединены

road:array[1..N]of integer;
// Дорога - номера точек карты
incl:array[1..N]of boolean; // incl[1]равен TRUE, если точка

// с номером i включена в road

start,finish:integer; // Начальная и конечная точки
found:boolean; i,j:integer;

procedure step(s,f,p:integer);

var

с:integer;// Номер точки, в которую делаем очередной шаг
i:integer;
begin

if s=f then begin

// Точки s и f совпали !

found:=TRUE;

Labell.caption:=Labell.caption+#13+'Путь:';

for i:=l to p-1 do

Labell.caption:=Labell.caption+' '
+IntToStr(road[i]);
end

else begin

// выбираем очередную точку for c:=l to N do

begin // проверяем все вершины
if(map[s,c]<>
0)and(NOT incite1)

// точка соединена с текущей и не включена в маршрут
then begin

road[p]:=c;// добавим вершину в путь
incl[c]:=TRUE;// пометим вершину как включенную
step(c,f,p+l);
incite]:=FALSE; road[p]:=0;
end;
end;
end;
end;// конец процедуры step

begin

Label1.caption: =' ' ;

// инициализация массивов

for i:=l to N do road[i]:=0;

for i:=l to N do incl[i]:=FALSE;

// ввод описания карты из SrtingGrid.Cells
for i:=l to N do

for j:=1 to N do

if StringGrid1.Cells[i,j] <>
''

then map[i,j]:=StrToInt(StringGridl.Cells[i, j] ;
else map[i,j]:=0;

start:=StrToInt(Editl.text);

finish:=StrToInt(Edit2.text);


road[l]:=start;// внесем точку в маршрут

incl[start]:=TRUE;// пометим ее как включенную

step(start,finish,2);
//ищем вторую точку маршрута

// проверим, найден ли хотя бы один путь
if not found

then Labell.caption:='Указанные точки не соединены!';

end;

end.

При запуске программы в момент активизации формы приложения происходит событие onActivate, процедура обработки которого заполняет массив StringGridl.cells значениями, представляющими описание карты. Этаже процедура нумерует строки и столбцы таблицы, заполняя зафиксированные ячейки первого столбца и первой строки StringGridl.

Поиск маршрута инициирует процедура TFormi.Buttoniciick, которая запускается щелчком на кнопке Поиск. Данная процедура для поиска точки, соединенной с исходной точкой, вызывает процедуру step, которая после выбора первой точки, соединенной с начальной, и включения ее в маршрут вызывает сама себя. При этом в качестве начальной точки задается уже не исходная, а текущая, только что включенная в маршрут.

Поиск кратчайшего пути

Листинг 12.6. Поиск кратчайшего пути

procedure TForm1.Button1Click(Sender: TObject);

const

N=10;{ кол-во вершин графа} var

map:array[1..N,1..N]of integer;
// Карта.map[i,j] не 0,если

// точки i и j соединены

road:array[1..N]of integer;
// Дорога — номера точек карты
incl:array[1..N]of boolean; // incl[1]равен TRUE,если точка

// с номером i включена в road

start, finish:integer;
// Начальная и конечная точки
found:boolean; len:integer; // длина найденного (минимального)

// маршрута } c_len:integer; // длина текущего (формируемого)

// маршрута i,j:integer;

// выбор очередной точки
procedure step(s,f,p:integer);

var

с:integer; { Номер точки, в которую делаем очередной шаг }
i:integer; begin

if s=f then begin

len:=c_len;{ сохраним длину найденного маршрута }
{ вывод найденного маршрута }
for i:=1 to p-1 do

Label1.caption:=Label1.caption+' '+IntToStr(road[i]);

Label1.caption:=Label1.caption

+', длина:'+IntToStr(len)+#13;
end
else

{ выбираем очередную точку }
for c:=l to N do { проверяем все вершины }
if(map[s,c]<>
0)and(NOT incite])

and((len=0)or(c_len+map[s,c]< len)) then begin

// точка соединена с текущей, но не включена в
// маршрут

roadtp]:=c;{ добавим вершину в путь }
incl[c]:=TRUE;{ пометим вершину как включенную }
c_len:=c_len+map[s,с];
step(c,f,p+l);

incite]:=FALSE; roadtp]:=0;

c_len:=c_len-map[s,с];
end;
end;
{ конец процедуры step }

begin

Labell.caption:='';

{ инициализация массивов }

for i: =1 to N do road [ i ] : =0;

for i:=l to N do incl[i]:=FALSE;

{ ввод описания карты из SrtingGrid.Cells}

for i:=l to N do

for j:=1 to N do

if StringGridl.Cells[i, j] <>
"

then mapti,j]:=StrToInt(StringGridl.Cells[i,j])
else mapti,j]:=0;

len:=0; // длина найденного (минимального) маршрута с
len:=0,- // длина текущего (формируемого) маршрута

start:=StrToInt(Edit1.text);


finish:=StrToInt(Edit2.text);


road[1]:=start;{ внесем точку в маршрут }

incl[start]:=TRUE;{ пометим ее как включенную }

step(start,finish,2);
{ищем вторую точку маршрута }

// проверим, найден ли хотя бы один путь

if not found

then Label1.caption:='Указанные точки не соединены!';
end;

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

Массив тар

Рисунок 12.10. Массив тар

 Массив тар
Содержимое ячейки таблицы на пересечении строки i и столбца j соответcтвует значению map [ i, j ].

Помимо массива тар нам потребуются массив road (дорога) и массив incl(от include — включать). В road мы будем записывать номера пройденных городов. В момент достижения конечной точки он будет содержать номера всех пройденных точек, т. е. описание маршрута.

В inci [i] будем записывать true, если точка с номером i включена в маршрут. Делается это для того, чтобы не включать в маршрут уже пройденную точку (не ходить по кругу).

Так как мы используем рекурсивную процедуру, то надо обратить особое внимание на условие завершения рекурсивного процесса. Процедура должна прекратить вызывать сама себя, если текущая точка совпала с заданной конечной точкой.

На Рисунок 12.11 приведена блок-схема алгоритма процедуры выбора очередной точки формируемого маршрута, а диалоговое окно — на Рисунок 12.12.

Для ввода массива, представляющего описание карты, используется компонент stringGridl (значения его свойств приведены в таблице 12.1), для вывода результата (найденного маршрута) — поле метки Label 1. Начальная и конечная точки маршрута задаются вводом значений в поля редактирования Edit1 и Edit2. Процедура поиска запускается щелчком кнопки Поиск (Buttonl). Поля меток Label2, Label3 и Label4 используются для вывода поясняющего текста.

Окно программы вычисления факториала

Рисунок 12.1. Окно программы вычисления факториала

Окно программы вычисления факториала


Поиск кратчайшего пути

Поиск кратчайшего пути

Обычно задача поиска пути на графе формулируется следующим образом: найти наилучший маршрут. Под наилучшим маршрутом, как правило, понимают кратчайший. Найти кратчайший маршрут можно выбором из всех найденных. Однако совсем не обязательно искать все маршруты.

Можно поступить иначе: во время выбора очередной точки проверить, не превысит ли длина формируемого маршрута длину уже найденного пути, если эта точка будет включена в маршрут; если превысит, то эту точку следует пропустить и выбрать другую.

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

В листинге 12.6 приведена процедура, которая использует процедуру step, выполняющую выбор очередной точки маршрута таким образом, что обеспечивается поиск пути минимальной длины.



Поиск пути

Поиск пути

Механизм рекурсии весьма эффективен при программировании задач поиска. В качестве еще одного примера рассмотрим задачу поиска пути между двумя городами. Если несколько городов соединены дорогами, то очевидно, что попасть из одного города в другой можно различными маршрутами. Задача состоит в нахождении всех возможных маршрутов.

Карта дорог между городами может быть изображена в виде графа — набора вершин, означающих города, и ребер, обозначающих дороги (Рисунок 12.9).

Понятие рекурсии

Понятие рекурсии

Рекурсивным называется объект, частично состоящий или определяемый с помощью самого себя. Факториал — это классический пример рекурсивного объекта. Факториал числа п — это произведение целых чисел от 1 до п. Обозначается факториал числа п так: n!.

Согласно определению

n! = 1 х 2 х 3 х ... х (п - 1) х п. Приведенное выражение можно переписать так:

n! = nх ((n - 1) х (n - 2) х ...х 3 х 2 х 1) = n х (n - 1)!

То есть, факториал числа п равен произведению числа п на факториал числа (п - 1). В свою очередь, факториал числа ("-!) — это произведение числа (п - 1) на факториал числа (п - 2) и т. д.

Таким образом, если вычисление факториала п реализовать как функцию, то в теле этой функции будет инструкция вызова функции вычисления факториала числа (п - 1), т. е. функция будет вызывать сама себя. Такой способ вызова называется рекурсией, а функция, которая обращается сама к себе, называется рекурсивной функцией.

В листинге 12.1 приведена рекурсивная функция вычисления факториала.



Представление карты дорог в виде графа

Рисунок 12.9. Представление карты дорог в виде графа

Представление карты дорог в виде графа
Процесс поиска может быть представлен как последовательность шагов. На каждом шаге с использованием некоторого критерия выбирается точка, в которую можно попасть из текущей. Если очередная выбранная точка совпала с заданной конечной точкой, то маршрут найден. Если не совпала, то делаем из этой точки еще шаг. Так как текущая точка может быть соединена с несколькими другими, то нужен какой-то формальный критерий выбора. В простейшем случае можно выбрать точку с наименьшим номером.

Пусть, например, надо найти все возможные пути из точки 1 в точку 5. Согласно принятому правилу, сначала выбираем точку 2. На следующем шаге выясняем, что точка 2 тупиковая, поэтому возвращаемся в точку 1 и делаем шаг в точку 3. Из точки 3 — в точку 4, из 4 — в 6 и из точки 6 — в точку 5. Один маршрут найден. После этого возвращаемся в точку 6 и проверяем, возможен ли шаг в точку, отличную от 5. Так как это возможно, то делаем шаг в точку 7, и затем — в 5. Найден еще один путь. Таким образом, процесс поиска состоит из шагов вперед и возвратов назад. Поиск завершается, если из узла начала движения уже некуда идти.

Алгоритм поиска имеет рекурсивный характер: чтобы сделать шаг, мы выбираем точку и опять делаем шаг, и так продолжаем до тех пор, пока не достигнем цели.

Таким образом, задача поиска маршрута может рассматриваться как задача выбора очередной точки (города) и поиска оставшейся части маршрута, т. е. имеет место рекурсия.

Граф можно представить двумерным массивом, который назовем тар (карта). Значение элемента массива map[i, j] — это расстояние между городами i и j, если города соединены дорогой, или ноль, если города не соединены прямой дорогой. Для приведенного графа массив тар можно изобразить в виде таблицы, представленной на Рисунок 12.10.

Примеры программ

Примеры программ

Поиск файлов

В качестве примера использования рекурсии рассмотрим задачу поиска файлов. Пусть нужно получить список всех файлов, например, с расширением bmp, которые находятся в указанном пользователем каталоге и во всех подкаталогах этого каталога.

Словесно алгоритм обработки каталога может быть представлен так:

1. Вывести список всех файлов удовлетворяющих критерию запроса.

2. Если в каталоге есть подкаталоги, то обработать каждый из этих каталогов.

Приведенный алгоритм (его блок-схема представлена на Рисунок 12.4) является рекурсивным: для того чтобы обработать подкаталог, процедура обработки текущего каталога должна вызвать сама себя.

Примеры работы программы вычисления факториала

Рисунок 12.2. Примеры работы программы вычисления факториала

Примеры работы программы вычисления факториала
Результат, представленный на Рисунок 12.2, б, не соответствует ожидаемому. Факториал числа 44 равен нулю! Произошло это потому, что факториал числа 44 настолько велик, что превысил максимальное значение для переменной типа integer, и, как говорят программисты, произошло переполнение с потерей значения.

Delphi может включить в исполняемую программу инструкции контроля диапазона значений переменных. Чтобы инструкции контроля были добавлены в программу, нужно во вкладке Compiler диалогового окна Project Options (Рисунок 12.3) установить флажок Overflow checking (Контроль переполнения), который находится в группе Runtime errors (Ошибки времени выполнения).

Рекурсивный алгоритм поиска файлов

Рисунок 12.4. Рекурсивный алгоритм поиска файлов

Рекурсивный алгоритм поиска файлов
Вид диалогового окна программы приведен на Рисунок 12.5, текст — в листинге 12.3.

Поле Файл (Edit1) используется для ввода имени искомого файла или маски (для поиска файлов одного типа). Имя каталога, в котором нужно выполнить поиск, можно ввести непосредственно в поле Папка или выбрать из стандартного диалогового окна Обзор папок, которое появляется в результате щелчка на кнопке Папка. Окно Обзор папок (Рисунок 12.6) выводит на экран стандартная функция Seiectoirectory. Следует обратить внимание, что имя каталога, который используется в диалоговом окне Обзор папок в качестве корневого, должно передаваться функции SeiectDirectory как Строка WhideChar. Для Преобразования обычной строки в строку WideChar использована функция StringToWhideChar.

Значения свойств компонента

Таблица 12.1. Значения свойств компонента stringGrid1

Свойство

Значение

Name

StringGrid1

ColCount

11

RowCount

11

FixedCols

1

FixedRows

1

Options . goEditing

TRUE

DefaultColWidth

16

DefaultRowHeight

14

Текст программы приведен в листинге 12.5.



Вкладка Compiler диалогового окна Project Options

Рисунок 12.3. Вкладка Compiler диалогового окна Project Options


Вкладка Compiler диалогового окна Project Options



Отладка программы в Delphi

Диалоговое окно Add Source Breakpoint

Рисунок 13.4. Диалоговое окно Add Source Breakpoint

Диалоговое окно Add Source Breakpoint
Точку останова можно добавить, щелкнув мышью на синей точке, помечающей ту инструкцию программы, перед которой надо поместить точку останова (если в программе нет ошибок, то компилятор помечает выполняемые инструкции программы синими точками).

Для точки останова можно задать условие, при выполнении которого программа приостановит свою работу в данной точке (например, если значение переменной равно определенной величине). Условие (логическое выражение) вводится в поле Condition диалогового окна Add Source Breakpoint.

Добавление имени переменной в список Watch List

Рисунок 13.7. Добавление имени переменной в список Watch List


Добавление имени переменной в список Watch List

Добавление точки останова

Добавление точки останова

Для того чтобы поставить в программу точку останова (breakpoint), нужно из меню Run выбрать команду Add Breakpoint (Добавить точку останова), затем из меню следующего уровня — команду Source Breakpoint.

В результате открывается диалоговое окно Add Source Breakpoint (Рисунок 13.4), в котором выводится информация о добавляемой точке останова. Поле Filename содержит имя файла программы, куда добавляется точка останова, поле Line number — номер строки программы, в которую добавляется точка останова. О назначении полей Condition (Условие) и Pass count (Число пропусков) будет сказано далее.

После щелчка на кнопке ОК точка останова добавляется в программу, и строка, в которой находится точка останова, помечается красной точкой и выделяется цветом (Рисунок 13.5).

Изменение характеристик точки останова

Изменение характеристик точки останова

Программист может изменить характеристики точки останова. Для этого надо из меню View выбрать команду Debug Windows, затем из меню следующего уровня — команду Breakpoints. В открывшемся диалоговом окне Breakpoint List (Рисунок 13.6) нужно щелкнуть правой кнопкой мыши в строке, содержащей информацию о нужной точке останова, и в появившемся контекстном меню выбрать команду Properties. В результате открывается диалоговое окно Source Breakpoint Properties, в котором можно изменить характеристики точки останова, например, изменить условие (содержимое поля Condition) остановки программы в данной точке. Используя это же контекстное меню, можно быстро перейти к инструкции, в которой находится точка останова; для этого надо выбрать команду Edit Source.

Классификация ошибок

Классификация ошибок

Ошибки, которые могут быть в программе, принято делить на три группы:

  • синтаксические;
  • ошибки времени выполнения;
  • алгоритмические.
  • Синтаксические ошибки, их также называют ошибками времени компиляции (Compile-time error), наиболее легко устранимы. Их обнаруживает компилятор, а программисту остается только внести изменения в текст программы и выполнить повторную компиляцию.

    Ошибки времени выполнения, в Delphi они называются исключениями (exception), тоже, как правило, легко устранимы. Они обычно проявляются уже при первых запусках программы и во время тестирования.

    При возникновении ошибки в программе, запущенной из Delphi, среда разработки прерывает работу программы, о чем свидетельствует заключенное в скобки слово Stopped в заголовке главного окна Delphi, и на экране появляется диалоговое окно, которое содержит сообщение об ошибке и информацию о типе (классе) ошибки. На Рисунок 13.1 приведен пример сообщения об ошибке, возникающей при попытке открыть несуществующий файл.

    После возникновения ошибки программист может либо прервать выполнение программы, для этого надо из меню Run выбрать команду Program Reset, либо продолжить ее выполнение, например, по шагам (для этого из меню Run надо выбрать команду Step), наблюдая результат выполнения каждой инструкции.

    Контроль значений переменных во время пошагового выполнения программы

    Рисунок 13.9. Контроль значений переменных во время пошагового выполнения программы

    Контроль значений переменных во время пошагового выполнения программы
    В окне редактора кода стрелкой помечена инструкция, которая будет выполнена на следующем шаге выполнения программы (при нажатии клавиши или при выборе команды Step Over из меню Run), в диалоговом окне Watch List выведены значения переменных.

    Существует еще один способ, позволяющий проверить значение переменной, не добавляя ее имя в список Watch List. Заключается он в следующем. После того как программа достигнет точки останова, в результате чего откроется окно редактора кода, нужно установить курсор мыши на имени переменной, значение которой надо проверить. В окне редактора кода появится окно подсказки, в котором будет выведено значение переменной (Рисунок 13.10).

    Чтобы завершить процесс пошагового выполнения программы, нужно из меню Run выбрать команду Program Reset.

    Контроль значения переменной без добавления имени в список Watch List

    Рисунок 13.10. Контроль значения переменной без добавления имени в список Watch List


     Контроль значения переменной без добавления имени в список Watch List



    Обработка исключения типа EZeroDivide

    Листинг 13.1. Обработка исключения типа EZeroDivide

    unit UsTry_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;

    Editl: TEdit; // напряжение
    Edit2: TEdit; // сопротивление

    Label5: TLabel; // результат расчета - ток

    Button1: TButton; //кнопка Вычислить

    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations )
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.Button1Click(Sender: TObject);

    var

    u: real; // напряжение
    r: real; // сопротивление
    i: real; // ток
    begin

    Labels.Caption := ' '; try

    // инструкции, которые могут вызвать исключение (ошибку)
    u := StrToFloat(Edit1.Text);

    r := StrToFloat(Edit2.Text);

    i := u/r;

    except // секция обработки исключений
    onEZeroDivide do // деление на ноль
    begin

    ShowMessage('Сопротивление не может быть равно нулю!');

    exit;
    end;

    on EConvertError do // ошибка преобразования строки в число
    begin

    ShowMessage('Напряжение и сопротивление должны быть ' +

    'заданы числом. ' +#13+
    'При записи дробного числа используйте запятую.';

    exit;
    end;
    end;

    Label5.Caption := FloatToStr(i) + ' A';
    end;

    end.

    В приведенной программе исключения могут возникнуть при вычислении величины тока. Если пользователь задаст, что сопротивление равно нулю, то при выполнении инструкции i:=u/r возникает Исключение EZeroDivide.

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

    Наблюдение значений переменных

    Наблюдение значений переменных

    Во время отладки, в частности, при выполнении программы по шагам, довольно часто бывает полезно знать, чему равно значение той или иной переменной. Отладчик позволяет наблюдать значения переменных программы.

    Для того чтобы во время выполнения программы по шагам иметь возможность контролировать значение переменной, нужно добавить имя этой переменной в список наблюдаемых элементов (Watch List). Для этого надо из меню Run выбрать команду Add Watch (Добавить наблюдаемый элемент) и в поле Expression появившегося диалогового окна Watch Properties (Рисунок 13.7) ввести имя переменной.

    Окно редактора кода после добавления точки останова

    Рисунок 13.5. Окно редактора кода после добавления точки останова

    Окно редактора кода после добавления точки останова
    Если для точки останова задано условие, то программа приостанавливает свою работу только в том случае, если выражение, находящееся в поле Condition, истинно (его значение равно TRUE).

    Кроме условия для точки останова, можно задать количество пропусков данной точки. Если во время добавления в программу точки останова в поле Pass count (Число пропусков) диалогового окна Add Source Breakpoint записать отличное от нуля число, то программа приостановит свою работу в этой точке только после того, как инструкция, находящаяся в строке, помеченной точкой останова, будет выполнена указанное число раз.

    Отладчик

    Отладчик

    Интегрированная среда разработки Delphi предоставляет программисту мощное средство поиска и устранения ошибок в программе — отладчик. Отладчик позволяет выполнять трассировку программы, наблюдать значения переменных, контролировать выводимые программой данные.

    Предотвращение и обработка ошибок

    Предотвращение и обработка ошибок

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

    Нарушение в работе программы называется исключением. Обработку исключений (ошибок) берет на себя автоматически добавляемый в выполняемую программу код, который обеспечивает, в том числе, вывод информационного сообщения. Вместе с тем Delphi дает возможность программе самой выполнить обработку исключения.

    Инструкция обработки исключения в общем виде выглядит так:

    try

    // здесь инструкции, выполнение которых может вызвать исключение

    except // начало секции обработки исключений
    on ТипИсключения1 do Обработка1;
    on ТипИсключения2 do Обработка2;

    on ТипИсключенияJ do ОбработкаJ;
    else

    // здесь инструкции обработки остальных исключений
    end;

    где:

  • try — ключевое слово, обозначающее, что далее следуют инструкции, при выполнении которых возможно возникновение исключений, и что обработку этих исключений берет на себя программа;
  • except — ключевое слово, обозначающее начало секции обработки исключений. Инструкции этой секции будут выполнены, если в программе возникнет ошибка;
  • on — ключевое слово, за которым следует тип исключения, обработку которого выполняет инструкция, следующая за do;
  • else — ключевое слово, за которым следуют инструкции, обеспечивающие обработку исключений, тип которых не указаны в секции except.
  • Как было сказано выше, основной характеристикой исключения является его тип. В таблице 13.1 перечислены наиболее часто возникающие исключения и указаны причины, которые могут привести к их возникновению.



    Результат добавления имени переменной в список Watch List

    Рисунок 13.8. Результат добавления имени переменной в список Watch List

    Результат добавления имени переменной в список Watch List
    В результате в список Watch List, содержимое которого отражается в диалоговом окне Watch List (Рисунок 13.8), будет добавлен новый элемент. Так как переменные программы существуют (и, следовательно, доступны) только во время выполнения программы, то после имени переменной выводится сообщение: process not accessible (процесс недоступен).

    В качестве примера на Рисунок 13.9 приведен вид окна редактора кода и окна Watch List во время пошагового выполнения программы сортировки массива.

    Сообщение об ошибке при запуске программы из Windows

    Рисунок 13.2. Сообщение об ошибке при запуске программы из Windows

    Сообщение об ошибке при запуске программы из Windows
    С алгоритмическими ошибками дело обстоит иначе. Компиляция программы, в которой есть алгоритмическая ошибка, завершается успешно. При пробных запусках программа ведет себя нормально, однако при анализе результата выясняется, что он неверный. Для того чтобы устранить алгоритмическую ошибку," приходится анализировать алгоритм, вручную "прокручивать" его выполнение.

    Сообщение об ошибке при запуске программы из Delphi

    Рисунок 13.1. Сообщение об ошибке при запуске программы из Delphi

    Сообщение об ошибке при запуске программы из Delphi
    Если программа запущена из Windows, то при возникновении ошибки на экране также появляется сообщение об ошибке, но тип ошибки (исключения) в сообщении не указывается (Рисунок 13.2). После щелчка на кнопке ОК программа, в которой проявилась ошибка, продолжает (если сможет) работу.

    Типичные исключения

    Таблица 13.1. Типичные исключения

    Тип исключения

    Возникает

    EZeroDivide

    При выполнении операции деления, если делитель равен нулю

    EConvertError

    При выполнении преобразования, если преобразуемая величина не может быть приведена к требуемому виду. Наиболее часто возникает при преобразовании строки символов в число

    Тип исключения

    Возникает

    EFilerError

    При обращении к файлу. Наиболее частой причиной является отсутствие требуемого файла или, в случае использования сменного диска, отсутствие диска в накопителе

    Следующая программа, вид диалогового окна которой приведен на Рисунок 13.3, а текст— в листинге 13.1, демонстрирует обработку исключений при помощи инструкции try.

    Точки останова программы

    Точки останова программы

    При отладке широко используется метод, который называют методом точек останова. Суть метода заключается в том, что программист помечает некоторые инструкции программы (ставит точки останова), при достижении которых программа приостанавливает свою работу, и программист может начать трассировку или проконтролировать значения переменных.

    Трассировка программы

    Трассировка программы

    Во время работы программы ее инструкции выполняются одна за другой со скоростью работы процессора компьютера. При этом программист не может определить, какая инструкция выполняется в данный момент, и, следовательно, определить, соответствует ли реальный порядок выполнения инструкций разработанному им алгоритму.

    В случае неправильной работы программы необходимо видеть реальный порядок выполнения инструкций. Это можно сделать, выполнив трассировку программы. Трассировка — это процесс выполнения программы по шагам (step-by-step), инструкция за инструкцией. Во время трассировки программист дает команду: выполнить очередную инструкцию программы.

    Delphi обеспечивает два режима трассировки: без захода в процедуру (Step over) и с заходом в процедуру (Trace into). Режим трассировки без захода в процедуру выполняет трассировку только главной процедуры, при этом трассировка подпрограмм не выполняется, вся подпрограмма выполняется за один шаг. В режиме трассировки с заходом в процедуру выполняется трассировка всей программы, т. е. по шагам выполняется не только главная программа, но и все подпрограммы.

    Для того чтобы начать трассировку, необходимо из меню Run выбрать команду Step over или Trace into. В результате в окне редактора кода будет выделена первая инструкция программы. Для того чтобы выполнить выделенную инструкцию, необходимо из меню Run выбрать команду Step over (нажать клавишу ) или Trace into (нажать клавишу ). После выполнения инструкции будет выделена следующая. Таким образом, выбирая нужную команду из меню Run, можно выполнить трассировку программы.

    Активизировать и выполнить трассировку можно при помощи функциональной клавиатуры. Команде Step over соответствует клавиша , а команде Trace into — клавиша .

    В любой момент времени можно завершить трассировку и продолжить выполнение программы в реальном темпе. Для этого надо из меню Run выбрать команду Run.

    При необходимости выполнить трассировку части программы следует установить курсор на инструкцию программы, с которой надо начать трассировку, и из меню Run выбрать команду Run to cursor или нажать клавишу . Затем, нажимая клавишу или клавишу , выполнить трассировку нужного фрагмента программы.

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


    Удаление точки останова

    Удаление точки останова

    Для того чтобы удалить точку останова, нужно в диалоговом окне Breakpoint List щелкнуть правой кнопкой мыши в строке, содержащей информацию о точке, которую надо удалить, и в появившемся контекстном меню выбрать команду Delete.

    Можно также в окне редактора кода щелкнуть мышью на красной точке, помечающей строку, в которой находится точка останова.

    Отладка программы в Delphi

    Диалоговое окно Сноски

    Рисунок 14.1. Диалоговое окно Сноски

    Диалоговое окно Сноски
    В результате в документ будет вставлена сноска #, и в нижней части окна документа появится окно ввода текста сноски, в котором рядом со значком сноски следует ввести идентификатор помечаемого раздела справки (Рисунок 14.2).

    В качестве идентификатора можно использовать аббревиатуру заголовка раздела справки или сквозной номер раздела, поставив перед ним, например, буквы Ti (Topic Identifier). Однако лучше, чтобы идентификатор раздела справки начинался с префикса IDH_. В этом случае во время компиляции RTF-файла будет проверена корректность ссылок: компилятор выведет список идентификаторов, которые перечислены в разделе [MAP] файла проекта (см. ниже), но которых нет в RTF-файле.

    Диалоговое окно Tool Properties

    Рисунок 14.5. Диалоговое окно Tool Properties

    Диалоговое окно Tool Properties
    После запуска программы Microsoft Help Workshop на экране появляется главное окно программы.

    Для того чтобы приступить к созданию справочной системы, нужно из меню File выбрать команду New, затем в открывшемся диалоговом окне тип создаваемого файла — Help Project. В результате этих действий открывается окно Project File Name. В этом окне сначала надо выбрать папку, где находится программа, для которой создается справочная система, и где уже должен находиться файл документа справочной системы (RTF-файл). Затем в поле Имя файла нужно ввести имя файла проекта справочной системы. После щелчка на кнопке Сохранить открывается окно проекта справочной системы .

    Используя окно проекта справочной системы, можно добавить необходимые компоненты в проект, задать характеристики окна справочной системы, выполнить компиляцию проекта и пробный запуск созданной справочной системы.

    Для навигации по справочной информации можно использовать вкладку

    Рисунок 14.7. Для навигации по справочной информации можно использовать вкладку


    Для навигации по справочной информации можно использовать вкладку



    Добавление закладки

    Рисунок 14.8. Добавление закладки

    Добавление закладки
    Имя закладки должно отражать суть предполагаемого перехода к закладке, содержимое помечаемого фрагмента текста. В имени закладки пробел использовать нельзя. Вместо пробела можно поставить символ подчеркивания. Заголовки, оформленные стилем Заголовок, помечать закладками не надо. Таким образом, если в создаваемой справочной системе предполагаются переходы только к заголовкам разделов справочной информации, закладки допускается не вставлять. После этого можно приступить к расстановке гиперссылок.

    Чтобы вставить в документ ссылку на закладку или заголовок, который находится в этом же документе, надо выделить фрагмент текста (слово или фразу), который должен быть гиперссылкой, из меню Вставка выбрать команду Гиперссылка, в появившемся окне Добавление гиперссылки (Рисунок 14.9) сначала щелкнуть на кнопке Связать с местом в этом документе, затем — выбрать закладку или заголовок, к которому должен быть выполнен переход.

    Доступ к справочной информации

    Доступ к справочной информации

    Для того чтобы во время работы программы пользователь, нажав клавишу , мог получить справочную информацию, надо чтобы свойство HelpFile главного окна приложения содержало имя файла справочной системы, а свойство HelpContext числовой идентификатор нужного раздела (Рисунок 14.6). Вспомните, идентификаторы разделов справочной системы перечислены в разделе [MAP] файла проекта справочной системы.

    Файл документа справочной информации

    Файл документа справочной информации

    Файл документа справочной системы представляет собой RTF-файл определенной структуры. Создать RTF-файл справочной информации можно, например, при помощи Microsoft Word. Сначала нужно набрать текст разделов справки, оформив заголовки разделов одним из стилей Заголовок, например Заголовок1. При этом текст каждого раздела должен находиться на отдельной странице документа (заканчиваться символом "разрыв страницы").

    После того, как текст разделов будет набран, нужно, используя сноски (табл. 14.1), пометить заголовки разделов справочной информации (сноски используются компилятором справочной системы в процессе преобразования RTF-файла в HLP-файл, файл справки).



    Характеристики окна справочной системы

    Характеристики окна справочной системы

    Чтобы задать характеристики главного окна справочной системы, надо в окне проекта нажать кнопку Windows и в поле Create a window named открывшегося окна Create a window, ввести слово main.

    В результате щелчка на ОК появляется окно Window Properties, в поле Title bar text вкладки General которого нужно ввести заголовок главного окна создаваемой справочной системы.

    Используя вкладку Position диалогового окна Window Properties, можно задать положение и размер окна справочной системы (Рисунок 14.13). На вкладке Position находится кнопка Auto-Sizer, при нажатии которой открывается окно Help Window Auto-Sizer (Рисунок 14.14), размер и положение которого определяется содержимым полей вкладки Position. При помощи мыши можно

    менять размер и положение этого окна. После нажатия кнопки ОК координаты и размер окна Help Window Auto-Sizer будут записаны в поля вкладки Position.

    Используя вкладку Color , можно задать цвет фона области заголовка раздела справки (Nonscrolling area color) и области текста справки (Topic area color). Для этого надо нажать соответствующую кнопку Change и в стандартном окне Цвет выбрать нужный цвет.

    Использование HTML Help Workshop

    Использование HTML Help Workshop

    Подготовить HTML-файл можно и при помощи HTML-редактора, входящего в состав HTML Help Workshop. Однако для этого надо знать хотя бы основы HTML — языка гипертекстовой разметки (далее приведены краткие сведения об HTML, которых достаточно для того, чтобы создать вполне приличную справочную систему).

    Чтобы создать HTML-файл, надо запустить HTML Help Workshop, из меню File выбрать команду New | HTML File и в появившемся окне HTML Title задать название раздела справки, текст которого будет находиться в создаваемом файле.

    После щелчка на кнопке ОК становится доступным окно HTML-редактора, в котором находится шаблон HTML-документа. В этом окне, после строки , можно набирать текст.

    Использование редактора Microsoft Word

    Использование редактора Microsoft Word

    Сначала нужно набрать текст разделов справки (каждый раздел в отдельном файле). Заголовки разделов и подразделов нужно оформить одним из стилей Заголовок. Заголовки разделов, как правило, оформляют стилем Заголовок1, подразделов — Заголовок2.

    Следующее, что надо сделать, — вставить закладки в те точки документа, в которые предполагаются переходы из других частей документа. Чтобы вставить в документ закладку, нужно установить курсор в точку текста, в которой должна быть закладка, из меню Вставка выбрать команду Закладка и в поле Имя закладки диалогового окна Закладка (Рисунок 14.8) ввести имя закладки.

    Компиляция проекта

    Компиляция проекта

    После того, как будет подготовлен файл проекта, можно выполнить компиляцию, щелкнув на находящейся в окне проекта кнопке Save and Compile. Однако первый раз компиляцию проекта справочной системы лучше выполнить выбором из меню File команды Compile, в результате выполнения которой открывается диалоговое окно Compile a Help File (Рисунок 14.19).

    В этом окне следует установить флажок Automatically display Help file in WinHelp when done (Автоматически показывать созданную справочную систему по завершении компиляции), а затем нажать кнопку Compile. По завершении компиляции на экране появляется окно с информационным сообщением о результатах компиляции и, если компиляция выполнена успешно, окно созданной справочной системы. Созданный компилятором файл справочной системы (HLP-файл) будет помещен в ту папку, в которой находится файл проекта.


    Компиляция

    Компиляция

    Компиляция — это процесс преобразования исходной справочной информации в файл справочной системы (СНМ-файл).

    Исходной информацией для HTML Help компилятора являются:

  • файл проекта (ННР-файл);
  • файл контекста (ННС);
  • файлы справочной информации (НТМ-файлы);
  • файлы иллюстраций (GIF- и JPG-файлы).
  • Результатом компиляции является файл справочной системы (СНМ-файл).

    Чтобы выполнить компиляцию, надо из меню File выбрать команду Compile, в появившемся диалоговом окне Create a compiled file установить переключатель Automatically display compiled help file when done

    (после компиляции показать созданный файл справки) и щелкнуть на кнопке Compile. В результате этого будет создан файл справки, и на экране появится окно справочной системы, в котором будет выведена информация главного раздела.


    Описание класса THhореn

    Листинг 14.1. Описание класса THhореn

    THhopen = class(Telecontrol)
    private

    FIntf: _DHhopen;

    function GetControlInterface: _DHhopen;
    protected

    procedure CreateControl;

    procedure InitControlData;
    override;
    public

    function OpenHelp(const HelpFile: WideString;

    const HelpSection: WideString): Integer;

    procedure CloseHelp;

    property ControlInterface:_DHhopen
    read GetControlInterface;

    property DefaultInterface:_DHhopen
    read GetControlInterface;
    published

    property isHelpOpened: WordBool index 1
    read GetWordBoolProp
    write SetWordBoolProp
    stored False;
    end;

    Класс тньореп предоставляет два метода: OpenHelp и CloseHelp.

    Метод OpenHeip обеспечивает вывод справочной информации, метод close-Help — закрывает окно справочной системы.

    У метода openHeip два параметра — имя файла справочной информации и имя раздела, содержимое которого будет выведено. В качестве имени раздела надо использовать имя HTML-файла, который применялся программой HTML Help Workshop в процессе создания СНМ-файла. Следует обратить внимание на то, что оба параметра должны быть строками widechar.

    Следующая программа, ее диалоговое окно приведено на Рисунок 14.10, а текст — в листинге 14.2, демонстрирует использование ActiveX-компонента Hhopen для вывода справочной информации. Компонент нпореп добавляется в форму обычным образом. Так как во время работы программы он не отображается, то его можно поместить в любое место формы.

    Использование компонента Hhopen unit ushh_;

    Листинг 14.2. Использование компонента Hhopen unit ushh_;

    interface

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls,
    Forms, Dialogs, OleCtrls, HHOPENLibJTLB, StdCtrls;

    type

    TForm1 = class(TForm) Label1: TLabel;

    Editl: TEdit; // файл справки

    Edit2: TEdit; //раздел справки (имя HTML-файла)

    Button1: TButton; // кнопка Справка

    Hhopen1: THhopen; // ActiveX-компонент Hhopen

    Label2: TLabel;

    Label3: TLabel;

    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    // щелчок на кнопке Справка

    procedure TForm1.ButtonlClick(Sender: TObject);


    var

    HelpFile : string; // файл справки

    HelpTopic : string; // раздел справки

    pwHelpFile : PWideChar;
    // файл справки (указатель на строку WideChar)

    pwHelpTopic : PWideChar;
    // раздел (указатель на строку WideChar)
    begin

    HelpFile := Edit1.Text;

    HelpTopic := Edit2.Text;

    // выделить память для строк WideChar
    GetMemfpwHelpFile, Length(HelpFile) * 2) ;
    GetMemfpwHelpTopic, Length(HelpTopic)*2);


    // преобразовать Ansi-строку в WideString-строку

    pwHelpFile := StringToWideChar
    (HelpFile,pwHelpFile,MAX_PATH*2)
    pwHelpTopic := StringToWideChar(HelpTopic,pwHelpTopic,32);

    // вывести справочную информацию
    Form1.Hhopen1.OpenHelp(pwHelpFile,pwHelpTopic);


    end;

    end.

    Вывод справочной информации выполняет процедура обработки события Onciic на кнопке Справка. Так как параметры метода OpenHelp должны быть строками widechar, то сначала выполняется преобразование ANSI-строки В строку WideChar.

    Назначение числовых значений идентификаторам разделов справки

    Назначение числовых значений идентификаторам разделов справки

    Чтобы программа, использующая справочную систему, могла получить доступ к конкретному разделу справочной информации, нужно определить числовые значения для идентификаторов разделов. Чтобы это сделать, надо в окне проекта справочной системы нажать кнопку Map, в результате чего откроется диалоговое окно Map. В этом окне нужно нажать кнопку Add и в поле Topic ID, открывшегося диалогового окна Add Map Entry , ввести идентификатор раздела справки, а в поле Mapped numeric value — соответствующее идентификатору числовое значение. В поле Comment можно ввести комментарий — название раздела справочной системы, которому соответствует идентификатор.

    Оформление ссылки на другой раздел справки

    Рисунок 14.3. Оформление ссылки на другой раздел справки

    Оформление ссылки на другой раздел справки
    Помимо ссылки, обеспечивающей переход к другому разделу справки, в документ можно вставить ссылку на комментарий — текст, появляющийся в всплывающем окне. Во время работы справочной системы ссылки на комментарии выделяются цветом и подчеркиваются пунктирной линией. При подготовке документа справочной системы комментарии, как и разделы справки, располагают на отдельной странице, однако текст комментария не должен иметь заголовка. Сноска # должна быть поставлена перед текстом комментария. Ссылка на комментарий оформляется следующим образом: сначала надо подчеркнуть одинарной линией слово, выбор которого должен вызвать появление комментария, затем сразу после этого слова вставить идентификатор комментария, оформив его как скрытый текст.

    Окно программы Использование ActiveX

    Рисунок 14.10. Окно программы Использование ActiveX

     Окно программы Использование ActiveX


    Основы HTML

    Основы HTML

    HTML-документ представляет собой текст, в который помимо обычного текста включены специальные последовательности символов — теги. Тег начинается символом < и заканчивается символом >. Теги используются программами отображения HTML-документов для форматирования текста в окне просмотра (сами теги не отображаются).

    Большинство тегов парные. Например, пара тегов <Н2> сообщает программе отображения HTML-документа, что текст, который находится между этими тегами, является заголовком второго уровня и должен быть отображен соответствующим стилем.

    В табл. 14.2 представлен минимальный набор тегов, используя которые можно подготовить HTML-файл с целью дальнейшего его преобразования в СНМ-файл справочной системы.



    Подготовка справочной информации

    Подготовка справочной информации

    Подготовить HTML-файл можно при помощи любого редактора текста. Наиболее быстро это можно сделать, если редактор позволяет сохранить набранный текст в HTML-формате. Если использовать обычный редактор, например, входящий в состав Windows Блокнот, то в этом случае придется изучить основы языка HTML.

    В простейшем случае вся справочная информация может быть помещена в один-единственный HTML-файл. Однако если для навигации по справочной системе предполагается использовать вкладку Содержание, в которой будут перечислены разделы справочной информации, то в этом случае информацию каждого раздела нужно поместить в отдельный HTML-файл. В качестве примера на Рисунок 14.7 приведено окно справочной системы программы Квадратное уравнение. Во вкладке Содержание три пункта. Это значит, что исходная справочная информация была представлена тремя HTML-файлами.

    Создание файла справки

    Создание файла справки

    После того как созданы HTML-файлы справочной информации, в которые помещены все необходимые для навигации по справочной системе гиперссылки, можно приступить к непосредственному созданию справочной системы.

    После запуска HTML Help Workshop надо из меню File выбрать команду New/Project и в окне New Project — Destination ввести имя файла проекта справочной системы. После щелчка на кнопке Далее в этом и следующем окне, окно HTML Help Workshop

    Первое, что надо сделать, — сформировать раздел [FILES], который должен включать имена HTML-файлов, содержащих справочную информацию по разделам. Чтобы добавить в раздел [FILES] имя файла, надо щелкнуть на кнопке Add/Remove topic files, затем, в появившемся диалоговом окне Topic Files — на кнопке Add и в появившемся стандартном диалоговом окне Открыть выбрать HTML-файл раздела справки. Если справочная информация распределена по нескольким файлам, то операцию добавления нужно повторить несколько раз. После того как в диалоговом окне Topic Files будут перечислены все необходимые для создания справочной информации HTML-файлы, нужно щелкнуть на кнопке ОК. В результате этих действий в файле проекта появится раздел [FILES], в котором будут перечислены HTML-файлы, используемые для создания справочной системы .

    Следующее, что надо сделать, — задать главный (стартовый) раздел и заголовок окна, в котором будет выводиться справочная информация. Текст заголовка и имя файла главного раздела вводятся соответственно в поля Title и Default file вкладки General диалогового окна Options, которое появляется в результате щелчка на кнопке Change project options.

    Если для навигации по справочной системе предполагается использовать вкладку Содержание, то надо создать файл контекста. Чтобы это сделать, нужно щелкнуть на вкладке Contents, подтвердить создание нового файла контекста и задать имя файла контекста, в качестве которого можно использовать имя проекта. В результате станет доступной вкладка Contents, в которую нужно ввести содержание — названия разделов справочной системы.

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

    Чтобы во вкладку Contents добавить элемент, соответствующий разделу справочной системы, нужно щелкнуть на кнопке Insert a heading, в поле Entry title появившегося диалогового окна Table of Contents Entry ввести название раздела и щелкнуть на кнопке Add. На экране появится окно Path or URL. В поле HTML titles этого окна будут перечислены названия разделов (заголовки HTML-файлов) справочной информации, которая находится во включенных в проект файлах (имена этих файлов указаны в разделе [FILES] вкладки Project). Если вместо названия раздела справочной информации будет указано имя файла, то это значит, что в этом файле нет тега . Выбрав (по заголовку или по имени) нужный файл нужно щелкнуть на кнопке ОК. В результате перечисленных выше действий во вкладке <b>Contents </b>появится строка с названием раздела справочной информации.<br> <br> Если нужно изменить значок, соответствующий добавленному разделу, то следует щелкнуть на кнопке <b>Edit selection </b>и, используя список <b>Image index </b>вкладки <b>Advanced </b>окна <b>Table of Contents, </b>выбрать нужный значок (обычно рядом с названием раздела или подраздела изображена книжка).<br> <br> Подраздел добавляется точно так же, как и раздел, но после того как подраздел будет добавлен, нужно щелкнуть на кнопке <b>Move selection right. </b>В результате чего уровень заголовка понизится, т. е. раздел станет подразделом.<br> <br> Элементы содержания, соответствующие темам справочной информации, добавляются аналогичным образом, но процесс начинается щелчком на кнопке <b>Insert a page.</b><br> <br> Иногда возникает необходимость изменить порядок следования элементов списка содержания или уровень иерархии элемента списка. Сделать это можно при помощи командных кнопок, на которых изображены стрелки. Кнопки <b>Move selection up и Move selection down </b>перемещают выделенный элемент списка, соответственно, вверх и вниз. Кнопка <b>Move selection right </b>перемещает выделенный элемент вправо, т. е. делает его подчиненным предыдущему элементу списка. Кнопка <b>Move selection left </b>выводит элемент из подчиненности предыдущему элементу.<br><br> <h1>Создание справочной системы</h1>Создание справочной системы <br><br> Создание проекта справочной системы<br> <br> После того как создан файл справочной информации системы (RTF-файл), можно приступить к созданию справочной системы (HLP-файла). Для этого удобно воспользоваться программой Microsoft Help Workshop, которая поставляется вместе с Delphi и находится в файле Hcw.exe.<br> <br> Запустить Microsoft Help Workshop можно из Windows или из Delphi, выбрав из меню <b>Tools </b>команду <b>Help Workshop.</b><br> <br> Если в меню <b>Tools </b>команды <b>Help Workshop </b>нет, то надо из этого же меню выбрать команду <b>Configure Tools </b>и в открывшемся диалоговом окне <b>Tool Options </b>(Рисунок 14.4) щелкнуть на кнопке Add. В результате этого откроется диалоговое окно <b>Tool Properties </b>(Рисунок 14.5), в поле <b>Title </b>которого надо ввести название программы — Help workshop, а в поле <b>Program </b>— полное (т. е. с указанием пути) имя исполняемого файла программы Microsoft Help<br> <br> <b>Workshop— </b>C:\Program Files\Borland\Delphi7\Help\Tools\HCW.exe. Для ввода имени файла можно воспользоваться кнопкой <b>Browse.</b><br><br> <h1>Свойство HelpFile должно содержать имя файла справки</h1>Рисунок 14.6. Свойство HelpFile должно содержать имя файла справки<br><br><img src="image/svojstvo-helpfile-dolzhno-soderzhat-imja-fajla_1.gif" alt="Свойство HelpFile должно содержать имя файла справки"><br> Файл справочной системы приложения лучше поместить в ту папку, в которой находится файл исполняемой программы.<br> <br> Для каждого компонента формы, например поля ввода, можно задать свой раздел справки. Раздел справки, который появляется, если фокус находится на компоненте, и пользователь нажимает клавишу <F1>, определяется значением свойства Heipcontext этого компонента. Если значение свойства HelpContext элемента управления равно нулю, то при нажатии клавиши <F1> появляется тот раздел справки, который задан для формы приложения.<br> <br> Если в диалоговом окне есть кнопка <b>Справка, </b>то справочная информация выводится по-другому — для кнопки создается процедура обработки события onclick, которая обращением к функции winheip запускает программу Windows Help (файл Winhlp32.exe). При вызове функции winheip в качестве параметров указываются: идентификатор окна, которое запрашивает справочную информацию; имя файла справочной системы; константа, определяющая действие, которое должна выполнить программа Windows Help и уточняющий параметр.<br> <br> <b>Примечание</b><br> <br> Идентификатор окна — это свойство Handle формы приложения. Свойство Handle доступно только во время работы программы, поэтому в списке свойств в окне Object Inspector его нет.<br> <br> Если необходимо вывести конкретный раздел справки, то в качестве параметра, определяющего действие, используется константа HELP_CONTEXT. Уточняющий параметр в этом случае задает раздел справки, который будет выведен на экран.<br> <br> Ниже, в качестве примера, приведена процедура обработки события Onclick для кнопки <b>Справка </b>(Button4) диалогового окна программы решения квадратного уравнения.<br> <br> // щелчок на кнопке Справка<br> <br> <b>procedure </b>TForm1.Button4Click(Sender: TObject);<br> <br> <b>begin</b><br> <br> winhelp(Form1.Handle,'sqroot.hip',HELP_CONTEXT,1); end;<br> <br> <b>HTML Help Workshop</b><br> <br> Современные программы выводят справочную информацию в Internet-стиле — окно, которое используется для вывода справки, напоминает окно Internet Explorer. И это не удивительно, так как для вывода справочной информации используются компоненты, составляющие основу Microsoft Internet Explorer. Система отображения справочной информации является частью операционной системы, поэтому никакие дополнительные средства для вывода справочной информации не нужны.<br> <br> Физически справочная информация находится в файлах с расширением chm. СНМ-файл — это так называемый компилированный HTML-документ. СНМ-файл получается путем компиляции (объединения) файлов, составляющих HTML-документ, который, как правило, состоит из нескольких HTML-файлов.<br> <br> Процесс преобразования HTML-документа в справочную систему называют компиляцией. Исходной информацией для компилятора справочной системы являются HTML-файлы, файлы иллюстраций и файл проекта. В результате компиляции получается СНМ-файл, содержащий всю справочную информацию.<br> <br> Наиболее просто создать справочную систему можно при помощи программы Microsoft HTML Help Workshop.<br> <br> Чтобы создать справочную систему, нужно:<br> <br> <li>подготовить файлы справочной информации;<br> </li> <li> создать файл проекта;<br> </li> <li> создать файл контекста (содержания);<br> </li> <li> выполнить компиляцию.<br> </li> Последние три из перечисленных выше шагов выполняются в программе HTML Help Workshop.<br><br> <h1>Сноски используемые для разметки RTFфайла</h1>Таблица 14.1. Сноски, используемые для разметки RTF-файла<br><br> <table border=1> <tr> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td> </td> <td> <b>Сноска</b><br> <br> </td> <td> <b>Назначение</b><br> <br> </td> <td> </td> </tr> <tr> <td> </td> <td> #<br><br> $<br><br> к<br> <br> </td> <td> Задает идентификатор раздела справки, который может использоваться в других разделах для перехода к помеченному этой сноской разделу<br> <br> Задает имя раздела, которое будет использоваться для идентификации раздела справки в списке поиска и в списке просмотренных тем во время использования справочной системы<br> <br> Задает список ключевых слов, при выборе которых из списка диалога поиска осуществляется переход к разделу справки, заголовок которой помечен этой сноской<br> <br> </td> <td> </td> </tr> <tr> <td> </td> <td> </td> <td> </td> <td> </td> </tr> </table> Для того чтобы пометить заголовок раздела сноской, нужно установить курсор перед первой буквой заголовка раздела и из меню <b>Вставка </b>выбрать команду <b>Сноска. В </b>открывшемся диалоговом окне <b>Сноски </b>(Рисунок 14.1) в группе <b>Вставить сноску </b>нужно установить переключатель в положение <b>обычную, </b>а в группе <b>Нумерация </b>— в положение <b>другая. </b>В поле ввода номера сноски следует ввести символ "#" и нажать кнопку <b>ОК.</b><br><br> <h1>HTMLтеги</h1>Таблица 14.2. HTML-теги<br><br> <table border=1> <tr> <td> </td> <td> </td> <td> </td> <td> </td> </tr> <tr> <td> </td> <td> <b>Тег</b><br> <br> </td> <td> <b>Пояснение</b><br> <br> </td> <td> </td> </tr> <tr> <td></td> <td><TITLE> Название Задает название HTML-документа. Программы отображения HTML-документов, как правило, выводят название документа в заголовке окна, в котором документ отображается. Если название не задано, то в заголовке окна будет выведено название файла

    Параметр BACKGROUND задает фоновый рисунок, BGCOLOR — цвет фона, TEXT — цвет символов НТМ L-документа



    Задает основной шрифт, который используется для отображения текста: FACE — название шрифта, SIZE — размер в относительных единицах. По умолчанию значение параметра SIZE равно 3. Размер шрифта заголовков (см. тег <н>) берется от размера, заданного параметром SIZE

    <Н1>

    Определяет текст, находящийся между тегами <Н1> и как заголовок уровня 1. Пара тегов <Н2> определяет заголовок второго уровня, а пара <нзх/нЗ> — третьего




    Конец строки. Текст, находящийся после этого тега, будет выведен с начала новой строки

    <в>

    Текст, находящийся внутри этой пары тегов, будет выделен полужирным



    Текст, находящийся внутри этой пары тегов, будет выделен курсивом

    <А NAME=" За кладка ">

    Помечает фрагмент документа закладкой. Имя закладки задает параметр NAME. Это имя используется для перехода к закладке

    <А HREF="Файл.htm#Закладка">

    Выделяет фрагмент документа как гиперссылку, при выборе которой происходит перемещение к закладке, имя которой указано в параметре HREF



    Выводит иллюстрацию, имя файла которой указано в параметре SRC

    - -- >

    Комментарий. Текст, находящийся между дефисами, на экран не выводится

    Набирается HTML-текст обычным образом. Теги можно набирать как прописными, так и строчными буквами. Однако, чтобы лучше была видна структура документа, рекомендуется записывать все теги строчными (большими) буквами. Следующее, на что надо обратить внимание — программы отображения HTML-документов игнорируют "лишние" пробелы и другие "невидимые" символы (табуляция, новая строка). Это значит, что для того, чтобы фрагмент документа начинался с новой строки, в конце предыдущей строки надо поставить тег <вк>, а чтобы между строками текста появилась пустая строка, в HTML-текст нужно вставить два тега <вк> подряд.

    Работая с HTML-редактором в программе HTML Help Workshop, в процессе набора HTML-текста можно увидеть, как будет выглядеть набираемый текст. Для этого надо из меню View выбрать команду In Browser или щелкнуть на командной кнопке, на которой изображен стандартный значок Internet Explorer.



    <ТITLE>Kвадратное уравнение






    <Н2>Квадратное уравне-ние
    Квадратное уравнение задается в общем виде следующим образом:


    AX2+BX+C=0


    где : А, В и С — коэффициенты при неизвестном X .


    Квадратное уравнение имеет
    <А HREF="sqroot_02.htm#Корни_уравнения">корни
    ( решение ), если <А HREF="sqroot_О3.htm#Дискриминант">дискриминант уравнения больше или равен нулю. Если дискриминант уравнения меньше нуля, то уравнение не имеет решения.





    CM.


    Дискриминант<ВК>

    KopHH уравнения<ВК>








    Включение в проект файла справочной информации (RTFфайла)

    Включение в проект файла справочной информации (RTF-файла)

    Для того чтобы добавить в проект файл справочной информации, нужно щелкнуть на кнопке Files и в открывшемся диалоговом окне Topic Files -кнопку Add. В результате откроется стандартное окно Открытие файла, используя которое следует выбрать нужный RTF-файл. В результате этих действий в окне проекта появится раздел [FILES], в котором будет указано имя файла справочной информации. Если справочная информация распределена по нескольким файлам, то операцию добавления файла нужно повторить.

    Вставка в документ сноски помечающей заголовок раздела справки

    Рисунок 14.2. Вставка в документ сноски, помечающей заголовок раздела справки

    Вставка в документ сноски помечающей заголовок раздела справки
    Как правило, разделы справки содержат ссылки на другие разделы. В окне справочной системы понятия (слова), выбор которых вызывает переход к другому разделу справки, выделяются отличным от основного текста справки цветом и подчеркиваются.

    Во время подготовки текста справочной информации, слово-ссылку, выбор которого должен обеспечить переход к другому разделу справки, следует подчеркнуть двойной линией и сразу за этим словом, без пробела, поместить идентификатор раздела справки, к которому должен быть выполнен переход. Вставленный идентификатор необходимо оформить как скрытый текст.

    На Рисунок 14.3 приведен вид окна редактора текста во время подготовки файла справочной информации для программы решения квадратного уравнения. Слово "дискриминант" помечено как ссылка на другой раздел справки (здесь предполагается, что раздел справки, в котором находятся сведения о дискриминанте, помечен сноской #, имеющей идентификатор IDH_2).

    Выбор точки документа для перехода по ссылке

    Рисунок 14.9. Выбор точки документа для перехода по ссылке

    Выбор точки документа для перехода по ссылке
    Если нужно вставить в документ ссылку на раздел справки, который находится в другом файле, то в диалоговом окне Добавление гиперссылки нужно щелкнуть на кнопке Файл и в появившемся стандартном окне выбрать имя нужного HTML-файла.

    После того как в документ будут помещены все необходимые гиперссылки, документ нужно сохранить в HTML-формате.

    Вывод справочной информации

    Вывод справочной информации

    Чтобы вывести справочную информацию, которая находится в СНМ-файле, нужно воспользоваться ActiveX-компонентом (элементом управления) ньореп, который входит в состав Windows и представляет собой специальную динамическую библиотеку (файл Hhopen.ocx).

    Первое, что следует сделать, — установить компонент Hhopen на одну из вкладок палитры компонентов. Для этого надо из меню Component выбрать команду Import ActiveX Control. На экране появится окно Import ActiveX, в котором будут перечислены все зарегистрированные в реестре Windows компоненты. В окне Import ActiveX, в списке зарегистрированных компонентов, нужно выбрать строку hhopen OLE Control module и щелкнуть на кнопке Install. В результате этого на экране появится диалоговое окно Install, в котором программист может выбрать пакет (packege — пакет, библиотека компонентов), в который будет добавлен устанавливаемый компонент. Компоненты, добавляемые программистом, "по умолчанию" добавляются в пакет dciusr. В результате щелчка на кнопке ОК выбранный компонент добавляется в пакет, и на экране появляется окно Package и запрос подтверждения процесса перекомпиляции пакета . По завершении процесса компиляции на экране появится окно, информирующее о том, что компонент добавлен в пакет и зарегистрирован . Значок компонента ньореп будет добавлен на вкладку ActiveX. В процессе компиляции будет создан файл представления компонента -- модуль HHOPENLib_TLIB.pas, который содержит описание методов, свойств и событий компонента.

    Модуль представления можно увидеть, загрузив его в редактор кода из каталога \Delphi 7\Lib. Пролистав в окне редактора кода модуль HHOPENLib_TLIB.pas, который представляет собой интерфейс для доступа к элементу управления, можно найти описание класса тньореп (листинг 14.1).



    Отладка программы в Delphi

    Диалоговое окно программы тестирования

    Рисунок 15.1. Диалоговое окно программы тестирования


    Диалоговое окно программы тестирования



    Файл теста

    Файл теста

    Тест представляет собой последовательность вопросов, на которые испытуемый должен ответить путем выбора правильного ответа из нескольких предложенных вариантов.

    Файл теста состоит из трех разделов:
  • раздел заголовка;
  • раздел оценок;
  • раздел вопросов.
  • Заголовок содержит общую информацию о тесте, например, о его назначении. Заголовок может состоять из нескольких строк. Признаком конца заголовка является точка, стоящая в начале строки.

    Вот пример заголовка файла теста:

    Сейчас Вам будут предложены вопросы о знаменитых памятниках и архитектурных сооружениях Санкт-Петербурга.

    Вы должны из предложенных нескольких вариантов ответа выбрать правильный.

    За заголовком следует раздел оценок, в котором приводятся названия оценочных уровней и количество баллов, необходимое для достижения этих уровней. Название уровня должно располагаться в одной строке. Вот пример раздела оценок:

    Отлично

    100

    Хорошо

    85

    Удовлетворительно

    60

    Плохо

    50

    За разделом оценок следует раздел вопросов теста.

    Каждый вопрос начинается текстом вопроса, за которым может следовать имя файла иллюстрации, размещаемое на отдельной строке и начинающееся символом \. Имя файла иллюстрации является признаком конца текста вопроса. Если к вопросу нет иллюстрации, то вместо имени файла ставится точка.

    После вопроса следуют альтернативные ответы. Текст альтернативного ответа может занимать несколько строк. В строке, следующей за текстом ответа, располагается оценка (количество баллов) за выбор этого ответа. Если альтернативный ответ не является последним для текущего ответа, то перед оценкой ставится запятая, если последний — то точка.

    Вот пример вопроса:

    Какую формулу следует записать в ячейку В5, чтобы вычислить сумму выплаты?

    \tab1.bmp

    =сумма(В2-В4)

    ,0

    =сумма(В2:В4)

    ,2

    =В2+ВЗ+В4

    .1

    В приведенном вопросе второй и третий ответы помечены как правильные (оценка за их выбор не равна нулю). При этом видно, что выбор второго альтернативного ответа дает более весомый вклад в общую сумму баллов.

    Ниже, в качестве примера, приведен текст файла вопросов для контроля знания истории памятников и архитектурных сооружений Санкт-Петербурга.

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

    Вы прекрасно знаете историю Санкт-Петербурга! 8

    Вы много знаете о Санкт-Петербурге, но на некоторые вопросы ответили неверно . 7

    Вы недостаточно хорошо знаете историю Санкт-Петербурга. 6

    Вы, наверное, только начали знакомиться с историей Санкт-Петербурга? 5

    Архитектор Исаакиевского собора:

    \isaak.bmp

    Доменико Трезини

    ,0

    Огюст Монферран

    ,1

    Карл Росси

    .0

    Александровская колонна воздвигнута как памятник, посвященный:

    \aleks.bmp

    деяниям императора Александра 1

    ,0

    подвигу народа в Отечественной войне 1812 года

    .1

    Архитектор Зимнего дворца:

    \herm.bmp

    Бартоломео Растрелли

    ,1

    Огюст Монферран

    ,0

    Карл Росси

    .0

    Памятник русской военной славы собор Божией Матери Казанской (Казанский собор) построен по проекту русского зодчего:

    A. Н. Воронихина

    ,1

    И. Е. Старова

    ,0

    B. И. Баженова .0

    Остров, на котором находится Ботанический сад, основанный императором

    Петром I, называется:

    \bot.bmp

    Заячий

    ,0

    Медицинский

    ,0

    Аптекарский

    .1

    Невский проспект получил свое название:

    по имени реки, на берегах которой расположен Санкт-Петербург

    , 0

    по имени близко расположенной Александро-Невской лавры

    ,1

    в память о знаменитом полководце Александре Невском

    .0

    Создатель скульптурных групп Аничкова моста. "Укрощение коня человеком":

    \klodt.bmp

    П. Клодт

    ,1

    Э. Фальконе

    .0

    Скульптор знаменитого монумента "Медный всадник":

    Э. Фальконе

    ,1

    П. Клодт

    .0

    Файл теста может быть подготовлен в текстовом редакторе Notepad или Microsoft Word. В случае использования Microsoft Word при сохранении текста следует указать, что надо сохранить только текст. Для этого в диалоговом окне Сохранить в списке Тип файла следует выбрать вариант Только текст (*.txt).

    Форма приложения

    Форма приложения

    На Рисунок 15.2 приведен вид стартовой формы Forml во время разработки программы. Эта форма будет использоваться как для вывода вопросов теста и ввода ответов пользователя, так и для вывода начальной информации о тесте и результатов тестирования.

    Поле метки Label3 предназначено для вывода текста вопроса, начальной информации о тесте и результатов тестирования.

    Поля Label 1, Label2, Label3 и Label 4 предназначены для вывода текста альтернативных ответов, а переключатели RadioButtoni, RadioButton2, RadioButton3 и RadioButton4 — для выбора ответа.

    Командная кнопка Buttonl предназначена для подтверждения выбора альтернативного ответа и перехода к следующему вопросу теста.

    Следует обратить внимание на недоступный (невидимый) во время работы переключатель RadioButton5. Перед выводом очередного вопроса он программно устанавливается в выбранное положение, что обеспечивает сброс (установку в невыбранное состояние) переключателей выбора ответа (RadioButton1i, RadioButton2, RadioButton3 И RadioButton4).

    На форме отсутствуют поля вывода

    Рисунок 15.7. Форма приложения Тест, версия 2

    На форме отсутствуют поля вывода
    На форме отсутствуют поля вывода альтернативных ответов и переключатели выбора правильного ответа. Они будут созданы во время работы программы.

    Объявление массива компонентов ничем не отличается от объявления обычного массива — указывается имя массива, диапазон изменения индекса и тип элементов массива. Ниже приведено объявление массивов компонентов формы разрабатываемой программы:

    answer: array[1..N_ANSWERS] of TLabel;

    // альтернативные ответы selector:

    array[1..N_ANSWERS+1] of TRadioButton;

    // кнопки выбора ответа

    Однако, для того чтобы компонент появился в форме, одного объявления недостаточно. Компонент — это объект Delphi, и его объявление — это только указатель на область памяти, который без наличия объекта ни на что не указывает. Создается компонент применением метода Create к указателю на компонент, в нашем случае — к элементу массива.

    Например, инструкции

    answer[1] := TLabel.Create(self) ;

    answer[1].Parent := Form1;

    создают компонент Label и помещают его в форму.

    После создания компонента программа должна выполнить его настройку, т. е. ту работу, которую во время создания формы приложения выполняет программист при помощи Object Inspector. Под настройкой понимается присваивание начальных значений тем свойствам компонента, предопределенные значения которых не отвечают предъявляемым требованиям.

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

    type

    TForm1 = class(TForm)

    Label5: TLabel; // поле вывода вопроса

    Image1: TImage; // область вывода иллюстрации

    Panel1: TPanel;

    Button1: TButton; // кнопка Ok, Дальше, Завершить

    procedure FormActivate(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure ButtonlClick(Sender: TObject);

    procedure SelectorClick(Sender: TObject);

    private

    { Private declarations } public

    { Public declarations } end;

    В отличие от других, сгенерированных Delphi, строк объявления типа, строка procedure SelectorClick(Sender: TObject) вставлена В объявление вручную.

    Примечание

    При создании процедуры обработки события для обычного компонента (компонента, который добавлен в форму во время разработки формы программы) Delphi автоматически генерирует заготовку процедуры обработки события и ее объявление. Программист должен написать только инструкции процедуры.

    В случае создания процедуры обработки события для компонента, который создается динамически, программист должен полностью написать текст процедуры и поместить ее объявление в объявление формы.

    После того как будет написана процедура обработки события, нужно связать эту процедуру с конкретным компонентом. Делается это путем присвоения имени процедуры обработки свойству, имя которого совпадает с именем обрабатываемого события. Например, инструкция

    selector[1].OnClick : = SelectorClick;

    задает процедуру обработки события Onclick для компонента selector [i]. В листинге 15.2 приведен полный текст программы Тест, версия 2.



    Форма приложения Test Значения свойств стартовой формы приведены в табл 15 1

    Рисунок 15.2. Форма приложения Test Значения свойств стартовой формы приведены в табл. 15.1.

    Форма приложения Test Значения свойств стартовой формы приведены в табл 15 1


    Форма приложения

    Форма приложения

    Главная (стартовая) форма игры Сапер 2002 приведена на Рисунок 15.11.

    Следует обратить внимание, что размер

    Рисунок 15.11. Главная форма программы Сапер 2002

    Следует обратить внимание, что размер
    Следует обратить внимание, что размер формы не соответствует размеру игрового поля. Нужный размер формы будет установлен во время работы программы. Делает это процедура обработки события OnFormActivate, которая на основе информации о размере игрового поля (количестве клеток по вертикали и горизонтали) и клеток устанавливает значение свойств ClientHeight и ClientWidth, определяющих размер клиентской области главного окна программы.

    Основное окно программы содержит компонент MainMenu1, который представляет собой главное меню программы. Значок компонента MainMenu находится на вкладке Standard (Рисунок 15.12).

    с операционной системой Windows, хорошо

    Игра Сапер 2002

    Всем, кто работает с операционной системой Windows, хорошо знакома игра Сапер. В этом разделе рассматривается аналогичная программа — игра Сапер 2002.

    Пример окна программы в конце игры, после того как игрок открыл клетку, в которой находится мина, приведен на Рисунок 15.8.

    Игра

    Игра

    Во время игры программа воспринимает нажатия кнопок мыши и, в соответствии с правилами игры, открывает клетки или ставит в клетки флажки.

    Основную работу выполняет процедура обработки события onMouseDown (ее текст приведен в листинге 15.6). Сначала процедура преобразует координаты точки, в которой игрок нажал кнопку мыши, в координаты клетки игрового поля. Затем делает необходимые изменения в массиве Pole и, если нажата правая кнопка, рисует в клетке флажок. Если нажата левая кнопка в клетке, в которой нет мины, то эта клетка открывается, на экран выводится ее содержимое. Если нажата левая кнопка в клетке, в которой есть мина, то вызывается процедура showPole, которая показывает все мины, в том числе и те, которые игрок не успел найти.



    Информация о программе

    Информация о программе

    При выборе из меню ? команды О программе на экране должно появиться одноименное окно (Рисунок 15.15).

    Клетке игрового поля соответствует элемент массива

    Рисунок 15.9. Клетке игрового поля соответствует элемент массива

    Клетке игрового поля соответствует элемент массива
    В начале игры каждый элемент массива, соответствующий клеткам игрового поля, может содержать число от 0 до 9. Ноль соответствует пустой клетке, рядом с которой нет мин. Клеткам, в которых нет мин, но рядом с которыми мины есть, соответствуют числа от 1 до 8. Элементы массива, соответствующие клеткам, в которых находятся мины, имеют значение 9.

    Элементы массива, соответствующие границе поля, содержат -3.

    В качестве примера на Рисунок 15.10 изображен массив, соответствующий состоянию поля в начале игры.

    Компонент MainMenu

    Рисунок 15.12. Компонент MainMenu

     Компонент MainMenu
    Значок компонента MainMenu можно поместить в любое место формы, так как во время работы программы он не виден. Пункты меню появляются в верхней части формы в результате настройки меню. Для настройки меню используется редактор меню, который запускается двойным щелчком левой кнопкой мыши на значке компонента или выбором из контекстного меню компонента команды Menu Designer. В начале работы над новым меню, сразу после добавления компонента к форме, в окне редактора находится один-единственный прямоугольник — заготовка пункта меню. Чтобы превратить эту заготовку в меню, нужно в окне Object Inspector в поле Caption ввести название меню.

    Если перед какой-либо буквой в названии меню ввести знак &, то во время работы программы можно будет активизировать этот пункт меню путем нажатия комбинации клавиши <Аlt> и клавиши, соответствующей символу, перед которым стоит знак &. В названии меню эта буква будет подчеркнута.

    Чтобы добавить в главное меню элемент, необходимо в окне редактора меню выбрать последний (пустой) элемент меню и ввести название нового пункта.

    Чтобы добавить в меню команду, необходимо выбрать пункт меню, в который нужно добавить команду, переместить указатель активного элемента меню в конец списка команд меню и ввести название команды.

    На Рисунок 15.13 приведено окно редактора меню, в котором находится меню программы Сапер 2002.

    После того как будет сформирована структура меню, нужно, используя окно Object Inspector, выполнить настройку элементов меню (выбрать настраиваемый пункт меню можно в окне формы приложения или из списка объектов в верхней части окна Object Inspector). Каждый элемент меню (пункты и команды) — это объект типа TMenuitem. Свойства объектов TMenuitem (табл. 15.7) определяют вид меню во время работы программы.

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

    Листинг 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>
    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
    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 <>
    " 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±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 (ido

    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.

    создадим пять меток для вывода

    Листинг 15.2. Программа тестирования, версия 2

    unit test2_;

    interface

    uses

    SysUtils, WinTypes, WinProcs,

    Messages, Classes, Graphics,

    Controls, Forms, Dialogs,

    StdCtrls, ExtCtrls;

    type

    TForm1 = class(TForm)

    Label5: TLabel; // поле вывода вопроса

    Image1: TImage; // область вывода иллюстрации

    Panel1: ТPanel; Button1: TButton;

    // кнопка Ok, Дальше, Завершить

    procedure FormActivate(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure ButtonlClick(Sender: TObject);

    procedure SelectorClick(Sender: TObject);

    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1; // форма

    implementation

    const

    N_ANSWERS=4; // четыре варианта ответов

    N_LEVEL=4; // четыре уровня оценки

    var

    // динамически создаваемые компоненты

    answer: array[1..N_ANSWERS] of TLabel;

    // альтернативные ответы

    selector: array[1..N_ANSWERS+1] of TRadioButton;

    // кнопки выбора ответа

    f:TextFile;

    fn:string; // имя файла вопросов

    level:array[1..N_LEVEL] of integer;

    // сумма, соответствующая уровню

    mes:array[1..N_LEVEL] of string;

    // сообщение, соответствующее уровню

    score:array[1..N_ANSWERS] of integer;

    // очки за выбор ответа

    summa:integer; // набрано очков

    vopros:integer; // номер текущего вопроса

    n_otv:integer; // число вариантов ответа

    otv:integer; // номер выбранного ответа

    // установка формы в исходное состояние

    Procedure ResetForm(frm:TForm1);

    var

    i:integer; begin

    for i:=1 to N_ANSWERS do begin

    answer[i].width:=frm.ClientWidth-answer[i].left-5;

    answer[i].Visible:=FALSE; Selector[i].Visible:=FALSE;

    end;

    frm. Label5.width:=frm.ClientWidth-frm.Label5.left-5;

    frm. Image1.Visible:=False;

    end;

    // определение достигнутого уровня

    procedure Itog(suirana:integer;frm:TForm1);

    var

    i:integer; buf:string;

    begin buf: = ";

    str(summa:5,buf);
    buf:='Результаты тестирования'+chr(13)

    +'Всего баллов: '+buf; i:=1;

    while (summa < level[i]) and (ido

    i:=i+l;

    buf:=buf+chr(13)+mes[i];

    frm.Labels.caption:=buf;

    end;

    procedure TForm1.FormCreate(Sender: TObject);

    var

    i: integer; begin

    // создадим пять меток для вывода вопроса и альтернативных ответов

    for i:=l to N_ANSWERS do

    begin

    answer[i]:=TLabel.Create(self);

    answer[i].Parent:=Forml;

    answer[i].Left:=36;

    answer[i].Wordwrap:=True;

    end;

    // создадим переключатели для выбора ответа

    for i:=l to N_ANSWERS+1 do

    begin

    selector[i]:=TRadioButton.Create(self);

    selector[i].Parent:=self;

    selector[i].Caption:='';

    selector[i].Width:=17;

    selector[i].Left:=16;

    selector[i].Visible:=False;

    selector[i].Enabled:=True;

    selector[i].OnClick:=SelectorClick;

    end;

    ResetForm(Forml);
    end;

    // вывод начальной информации о тесте

    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] ='.';

    Form1.Labels.caption:=buf;

    end;

    // прочитать информацию об оценках за тест

    Procedure GetLevel(var f:TextFile);

    var

    i:integer; buf:string;

    begin // заполняем значения глобальных массивов i:=1;

    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 ScalePicture;

    var

    w,h:integer; // максимально допустимые размеры картинки

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

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

    scale:real; // общий коэф. масштабирования

    i:integer; begin

    // вычислить максимально допустимые размеры картинки

    w:=Form1.ClientWidth-Form1.Labels.Left;

    h:=Form1.ClientHeight

    - Form1.Panel1.Height -5

    - Form1.Label5.Top

    - Forml.Label5.Height - 5;

    for i:=1 to N_ANSWERS do

    if answer[i].Caption <>
    ''

    then h:=h-answer[i].Height-5;

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

    // определить масштаб

    if w>
    Form1.Image1.Picture.Width

    then scaleX:=1

    else scaleX:=w/Forml.Image1.Picture.Width;

    if h>
    Forml.Image1.Picture.Height

    then scaleY:=1

    else scaleY:=h/Form1.Image1.Picture.Height;

    if ScaleYOcaleX

    then scale:=scaleY

    else scale:=scaleX; // здесь масштаб определен

    Form1.Image1.Top:=

    Form1.Label5.Top+Forml.LabelS.Height+5;

    Form1.Image1.Left:=Form1.Label5.Left;

    Form1.Image1.Width:=

    Round(Form1.Image1.Picture.Width*scale);

    Form1.Image1.Height:=

    Round(Form1.Image1.Picture.Height*scale)

    Form1.Label5.Visible:=TRUE;

    end;

    // вывод вопроса на экран

    Procedure VoprosToScr(var f:TextFile;

    frm:TForm1;var vopros:integer),

    var

    i:integer; code:integer; s,buf:string;

    ifn:string; // файл иллюстрации

    begin

    vopros:=vopros+1 ;

    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[l] = '\'

    then // к вопросу есть иллюстрация

    begin

    frm.Image1.Tag:=1; ifn:=copy(s,2,length(s));


    try

    frm.Image1.Picture.LoadFromFile(ifn);
    except

    on E:EFOpenError do

    frm.tag:=0; end //

    try

    end

    else frm. Image1.Tag: =0;

    // читаем варианты, ответов

    for i:=1 to N_ANSWERS do begin

    answer[i].caption:='';

    answer[i].Width:=frm.ClientWidth-Form1.Label5.Left-5;

    end; i:=l;

    repeat

    buf: = " ;

    repeat // читаем текст варианта ответа

    readln(f,s);

    if (s[l]<>
    '.') and (s[1] <>
    ',')

    then buf:=buf+s+' ';

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

    // прочитан альтернативный ответ

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

    answer[i].caption:=buf;

    i:=i+l;

    until s [1] = '.'; // здесь прочитана иллюстрация и альтернативные ответы

    if Form1.Image1.Tag =1 // есть иллюстрация к вопросу?

    then begin ScalePicture;

    Forml.Image1.Visible:=TRUE;

    end;

    // вывод альтернативных ответов

    i:=1;

    while (answer[i].caption <>
    ") and (i <= N_ANSWERS) do

    begin

    if i = 1 then

    if frm.Image1.Tag =1

    then answer[1].top:=frm.Image1.Top+frm.Image1.Height+5

    else answer[i].top:=frm.Label5.Top+frm.Label5.Height+5

    else

    answer [i] . top:=answer [i-1] .

    top+ answer [i-1] . height+5;

    selector[i] . top:=answer [i] .

    top; selectorfi] ,visible:=TRUE;

    answer [i] . visible : =TRUE; i:=i+l;

    end;

    end;

    {$R *.DFM}

    procedure TForml . FormActivate ( Sender : TOb j ect ) ;

    begin

    ResetForm ( Forml ) ;

    if ParamCount = 0 then begin

    Label3 . font . color : =clRed;

    Label5. caption: = 'He задан файл вопросов теста.1;

    Buttonl . caption : = ' Ok ' ; Buttonl.tag:=2;

    Buttonl . Enabled : =TRUE

    end else

    begin

    fn:=ParamStr (1) ;

    assignf ile ( f , fn) ;

    {$!-} reset (f) ;

    if IOResult=0 then

    begin

    Inf <>
    (f, Label3) ;

    GetLevel(f) ;

    end;

    summa:=0;

    end;

    end;

    procedure TForm1. ButtonlClick (Sender: TObject)

    begin

    case Button1.tag of

    0: begin

    Button1.caption:='Дальше';

    Buttonl.tag:=1;

    Selector[N_ANSWERS+1].Checked:=TRUE; // вывод первого вопроса

    Buttonl.Enabled:=False;

    ResetForm(Forml);


    VoprosToScr(f,Forml,vopros)

    end;

    1: begin // вывод остальных вопросов

    summa:=summa+score[otv];

    Selector[N_ANSWERS+1].Checked:=TRUE;

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

    if not eof(f)

    then VoprosToScr(f,Forml,vopros) else

    begin

    closefile(f);
    Button1.caption:='Ok';

    Forml.сарtiоn:='Результат';

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

    Itog(summa,Form1);


    end;

    end;

    2: begin // завершение работы

    Form1.Close;

    end;

    end;

    end;

    // щелчок на кнопке выбора ответа

    procedure TForml.SelectorClick(Sender: TObject);

    var

    i: integer;

    begin

    while selector[i].Checked = FALSE do

    i:=i+l;

    otv:=i;

    Buttonl.enabled:=TRUE;

    end;

    end.

    По сравнению с первым вариантом программа Тест, версия 2 обладает существенным преимуществом. Для ее модернизации, например для увеличения количества альтернативных ответов, достаточно изменить только описание именованной константы N_ANSWERS.

    Процедура NewGame

    Листинг 15.3. Процедура NewGame

    // новая игра — генерирует новое поле
    procedure NewGame ();


    row,col : integer; // координаты клетки (индексы массива)
    n : integer; // количество поставленных мин
    k : integer; // кол-во мин в соседних клетках
    begin

    // Очистим эл-ты массива, соответствующие клеткам
    // игрового поля
    for row :=1 to MR do
    for col :=1 to MC do Pole[row,col] := 0;

    // расставим мины

    Randomize О; // инициализация ГСЧ

    n := 0; // кол-во мин

    repeat

    row := Random(MR) + 1;
    col := Random(MC) + 1;
    if (Pole[row,col] <>
    9) then begin

    Pole[row,col] := 9; n := n+1;
    end;
    until (n = NM);


    // для каждой клетки вычислим // кол-во мин в соседних клетках
    for row := 1 to MR do
    for col := 1 to MC do

    if (Pole[row,col] <>
    9) then
    begin k :=0 ;

    if Pole[row-l,col-l] = 9 then k = k + 1;

    if Pole[row-1,col] =' 9 then k = k + 1;

    if Pole[row-1,col+1] = 9 then k = k + 1;

    if Pole[row,col-1] = 9 then k = k + 1;

    if Pole[row,col+1] = 9 then k = k + 1;

    if Pole[row+1,col-1] = 9 then k = k + 1;

    if Pole[row+1,col] = 9 then k = k + 1;

    if Pole[row+l,col+l] = 9 then k := k + 1;
    Pole[row,col] := k;
    end;

    status := 0; // начало игры
    nMin := 0; // нет обнаруженных мин
    nFlag := 0; // нет поставленных флагов
    end;

    После того как процедура NewGame расставит мины, процедура showPoie (ее текст приведен в листинге 15.4) выводит изображение игрового поля.



    Процедура ShowPole

    Листинг 15.4. Процедура ShowPole

    // Показывает поле

    Procedure ShowPoie(Canvas : TCanvas; status : integer);

    var

    row,col : integer;
    begin

    for row := 1 to MR do
    for col := 1 to MC do

    Kletka(Canvas, row, col, status);

    end;

    Процедура showPoie выводит изображение поля последовательно, клетка за клеткой. Вывод изображения отдельной клетки выполняет процедура Kletka, ее текст приведен в листинге 15.5. Процедура Kletka используется для вывода изображения поля в начале игры, во время игры и в ее конце. В начале игры (значение параметра status = 0) процедура выводит только контур клетки, во время игры — количество мин в соседних клетках или флажок, а в конце отображает исходное состояние клетки и действия пользователя. Информацию о фазе игры процедура Kletka получает через параметр status.



    Процедура Kletka

    Листинг 15.5. Процедура Kletka

    // выводит на экран изображение клетки

    Procedure Kletka(Canvas : TCanvas;
    row, col, status : integer);

    var

    x,y : integer; // координаты области вывода
    begin

    x := (col-1)* W + I; у := (row-1)* H + 1;

    if status = 0 then begin

    Canvas.Brush.Color := clLtGray;

    Canvas.Rectangle(x-1,y-1,x+W,y+H);


    exit;
    end;

    if Pole[row,col] < 100 then
    begin

    Canvas.Brush.Color := clLtGray; // неоткрытые — серые
    Canvas.Rectangle(x-1,y-l,x+W,y+H);


    // если игра завершена (status = 2), то показать мины
    if (status = 2) and (Pole[row,col] = 9)

    then Mina(Canvas, x, y) ; exit; end;

    // открытая клетка

    Canvas.Brush.Color := clWhite; // открытые белые

    Canvas.Rectangle(x-1,y-l,x+W,y+H);


    if (Pole[row,col] = 100)

    then exit; // клетка открыта, но она пустая

    if (Pole[row,col] >
    = 101)
    and (Pole[row,col] <= 108)
    then begin // в соседних клетках есть мины

    Canvas.Font.Size := 14;

    Canvas.Font.Color := clBlue;

    Canvas.TextOut(x+3,y+2,IntToStr(Pole[row,col] -100));


    exit;
    end;

    if (Pole[row,col] >
    = 200)
    then Flag(Canvas, x, y);


    if (Pole[row,col] = 109)
    then // на этой мине подорвались!
    begin

    Canvas.Brush.Color := clRed;
    Canvas.Rectangle(x-1,y-1,x+W,y+H);


    end;

    if ((Pole[row,col] mod 10) = 9)
    and (status = 2) then

    Mina(Canvas, x, y);

    end;

    Обработка события OnMouseDown на поверхности игрового поля

    Листинг 15.6. Обработка события OnMouseDown на поверхности игрового поля

    // нажатие кнопки мыши на игровом поле

    procedure TForm1.Form1MouseDown(Sender: TObject;
    Button: TMouseButton;

    Shift: TShiftState; X, Y: Integer);

    var

    row, col : integer;
    begin

    if status = 2 // игра завершена
    then exit;

    if status = 0 then // первый щелчок
    status := 1;

    // преобразуем координаты мыши в индексы

    // клетки поля

    row := Trunc(y/H) + 1;

    col := Trunc(x/W) + 1;

    if Button = mbLeft then

    begin

    if Pole[row,col] = 9 then

    begin // открыта клетка, в которой есть мина
    Pole[row,col] := Pole[row,col] + 100;
    status := 2; // игра закончена
    ShowPole(Form1.Canvas, status);

    end else
    if Pole[row,col] < 9 then

    Open(row,col);

    end else

    if Button = mbRight then

    if Pole[row,col] >
    200 then begin

    // уберем флаг и закроем клетку
    nFlag := nFlag — 1;

    Pole[row,col] := Pole[row,col]-200;
    // уберем флаг
    x := (col-D* W + 1; у := (row-1)* H + 1;
    Canvas.Brush.Color := clLtGray;
    Canvas.Rectangle(x-1,y-1,x+W,y+H);

    end else

    begin // поставить в клетку флаг
    nFlag := nFlag + 1; if Pole[row,col] = 9

    then nMin := nMin + 1;

    Pole[row,col]:=Pole[row,col]+200;
    // поставили флаг
    if (nMin = NM) and (nFlag = NM) then begin

    status := 2;
    // игра закончена
    ShowPole(Form1.Canvas, status);

    end

    else Kletka(Form1.Canvas, row, col, status);

    end;
    end;

    Вывод справочной информации

    Листинг 15.7. Вывод справочной информации

    // выбор из меню ? команды Справка
    procedure TForm1.N3Click(Sender: TObject);


    HelpFile : string; // файл справки

    HelpTopic : string; // раздел справки

    pwHelpFile : PWideChar;
    // файл справки (указатель на строку WideChar)

    pwHelpTopic : PWideChar;
    // раздел (указатель на строку WideChar)
    begin

    HelpFile := 'saper.chm';
    HelpTopic := 'saper_02.htm';

    // выделить память для
    WideChar-строк GetMem(pwHelpFile, Length(HelpFile) * 2);

    GetMem(pwHelpTopic, Length(HelpTopic)*2);


    // преобразовать ANSI-строку в WideString-строку

    pwHelpFile := StringToWideChar(HelpFile,
    pwHelpFile, MAX_PATH*2);


    pwHelpTopic := StringToWideChar(HelpTopic,
    pwHelpTopic,32);


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

    Form1.Hhopen1.OpenHelp(pwHelpFile,
    pwHelpTopic);


    end;

    Вывод окна О программе

    Листинг 15.8. Вывод окна О программе

    // выбор из меню ? команды О программе
    procedure TForm1.N4Click(Sender: TObject);

    begin

    AboutForm.Top :=
    Trunc(Forml.Top + Forml.Height/2 - AboutForm.Height/2);


    AboutForm.Left :=
    Trunc (Form1.Left +Form1 .Width/2

    - AboutForm. Width/2 }; AboutForm. ShowModal;
    end;

    Примечание

    Модальный диалог перехватывает все события, адресованные другим окнам приложения. Пока модальный диалог находится на экране, другие окна приложения не реагируют на действия пользователя. Для продолжения работы с приложением нужно закрыть модальный диалог. В большинстве программ в том числе и в Delphi, информация о программе реализована как модальный диалог.

    Если не предпринимать никаких усилий, то окно О программе появится в той точке экрана, в которой находилась форма во время ее разработки Вместе с тем, можно "привязать" это окно к главному окну программы так. чтобы оно появлялось в центре главного окна. Привязка осуществляется на основании информации о текущем положении главного окна программы (свойства тор и Left) и размере окна О программе. Окно О программе должно быть удалено с экрана в результате щелчка на кнопке Ok. Процедура обработки этого события приведена ниже.

    procedure TAboutForm.ButtonlClick (Sender: TObject) ;
    begin

    ModalResult := mrOk;
    end;

    Модуль главного окна программы Сапер

    Листинг 15.9. Модуль главного окна программы Сапер 2002

    unit saper_1;
    interface

    uses
    Windows, Messages, SysUtils, Classes,

    Graphics, Controls, Forms, Dialogs,
    Menus, StdCtrls, OleCtrls, HHOPENLib_TLB;

    type
    TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    N4: TMenuItem;
    Hhopen1: THhopen;

    procedure Form1Create(Sender: TObject);

    procedure Form1Paint(Sender: TObject);

    procedure Form1MouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);

    procedure N1Click(Sender: TObject);

    procedure N4Click(Sender: TObject);

    procedure N3Click(Sender: TObject);

    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    uses saper_2;

    {$R *.DFM}

    const
    MR = 10; // кол-во клеток по вертикали
    MC = 10; // кол-во клеток по горизонтали
    NM = 10; // кол-во мин

    W = 40; // ширина клетки поля
    H = 40; // высота клетки поля

    var
    Pole: array[0..MR+1, 0.. MC+1] of integer; // минное поле
    // значение элемента массива:
    // 0..8 - количество мин в соседних клетках
    // 9 - в клетке мина
    // 100..109 - клетка открыта
    // 200..209 - в клетку поставлен флаг

    nMin : integer; // кол-во найденных мин
    nFlag : integer; // кол-во поставленных флагов

    status : integer; // 0 - начало игры; 1- игра; 2 -результат

    Procedure NewGame();
    forward;

    // генерирует новое поле
    Procedure ShowPole(Canvas : TCanvas; status : integer);
    forward;// Показывает поле
    Procedure Kletka(Canvas : TCanvas; row, col, status : integer);
    forward; // выводит содержимое клетки
    Procedure Open( row, col : integer);
    forward;// открывает текущую и все соседние клетки, в которых нет мин
    Procedure Mina(Canvas : TCanvas; x, y : integer);
    forward; // Рисует мину
    Procedure Flag( Canvas : TCanvas; x, y : integer);
    forward;// Рисует флаг

    // выводит на экран содержимое клетки
    Procedure Kletka(Canvas : TCanvas; row, col, status : integer);

    var
    x,y : integer; // координаты области вывода
    begin
    x := (col-1)* W + 1;
    y := (row-1)* H + 1;

    if status = 0 then
    begin
    Canvas.Brush.Color := clLtGray;
    Canvas.Rectangle(x-1,y-1,x+W,y+H);

    exit;
    end;


    if Pole[row,col] < 100 then
    begin
    Canvas.Brush.Color := clLtGray; // не открытые - серые
    Canvas.Rectangle(x-1,y-1,x+W,y+H);

    // если игра завершена (status = 2), то показать мины
    if (status = 2) and (Pole[row,col] = 9)
    then Mina(Canvas, x, y);

    exit;
    end;


    // открываем клетку
    Canvas.Brush.Color := clWhite; // открытые белые
    Canvas.Rectangle(x-1,y-1,x+W,y+H);

    if ( Pole[row,col] = 100 )
    then exit; // клетка открыта, но она пустая

    if ( Pole[row,col] >
    = 101) and (Pole[row,col] <= 108 ) then
    begin
    Canvas.Font.Size := 14;
    Canvas.Font.Color := clBlue;
    Canvas.TextOut(x+3,y+2,IntToStr(Pole[row,col] -100 ));

    exit;
    end;

    if ( Pole[row,col] >
    = 200 ) then
    Flag(Canvas, x, y);

    if (Pole[row,col] = 109 ) then // на этой мине подорвались!
    begin
    Canvas.Brush.Color := clRed;
    Canvas.Rectangle(x-1,y-1,x+W,y+H);

    end;

    if ( (Pole[row,col] mod 10) = 9) and (status = 2) then
    Mina(Canvas, x, y);

    end;

    // Показывает поле
    Procedure ShowPole(Canvas : TCanvas; status : integer);

    var
    row,col : integer;
    begin
    for row := 1 to MR do
    for col := 1 to MC do
    Kletka(Canvas, row, col, status);

    end;

    // рекурсивная функция открывает текущую и все соседние
    // клетки, в которых нет мин
    Procedure Open( row, col : integer);

    begin
    if
    Pole[row,col] = 0 then
    begin
    Pole[row,col] := 100;
    Kletka(Form1.Canvas, row,col, 1);

    Open(row,col-1);

    Open(row-1,col);

    Open(row,col+1);

    Open(row+1,col);

    //примыкающие диагонально
    Open(row-1,col-1);

    Open(row-1,col+1);

    Open(row+1,col-1);

    Open(row+1,col+1);

    end
    else
    if
    (Pole[row,col] < 100) and ( Pole[row,col] <>
    -3 ) then
    begin
    Pole[row,col] := Pole[row,col] + 100;
    Kletka(Form1.Canvas, row, col, 1);

    end;
    end;


    // новая игра - генерирует новое поле
    procedure NewGame();

    var
    row,col : integer; // координаты клетки
    n : integer; // количество поставленных мин
    k : integer; // кол-во мин в соседних клетках
    begin
    // Очистим эл-ты массива, соответствующие клеткам
    // игрового поля.
    for row :=1 to MR do
    for col :=1 to MC do
    Pole[row,col] := 0;

    // расставим мины
    Randomize();
    // инициализация ГСЧ
    n := 0; // кол-во мин
    repeat
    row := Random(MR) + 1;
    col := Random(MC) + 1;
    if ( Pole[row,col] <>
    9) then
    begin
    Pole[row,col] := 9;
    n := n+1;
    end;
    until ( n = NM );

    // для каждой клетки вычислим
    // кол-во мин в соседних клетках
    for row := 1 to MR do
    for col := 1 to MC do
    if ( Pole[row,col] <>
    9 ) then
    begin
    k :=0 ;
    if Pole[row-1,col-1] = 9 then k := k + 1;
    if Pole[row-1,col] = 9 then k := k + 1;
    if Pole[row-1,col+1] = 9 then k := k + 1;
    if Pole[row,col-1] = 9 then k := k + 1;
    if Pole[row,col+1] = 9 then k := k + 1;
    if Pole[row+1,col-1] = 9 then k := k + 1;
    if Pole[row+1,col] = 9 then k := k + 1;
    if Pole[row+1,col+1] = 9 then k := k + 1;
    Pole[row,col] := k;
    end;
    status := 0; // начало игры
    nMin := 0; // нет обнаруженных мин
    nFlag := 0; // нет флагов

    end;

    // Рисует мину
    Procedure Mina(Canvas : TCanvas; x, y : integer);

    begin
    with Canvas do
    begin
    Brush.Color := clGreen;
    Pen.Color := clBlack;
    Rectangle(x+16,y+26,x+24,y+30);

    Rectangle(x+8,y+30,x+16,y+34);

    Rectangle(x+24,y+30,x+32,y+34);

    Pie(x+6,y+28,x+34,y+44,x+34,y+36,x+6,y+36);

    MoveTo(x+12,y+32);
    LineTo(x+26,y+32);

    MoveTo(x+8,y+36);
    LineTo(x+32,y+36);

    MoveTo(x+20,y+22);
    LineTo(x+20,y+26);

    MoveTo(x+8, y+30);
    LineTo(x+6,y+28);

    MoveTo(x+32,y+30);
    LineTo(x+34,y+28);

    end;
    end;


    // Рисует флаг
    Procedure Flag( Canvas : TCanvas; x, y : integer);

    var
    p : array [0..3] of TPoint; // координаты флажка и нижней точки древка
    m : array [0..4] of TPoint; // буква М
    begin
    // зададим координаты точек флажка
    p[0].x:=x+4; p[0].y:=y+4;
    p[1].x:=x+30; p[1].y:=y+12;
    p[2].x:=x+4; p[2].y:=y+20;
    p[3].x:=x+4; p[3].y:=y+36; // нижняя точка древка

    m[0].x:=x+8; m[0].y:=y+14;
    m[1].x:=x+8; m[1].y:=y+8;
    m[2].x:=x+10; m[2].y:=y+10;
    m[3].x:=x+12; m[3].y:=y+8;
    m[4].x:=x+12; m[4].y:=y+14;

    with Canvas do
    begin
    // установим цвет кисти и карандаша
    Brush.Color := clRed;
    Pen.Color := clRed;

    Polygon(p);
    // флажок

    // древко
    Pen.Color := clBlack;
    MoveTo(p[0].x, p[0].y);

    LineTo(p[3].x, p[3].y);

    // буква М
    Pen.Color := clWhite;
    Polyline(m);

    Pen.Color := clBlack;
    end;
    end;


    // выбор из меню ? команды О программе
    procedure TForm1.N4Click(Sender: TObject);

    begin
    AboutForm.Top := Trunc(Form1.Top + Form1.Height/2 - AboutForm.Height/2);

    AboutForm.Left := Trunc(Form1.Left +Form1.Width/2 - AboutForm.Width/2);

    AboutForm.ShowModal;
    end;

    procedure TForm1.Form1Create(Sender: TObject);

    var
    row,col : integer;
    begin
    // В неотображаемые эл-ты массива, которые соответствуют
    // клеткам по границе игрового поля запишем число -3.
    // Это значение используется функцией Open для завершения
    // рекурсивного процесса открытия соседних пустых клеток.
    for row :=0 to MR+1 do
    for col :=0 to MC+1 do
    Pole[row,col] := -3;

    NewGame();
    // "разбросать" мины
    Form1.ClientHeight := H*MR + 1;
    Form1.ClientWidth := W*MC + 1;
    end;

    // нажатие кнопки мыши на игровом поле
    procedure TForm1.Form1MouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);

    var
    row, col : integer;
    begin
    if
    status = 2 // игра завершена
    then exit;

    if status = 0 then // первый щелчок
    status := 1;

    // преобразуем координаты мыши в индексы
    // клетки поля
    row := Trunc(y/H) + 1;
    col := Trunc(x/W) + 1;

    if Button = mbLeft then
    begin
    if Pole[row,col] = 9 then
    begin // открыта клетка, в которой есть мина
    Pole[row,col] := Pole[row,col] + 100;
    status := 2; // игра закончена
    ShowPole(Form1.Canvas, status);

    end
    else if Pole[row,col] < 9 then
    Open(row,col);

    end
    else

    if Button = mbRight then
    if Pole[row,col] >
    200 then
    begin
    // уберем флаг и закроем клетку
    nFlag := nFlag - 1;
    Pole[row,col] := Pole[row,col] - 200; // уберем флаг
    x := (col-1)* W + 1;
    y := (row-1)* H + 1;
    Canvas.Brush.Color := clLtGray;
    Canvas.Rectangle(x-1,y-1,x+W,y+H);

    end
    else

    begin // поставить в клетку флаг
    nFlag := nFlag + 1;
    if Pole[row,col] = 9
    then nMin := nMin + 1;
    Pole[row,col] := Pole[row,col]+ 200; // поставили флаг
    if (nMin = NM) and (nFlag = NM) then
    begin
    status := 2; // игра закончена
    ShowPole(Form1.Canvas, status);

    end
    else
    Kletka(Form1.Canvas, row, col, status);

    end;
    end;


    // Выбор меню Новая игра
    procedure TForm1.N1Click(Sender: TObject);

    begin
    NewGame();

    ShowPole(Form1.Canvas,status);

    end;

    // выбор из меню ? команды Справка
    procedure TForm1.N3Click(Sender: TObject);

    var
    HelpFile : string; // файл справки
    HelpTopic : string; // раздел справки
    pwHelpFile : PWideChar; // файл справки (указатель на WideChar строку)
    pwHelpTopic : PWideChar; // раздел (указатель на WideChar строку)
    begin
    HelpFile := 'saper.chm';
    HelpTopic := 'saper_02.htm';

    // выделить память для WideChar строк
    GetMem(pwHelpFile, Length(HelpFile) * 2);

    GetMem(pwHelpTopic, Length(HelpTopic)*2);

    // преобразовать Ansi строку в WideString строку
    pwHelpFile := StringToWideChar(HelpFile,pwHelpFile,MAX_PATH*2);

    pwHelpTopic := StringToWideChar(HelpTopic,pwHelpTopic,32);

    // вывести справочную информацию
    Form1.Hhopen1.OpenHelp(pwHelpFile,pwHelpTopic);

    end;

    procedure TForm1.Form1Paint(Sender: TObject);

    begin
    ShowPole(Form1.Canvas, status);

    end;
    end
    .

    Полный текст программы Сапер 2002

    Полный текст программы Сапер 2002 представлен ниже. В листинге 15.9 приведен модуль, соответствующий главной форме, В листинге 15.10 -форме О программе.



    Массив в начале игры

    Рисунок 15.10. Массив в начале игры

     Массив в начале игры
    В процессе игры состояние игрового поля меняется (игрок открывает клетки и ставит флажки) и, соответственно, меняются значения элементов массива. Если игрок поставил в клетку флажок, то значение соответствующего элемента массива увеличивается на 100. Например, если флажок поставлен правильно в клетку, в которой есть мина, то значение соответствующего элемента массива станет 109. Если флажок поставлен ошибочно, например, в пустую клетку, элемент массива будет содержать число 100. Если игрок открыл клетку, то значение элемента массива увеличивается на 200. Такой способ кодирования позволяет сохранить информацию о исходном состоянии клетки.

    Начало игры

    Начало игры

    В начале игры нужно расставить мины, затем для каждой клетки поля подсчитать, сколько мин находится в соседних клетках. Процедура NewGame (ее текст приведен в листинге 15.3) решает эту задачу.



    Настройка программы тестирования

    Рисунок 15.5. Настройка программы тестирования

    Настройка программы тестирования
    Примечание

    Текст, находящийся в поле Объект вкладки Ярлык диалогового окна Свойства, называется командной строкой.

    Программа может получить параметр, указанный в командной строке запуска программы, как значение функции ParamStr^), где л — номер параметра. Количество параметров командной строки находится в глобальной переменной ParamCount. Для приведенного выше примера командной строки запуска программы тестирования значение переменной ParamCount равно 1, а функции ParamStr (1) — peterb.txt.

    Ниже приведен фрагмент программы, обеспечивающий прием параметра из командной строки:

    if ParamCount = 0 then begin

    ShowMessage('Ошибка! Не задан файл вопросов теста.');
    goto bye; // аварийное завершение программы
    end;

    FileName := ParamStr(1); // имя файла — параметр командной строки

    При запуске программы, использующей параметры командной строки, из среды разработки параметры нужно ввести в поле Parameters диалогового окна Run Parameters (Рисунок 15.6), которое открывается в результате выбора из меню Run команды Parameters.

    Окно О программе

    Рисунок 15.15. Окно О программе

     Окно О программе
    Чтобы программа во время своей работы могла вывести на экран окно, отличное от главного (стартового), нужно создать это окно. Делается это выбором из меню File команды New form. В результате выполнения команды New form в проект добавляется новая форма и соответствующим ей модуль.

    Вид формы AboutForm после добавления необходимых компонентов приведен на Рисунок 15.16, значения ее свойств — в табл. 15.8.

    Окно справочной информации

    Рисунок 15.14. Окно справочной информации

     Окно справочной информации
    Процесс создания СНМ-файла подробно описан в гл. 14. Процедура, обеспечивающая вывод справочной информации, приведена в листинге 15.7.

    Примечание

    Перед непосредственным созданием процедуры, обеспечивающей вывод справочной информации, в главную форму необходимо добавить компонент HhOpen.



    Правила

    Правила

    Игровое поле состоит из клеток, в каждой из которых может быть мина. Задача игрока — найти все мины и пометить их флажками.

    Используя кнопки мыши, игрок может открыть клетку или поставить в нее флажок, указав тем самым, что в клетке находится мина. Клетка открывается щелчком левой кнопки мыши, флажок ставится щелчком правой. Если в клетке, которую открыл -игрок, есть мина, то происходит взрыв (сапер ошибся, а он, как известно, ошибается только один раз) и игра заканчивается. Если в клетке мины нет, то в этой клетке появляется число, соответствующее количеству мин, находящихся в соседних клетках. Анализируя информацию о количестве мин в клетках, соседних с уже открытыми, игрок может обнаружить и пометить флажками все мины. Ограничений на количество клеток, помеченных флажками, нет. Однако для завершения игры (выигрыша) флажки должны быть установлены только в тех клетках, в которых есть мины. Ошибочно установленный флажок можно убрать, щелкнув правой кнопкой мыши в клетке, в которой он находится.

    Представление данных

    Представление данных

    В программе игровое поле представлено массивом N+2 на M+2, где N xM — размер игрового поля. Элементы массива с номерами строк от 1 до N и номерами столбцов от 1 до М соответствуют клеткам игрового поля (Рисунок 15.9), первые и последние столбцы и строки соответствуют границе игрового поля.

    Справочная информация

    Справочная информация

    При выборе из меню ? команды Справка появляется справочная информация — правила игры (Рисунок 15.14).

    Структура меню программы

    Рисунок 15.13. Структура меню программы Сапер 2002

    Структура меню программы


    Свойство

    Свойство

    Значение

    Name

    Panell

    Caption



    Height

    46

    Align

    alBottom



    Значения свойств стартовой формы

    Таблица 15.1. Значения свойств стартовой формы

    Свойство

    Значение Пояснение

    Caption



    Height

    362

    Width

    562

    Color

    clWhite

    Font . Name

    Arial Cyr

    Borderlcons . biSystemMenu

    True Есть кнопка системного меню

    Borderlcons . biMinimize"

    False Нет кнопки Свернуть окно

    Borderlcons . biMaximize

    False Нет кнопки Развернуть окно

    BorderStyle

    bsSingle Тонкая граница окна, нельзя изменить размер окна

    Следует обратить внимание, что несмотря на то, что свойства Border-icons. biMinimize И Borderlcons.biMaximize имеют значение False, кнопки свернуть окно и Развернуть окно отображены в форме. Реальное воздей-

    ствие значения этих свойств на вид окна проявляется только во время работы программы. Значение свойства Borderstyle также проявляет себя только во время работы программы.

    В табл. 15.2—15.5 приведены значения свойств компонентов формы.



    Значения свойств компонентов Label1

    Таблица 15.2. Значения свойств компонентов Label1 -Label5

    Свойство

    Компонент



    Label1

    Label2

    Label3

    Label 4

    Label5

    Left

    32

    32

    32

    32

    32

    Тор

    64

    96

    128

    160

    8

    AutoSize

    True

    True

    True

    True

    True

    Wordwrap

    True

    True

    True

    True

    True



    Значения свойств компонентов RadioButton1

    Таблица 15.3. Значения свойств компонентов RadioButton1 —RadioButton5

    Свойство

    Компонент





    Radio-

    Button1

    Radio-

    Button2

    Radio-

    Button3

    Radio-

    Button4

    Radio-

    Button5

    Caption



    -







    Left

    8

    8

    8

    8

    8

    Top

    64

    96

    128

    160

    174

    Visible

    True

    True

    True

    True

    False



    Значения свойств кнопки

    Таблица 15.4. Значения свойств кнопки Button1

    Свойство

    Значение

    Name

    Buttonl

    Caption

    Ok

    Left

    13

    Top

    273

    Height

    28

    Width

    82



    Значения свойств панели

    Таблица 15.5. Значения свойств панели Panel1



    Свойства компонента image

    Таблица 15.6. Свойства компонента image

    Свойство

    Определяет

    Name

    Имя компонента

    Picture

    Свойство, являющееся объектом типа Tbitmap. Определяет выводимую картинку

    Left

    Расстояние от левого края формы до левой границы области картинки

    Top

    Расстояние от верхней границы формы до верхней границы области картинки

    Height

    Высоту картинки

    Width

    Ширину картинки

    Stretch Признак автоматического сжатия или растяжения картинки таким образом, чтобы она была видна полностью в области, размер которой задан свойствами width и Height
    AutoSize

    Признак автоматического изменения размера компонента в соответствии с реальным размером картинки.

    Если значение свойства AutoSize равно True, то при изменении значения свойства picture автоматически меняется размер области вывода иллюстрации так, чтобы была видна вся картинка.
    Если значение свойства AutoSize равно False, а размер картинки превышает размер области, то отображается только часть картинки

    Картинку, отображаемую в области image, можно задать во время создания формы или во время работы программы. Во время создания формы картинка задается установкой значения свойства Picture. Во время работы программы — Применением Метода LoadFromFile.

    Например, для разрабатываемого приложения инструкция вывода иллюстрации, находящейся в файле Isaak.bmp (изображение Исаакиевского собора), может быть такой:

    Image1.Picture.LoadFromFile('isaak.bmp');

    Очевидно, что размер области формы, которая может использоваться для вывода иллюстрации, зависит от длины (количества слов) вопроса, длины и количества альтернативных ответов. Чем длиннее вопрос и ответы, тем больше места в поле формы они занимают, и тем меньше места остается для иллюстрации.

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

    Свойства объекта TMenuItem

    Таблица 15.7. Свойства объекта TMenuItem

    Свойство

    Определяет

    Name

    Имя элемента меню. Используется для доступа к свойствам

    Caption

    Название меню или команды

    Bitmap

    Значок, который отображается слева от названия элемента меню

    Enabled

    Признак доступности элемента меню. Если значение свойства равно False, то элемент меню недоступен, при этом название меню отображается серым цветом

    При выборе во время работы программы элемента меню происходит событие Click. Чтобы создать процедуру обработки этого события, нужно в окне формы выбрать пункт меню и щелкнуть левой кнопкой мыши - Delphi создаст шаблон процедуры обработки этого события. В качестве примера ниже приведена процедура обработки события, которое возникает в результате выбора из меню ? команды Справка. N3 — это имя элемента меню, соответствующего этой команде.

    Значения свойств формы О программе

    Таблица 15.8. Значения свойств формы О программе

    Свойство

    Значение

    Name

    AboutForm

    Caption

    0 программе

    BorderStyle

    BsSingle

    Borderlcons . biSystemMenu

    False

    Borderlcons .biMininize

    False

    Borderlcons . biMaximize

    False

    Вывод окна О программе выполняет процедура обработки события click, которое происходит в результате выбора из меню ? команды О программе.

    Непосредственно вывод окна выполняет метод showModai, который выводит окно как модальный диалог.



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

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

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

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

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



    Требования к программе

    Требования к программе

    В результате анализа различных тестов были сформулированы следующие требования к программе:

  • программа должна обеспечить работу с тестом произвольной длины, т. е. не должно быть ограничения на количество вопросов в тесте;
  • вопрос может сопровождаться иллюстрацией;
  • для каждого вопроса может быть до четырех возможных вариантов ответа со своей оценкой в баллах;
  • результат тестирования должен быть отнесен к одному из четырех уровней, например, "отлично", "хорошо", "удовлетворительно" или "плохо";
  • вопросы теста должны находиться в текстовом файле;
  • программа должна быть инвариантна к различным тестам, т. е. изменения в тесте не должны вызывать требование изменения программы;
  • в программе должна быть заблокирована возможность возврата к предыдущему вопросу. Если вопрос предложен, то на него должен быть дан ответ.
  • На Рисунок 15.1 приведен пример диалогового окна программы тестирования во время ее работы.

    Усовершенствование программы

    Усовершенствование программы

    Очевидно, что приведенный выше текст программы был бы намного проше и изящней, если бы поля вывода альтернативных ответов и переключатели выбора ответов были бы объединены в массивы. Тогда программа могла бы обращаться к полям и переключателям не по имени, а по индексу.

    Delphi позволяет объединить компоненты в массив, однако создаваться такие компоненты должны не во время создания формы приложения, а динамически — во время работы программы.

    На Рисунок 15.7 приведен вид формы усовершенствованного приложения.

    Вычисление размера области вывода иллюстрации

    Рисунок 15.4. Вычисление размера области вывода иллюстрации

    Вычисление размера области вывода иллюстрации
    Если реальный размер иллюстрации превышает размер области, выделенной для ее вывода, то необходимо вычислить коэффициент масштабирования и установить максимально возможные, пропорциональные ширине и высоте иллюстрации, значения свойств width и Height области вывода иллюстрации.

    Реальные размеры иллюстрации, загруженной в область image 1, можно получить из свойств Image1.Picture.Bitmap.Width И Image1.Picture.Bitmap.Height.

    Вывод иллюстрации

    Вывод иллюстрации

    Для вывода иллюстрации в форму добавлен компонент image, значок которого (Рисунок 15.3) находится на вкладке Additional палитры компонентов. В табл. 15.7 приведены свойства компонента image.

    Загрузка файла теста

    Загрузка файла теста

    Передать имя файла теста программе тестирования можно через параметр командной строки путем настройки свойств значка, изображающего программу тестирования на рабочем столе или в папке.

    Например, для настройки программы тестирования, значок запуска которой находится на рабочем столе, на работу с файлом теста Peterb.txt необходимо щелкнуть правой кнопкой мыши на значке программы, из появившегося контекстного меню выбрать команду Свойства и в поле Объект, после имени файла программы (Testl.exe), ввести имя файла теста (Peterb.txt), заключив его в двойные кавычки (Рисунок 15.5).

    Отладка программы в Delphi

    Диалоговое окно Confirm

    Рисунок 16.12. Диалоговое окно Confirm

     Диалоговое окно Confirm
    В результате открывается окно редактора пакета Package (Рисунок 16.13), в котором в списке Contains (Содержимое) перечислены компоненты пакета.

    Диалоговое окно Install Component

    Рисунок 16.4. Диалоговое окно Install Component

    Диалоговое окно Install Component
    В поле Unit file name нужно ввести имя файла модуля. Для этого удобно воспользоваться кнопкой Browse.

    Поле Search path (Путь поиска) должно содержать разделенные точкой с запятой имена каталогов, в которых Delphi во время установки компонента будет искать необходимые файлы, в частности файл ресурсов компонента. Если имя файла модуля было введено в поле Unit file name выбором файла из списка, полученного при помощи кнопки Browse, то Delphi автоматически добавляет в поле Search path имена необходимых каталогов.

    Примечание

    Файл ресурса компонента должен находиться в одном из каталогов, перечисленных в поле Search path. Если его там нет, то компоненту будет назначен значок его родительского класса.

    Поле Package file name должно содержать имя пакета, в который будет установлен компонент. По умолчанию компоненты, создаваемые программистом, добавляются в пакет Dclusr70.dpk.

    Поле Package description содержит название пакета. Для пакета Dclusr70.dpk

    ЭТО текст: Borland User's Components.

    После заполнения перечисленных полей и нажатия кнопки ОК начинается процесс установки. Сначала на экране появляется окно Confirm (Рисунок 16.5), в котором Delphi просит подтвердить обновление пакета.

    Диалоговое окно New Component

    Рисунок 16.1. Диалоговое окно New Component

    Диалоговое окно New Component
    Поле Ancestor type должно содержать базовый тип для создаваемого компонента. Базовый тип компонента можно задать непосредственным вводом имени типа или выбором из раскрывающегося списка. Для разрабатываемого компонента базовым компонентом является стандартный компонент Edit (поле ввода-редактирования). Поэтому базовым типом для типа разрабатываемого компонента является тип TEdit.

    В поле Class Name необходимо ввести имя класса разрабатываемого компонента, например TNkEdit. Вспомните, что в Delphi имена типов должны начинаться буквой т.

    В поле Palette Page нужно ввести имя вкладки палитры компонентов, на которую после создания компонента будет добавлен его значок. Название вкладки палитры компонентов можно выбрать из раскрывающегося списка. Если в поле Palette Page ввести имя еще не существующей вкладки палитры компонентов, то непосредственно перед добавлением компонента вкладка с указанным именем будет создана.

    В поле Unit, file name находится автоматически сформированное имя файла модуля создаваемого компонента. Delphi присваивает модулю компонента имя, которое совпадает с именем типа компонента, но без буквы T. Щелкнув на кнопке с тремя точками, можно выбрать каталог, в котором должен быть сохранен модуль компонента.

    После нажатия кнопки ОК к текущему проекту добавляется сформированный Delphi-модуль, представляющий собой заготовку (шаблон) модуля компонента. Текст этого модуля приведен в листинге 16.1.



    Диалоговое окно Palette Properties

    Рисунок 16.16. Диалоговое окно Palette Properties

     Диалоговое окно Palette Properties
    Сначала в списке Pages необходимо выделить нужную вкладку палитры компонентов. Затем, если надо изменить порядок следования вкладок палитры компонентов, следует воспользоваться кнопками Move Up и Move Down и путем перемещения выбранного имени по списку Pages добиться нужного порядка следования вкладок.

    Если надо изменить порядок следования значков компонентов на вкладке, то в списке Components следует выбрать нужный значок компонента и кнопками Move Up и Move Down переместить значок на новое место.

    При необходимости изменить имя вкладки палитры следует в списке Pages выбрать имя нужной вкладки, нажать кнопку Rename и в поле Page name открывшегося диалогового окна Rename page (Рисунок 16.17) ввести новое имя.

    Форма приложения Поездка на дачу (поля вводаредактирования компонента NkEdit)

    Рисунок 16.9. Форма приложения Поездка на дачу (поля ввода-редактирования компонента NkEdit)

    Форма приложения Поездка на дачу (поля вводаредактирования компонента NkEdit)
    Внешне форма разрабатываемого приложения почти ничем не отличается от формы приложения Поездка на дачу, рассмотренного в гл. 6. Однако если выбранным компонентом будет поле ввода, то в окне Object Inspector указано, что текущим компонентом является компонент класса TNkEdit, a в списке свойств можно увидеть новое (по сравнению со списком свойств стандартного компонента Edit) свойство — Numb (Рисунок 16.10).

    Форма приложения Тест компонента NkEdit

    Рисунок 16.2. Форма приложения Тест компонента NkEdit

    Форма приложения Тест компонента NkEdit
    Форма содержит две метки и командную кнопку. Первая метка предназначена для вывода информационного сообщения, вторая метка (на рисунке она выделена) используется для вывода числа, введенного в поле редактирования. Самого поля редактирования компонента NkEdit в форме нет. Этот компонент будет создан динамически во время работы программы, но для него оставлено место над полем метки.

    После создания формы в модуль приложения, автоматически сформированный Delphi, необходимо внести следующие дополнения:

    1. В список используемых модулей (раздел uses) добавить имя модуля тестируемого компонента (NkEdit).

    2. В раздел объявления переменных (var) добавить инструкцию объявления компонента. Здесь следует вспомнить, что компонент является объектом, поэтому объявление компонента в разделе переменных не обеспечивает создание компонента, а только генерирует указатель на компонент, следовательно необходима инструкция вызова конструктора объекта, которая действительно создает компонент (объект).

    3. Для формы приложения создать процедуру обработки события oncreate, которая вызовом конструктора тестируемого компонента создаст компонент и установит значения его свойств.

    В листинге 16.3 приведен модуль приложения тестирования компонента NkEdit.



    Информационное сообщение о том что компонент больше недоступен

    Рисунок 16.15. Информационное сообщение о том, что компонент больше недоступен

     Информационное сообщение о том что компонент больше недоступен
    После перекомпиляции пакета необходимо закрыть окно редактора пакета и в открывшемся окне подтвердить сохранение изменений в пакете, из которого был удален компонент.

    Шаблон модуля компонента

    Листинг 16.1. Шаблон модуля компонента

    unit NkEdit; interface

    uses

    Windows, Messages, SysUtils, Classes, Controls, StdCtrls;

    type

    TEdit1 = class(TEdit)
    private

    { Private declarations }
    protected

    { Protected declarations }
    public

    { Public declarations }
    published

    { Published declarations }
    end;

    procedure Register;
    implementation

    procedure Register;
    begin

    RegisterComponents('Samples', [TNkEdit]);

    end;

    end.

    В объявлении нового класса указан только тип родительского класса. В раздел реализации помещена процедура Register, которая используется во время установки созданного программистом компонента на указанную вкладку палитры компонентов Delphi для регистрации нового класса.

    В сформированное Delphi объявление класса нового компонента нужно внести дополнения: объявить свойство, поле данных этого свойства, функцию доступа к полю данных, процедуру установки значения поля данных, конструктор и деструктор. Если на некоторые события компонент должен реагировать не так, как базовый, то в объявление класса нужно поместить описание соответствующих процедур обработки событий.

    В листинге 16.2 приведен текст модуля компонента NkEdit после внесения всех необходимых изменений.



    Модуль компонента NkEdit

    Листинг 16.2. Модуль компонента NkEdit

    unit NkEdit;
    interface

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls,
    Forms, Dialogs, StdCtrls;
    type

    TNkEdit = class(TEdit)
    private

    FNumb: single; // число, находящееся в поле редактирования

    // Это описание функции доступа

    // и процедуры установки поля FNumb

    function GetNumb: single;

    procedure SetNumb(value:single);

    protected

    procedure KeyPress(var Key: Char);

    override;
    public

    published

    constructor Create(AOwner:TComponent);

    override; property Numb : single
    // свойство компонента
    read GetNumb write SetNumb;
    end;

    procedure Register;
    implementation

    // процедура регистрации компонента

    procedure Register;

    begin

    RegisterComponents('Samples',[TNkEdit]);


    end;

    // конструктор компонента

    constructor TNkEdit.Create(AOwner:TComponent);


    begin

    // don't forget to call the ancestors' constructor

    inherited Create(AOwner);

    end;

    // функция доступа к полю FNumb
    function TNkEdit.GetNumb:single;
    begin

    try // поле Text может быть пустым Result:=StrToFloat(text);
    except

    on EConvertError do begin

    Result:=0; text: =' ' ;
    end;
    end;
    end;

    // процедура записи в поле FNumb
    procedure TNkEdit.SetNumb(Value:single);

    begin

    FNumb:=Value;

    Text:=FloatToStr(value);

    end;

    // процедура обработки события KeyPress
    procedure TNkEdit.KeyPress(var key:char) ;
    begin

    case key of

    '0'.. '9', #8, #13: ;

    '-': if Length(text)<>
    0 then key:=#0;

    else

    if not ((key = DecimalSeparator) and

    (Pos(DecimalSeparator,text)=0))
    then key:= #0;
    end;

    inherited KeyPress(key);

    // вызов процедуры обработки события

    // OnKeyPress родительского класса

    end;
    end.

    В описание класса TNkEdit добавлено объявление свойства Numb, которое представляет собой число, находящееся в поле редактирования. Для хранения Значения свойства Numb используется поле FNumb. Функция GetNumb необходима для доступа к полю FNumb, а процедура setNumb — для установки значения свойства.

    Конструктор класса TNkEdit сначала вызывает конструктор родительского класса (TEdit), присваивает значение свойству Text, затем устанавливает значение свойства Numb.

    Реакция компонента NkEdit на нажатие клавиши клавиатуры определяется процедурой обработки события TNkEdit.KeyPress, которая замещает соответствующую процедуру базового класса. В качестве параметра процедура TNkEdit.KeyPress получает код нажатой клавиши. Перед вызовом процедуры обработки события OnKeyPress родительского класса код нажатой клавиши проверяется на допустимость. Если нажата недопустимая для компонента NkEdit клавиша, то код символа заменяется на ноль. Допустимыми для компонента NkEdit являются цифровые клавиши, разделитель целой и дробной частей числа (в зависимости от настройки Windows: точка или запятая), "минус",
    (позволяет удалить ошибочно введенный символ) и
    .

    Здесь следует вспомнить, что в тексте программы дробная часть числовой константы отделяется от целой части точкой. Во время работы программы при вводе исходных данных пользователь должен использовать тот символ, который задан в настройке Windows. В качестве разделителя обычно применяют запятую (это для России стандартная настройка) или точку. Приведенная процедура обработки события OnKeyPress учитывает, что настройка Windows может меняться, и поэтому введенный пользователем символ сравнивается не с константой, а со значением глобальной переменной

    DecimalSeparator, которая содержит символ-разделитель, используемый в Windows в данный момент.

    После ввода текста модуля компонента модуль нужно откомпилировать и сохранить.

    Тест компонента NkEdit

    Листинг 16.3. Тест компонента NkEdit

    unit tstNkEdit_; interface

    uses

    Windows, Messages, SysUtils,
    Variants, Classes, Graphics,
    Controls,Forms, Dialogs, StdCtrls,

    NkEdit; // ссылка на модуль компонента

    type

    TForm1 = class(TForm)

    Label1: TLabel;

    Label2: TLabel;

    Buttonl: TButton;

    procedure FormCreate(Sender: TObject);


    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    myEdit: TnkEdit; // компонент NkEdit

    implementation

    {$R *.dfm)

    procedure TForm1.FormCreate(Sender: TObject);

    begin

    // создадим компонент и поместим его на форму

    myEdit := TNkEdit.Create(self);

    myEdit.Parent := self;
    myEdit.Left := 8;
    myEdit.Top := 64;
    end;

    procedure TForm1.ButtonlClick(Sender: TObject);

    begin

    label2. Caption := FloatToStr (myEdit .Numb) ;
    end;

    end.

    Тестируемый компонент создается процедурой обработки события Formcre-ate (Создание формы) посредством вызова конструктора компонента, которому в качестве параметра передается значение self, показывающее, что владельцем компонента является форма приложения.

    После создания компонента обязательно должен быть выполнен важный шаг: свойству Parent необходимо присвоить значение. В данном случае тестируемый компонент находится в форме приложения, поэтому свойству Parent присваивается значение self.

    На Рисунок 16.3 приведено окно программы Тест компонента NkEdit во время ее работы, после ввода числа в поле редактирования и щелчка на кнопке Тест.

    Приложение "Поездка на дачу" тест компонента

    Листинг 16.4. Приложение "Поездка на дачу" тест компонента

    unit fazenda ;

    interface

    uses

    Windows, Messages, SysUtils,
    Variants, Classes, Graphics, Controls,

    Forms, Dialogs, StdCtrls,

    NkEdit; // ссылка на модуль компонента

    type

    TForm1 = class(TForm)

    NkEdit 1: TNkEdit; //расстояние

    NkEdit2: TNkEdit; // цена литра бензина

    NkEditS: TNkEdit; // потребление бензина на 100 км

    CheckBox1: TCheckBox; // True — поездка туда и обратно

    Button1: TButton; Label4: TLabel;
    Label1: TLabel; Label2: TLabel;
    Label3: TLabel;

    // кнопка Вычислить

    // поле вывода результата расчета

    procedure ButtonlClick(Sender: TObject);


    procedure NkEditlKeyPress
    (Sender: TObject; var Key: Char);


    procedure NkEdit2KeyPress
    (Sender: TObject; var Key: Char);


    procedure NkEditSKeyPress
    (Sender: TObject; var Key: Char);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    // нажатие клавиши в поле Расстояние

    procedure TForm1.NkEdit1KeyPress
    (Sender: TObject; var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then NkEdit2.SetFocus; // переместить курсор в поле Цена
    end;

    // нажатие клавиши в поле Цена

    procedure TForm1.NkEdit2KeyPress
    (Sender: TObject; var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then NkEdit3.SetFocus;
    // переместить курсор в поле Потребление
    end;

    // нажатие клавиши в поле Потребление

    procedure TForm1.NkEdit3KeyPress
    (Sender: TObject; var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then Buttonl.SetFocus; //
    // сделать активной кнопку Вычислить
    end;

    // щелчок на кнопке Вычислить

    procedure TForml.ButtonlClick(Sender: TObject);


    var

    rast : real; // расстояние

    cena : real; // цена

    potr : real; // потребление на 100 км

    summ : real; // сумма

    mes: string; begin

    rast := StrToFloat(NkEdit1.Text);


    cena := StrToFloat(NkEdit2.Text);


    potr := StrToFloat(NkEdit3.Text) ;

    summ := rast / 100 * potr * cena;

    if CheckBoxl.Checked then sunnm := summ * 2;

    mes := 'Поездка на дачу';

    if CheckBoxl.Checked then mes := mes + ' и обратно';

    mes := mes + 'обойдется в '
    + FloatToStrF(summ,ffGeneral,4,2) + ' руб.';

    Label4.Caption := mes;
    end;

    end.

    Настройка палитры компонентов

    Настройка палитры компонентов

    Delphi позволяет менять порядок следования вкладок палитры компонентов, названия вкладок, а также порядок следования значков компонентов на вкладках. Настройка палитры компонентов выполняется в диалоговом окне Palette Properties, которое открывается выбором из меню Component команды Configure Palette (Рисунок 16.16).

    Окно редактора пакета компонентов

    Рисунок 16.7. Окно редактора пакета компонентов

    Окно редактора пакета компонентов
    На этом процесс установки компонента заканчивается. В результате на вкладке палитры компонентов, имя которой было задано при создании модуля компонента, появляется значок установленного компонента (Рисунок 16.8).

    Окно редактора пакета

    Рисунок 16.13. Окно редактора пакета

     Окно редактора пакета
    Для того чтобы удалить компонент из пакета, необходимо нажать кнопку Remove. В открывшемся диалоговом окне Remove From Project (Рисунок 16.14) следует выбрать удаляемый компонент и нажать кнопку ОК.

    Ошибки при установке компонента

    Ошибки при установке компонента

    Во время работы над новым компонентом наиболее частой ошибкой является попытка установить (переустановить) компонент, который уже находится в одном из пакетов (обычно такое желание возникает после внесения изменений в модуль компонента).

    В этом случае Delphi выводит сообщение: The package already contains unit named... (Пакет уже содержит модуль, который называется...) и процесс установки завершается. Для того чтобы преодолеть эту ошибочную ситуацию и установить компонент в нужный пакет или установить в пакет обновленную версию компонента, необходимо сначала удалить компонент из пакета, а затем установить его снова.

    Ресурсы компонента

    Ресурсы компонента

    Файл ресурсов компонента можно создать при помощи утилиты Image Editor, которая запускается выбором из меню Tools команды Image Editor.

    Для того чтобы создать новый файл ресурса компонента, нужно из меню File выбрать команду New и из появившегося списка выбрать тип создаваемого файла — Component Resource File.

    В результате открывается окно файла ресурсов Untitledl.dcr, а в меню диалогового окна Image Editor появляется новый пункт — Resource. Теперь нужно из меню Resource выбрать команду New/Bitmap и в открывшемся окне Bitmap Properties установить характеристики битового образа значка компонента: Size — 24x24 пиксела, Colors — 16.

    В результате этих действий в создаваемый файл ресурсов компонента будет добавлен новый ресурс — битовый образ с именем Bitmap1 Двойной щелчок на имени ресурса (Bitmapl) раскрывает окно редактора битового образа, в котором можно нарисовать нужную картинку.

    Изображение в окне графического редактора можно увеличить. Для этого необходимо выбрать команду Zoom In меню View.

    Следует обратить внимание, что цвет правой нижней точки рисунка определяет "прозрачный" цвет. Элементы значка компонента, закрашенные этим цветом, на палитре компонентов Delphi не видны.

    Перед тем, как сохранить файл ресурсов компонента, битовому образу надо присвоить имя. Имя должно совпадать с именем класса компонента. Чтобы задать имя битового образа, необходимо щелкнуть правой кнопкой мыши на имени битового образа (Bitmap1), выбрать в появившемся контекстном меню команду Rename и ввести новое имя.

    Созданный файл ресурсов компонента нужно сохранить в том каталоге, в котором находится файл модуля компонента. Для этого надо из меню File выбрать команду Save.

    Внимание!

    Имя файла ресурсов компонента (Edit.dcr) должно совпадать с именем модуля компонента (Edit.pas), а имя битового образа (Edit) — с именем класса компонента (Edit).


    Сообщение о неуспешной установке компонента

    Рисунок 16.6. Сообщение о неуспешной установке компонента

    Сообщение о неуспешной установке компонента
    После установки компонента в пакет открывается диалоговое окно Package (Редактор пакета компонентов) (Рисунок 16.70), в котором перечислены компоненты, находящиеся в пакете.

    Создание модуля компонента

    Создание модуля компонента

    Перед началом работы по созданию нового компонента нужно создать отдельный каталог для модуля и других файлов компонента. После этого можно приступить к созданию модуля компонента.

    Для того чтобы создать модуль компонента, необходимо из меню Component выбрать команду New Component и в поля открывшегося диалогового окна New Component (Рисунок 16.1) ввести информацию о создаваемом компоненте.

    Свойство компонента NkEdit отражено в окне Object Inspector

    Рисунок 16.10. Свойство компонента NkEdit отражено в окне Object Inspector

     Свойство компонента NkEdit отражено в окне Object Inspector
    В листинге 16.4 приведен модуль приложения Поездка на дачу. Очевидно, что текст программы значительно меньше первоначального варианта, в котором для ввода данных использовался компонент Edit.



    Тестирование компонента Поле ввода — компонент NkEdit

    Рисунок 16.3. Тестирование компонента. Поле ввода — компонент NkEdit


    Тестирование компонента Поле ввода — компонент NkEdit



    Тестирование компонента

    Тестирование компонента

    После того как компонент будет добавлен в пакет, необходимо проверить поведение компонента во время разработки приложения, использующего этот компонент (работоспособность компонента была проверена раньше, когда он добавлялся в форму приложения динамически, во время работы программы).

    Можно считать, что компонент работает правильно, если во время разработки приложения удалось поместить этот компонент в форму разрабатываемого приложения и, используя окно Object Inspector, установить, значения свойств компонента, причем как новых, так и унаследованных от родительского класса.

    Работоспособность компонента NkEdit можно проверить, использовав его, например, в приложении Поездка на дачу, вид формы которого приведен на Рисунок 16.9.

    Тестирование модуля компонента

    Тестирование модуля компонента

    Перед добавлением нового компонента в палитру компонентов необходимо всесторонне его проверить. Для этого надо создать приложение, использующее компонент и убедиться, что компонент работает так, как надо.

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

    Создается тестовое приложение обычным образом: сначала создается форма приложения, а затем — модуль приложения.

    Вид формы приложения тестирования компонента NkEdit- приведен на Рисунок 16.2.

    Удаление компонента

    Удаление компонента

    Иногда возникает необходимость удалить компонент из пакета. Сделать это можно при помощи редактора пакета компонентов.

    Для того чтобы запустить редактор пакета компонентов, надо из меню Component выбрать команду Install Packages, в открывшемся диалоговом окне Project Options (Рисунок 16.11) из списка Design packages выбрать нужный пакет и нажать кнопку Edit.

    Установка компонента

    Установка компонента

    Для того чтобы значок компонента появился в палитре компонентов, компонент должен быть добавлен в один из пакетов (Packages) компонентов

    Delphi. Пакет компонентов — это файл с расширением dpk (Delphi Package File). Например, компоненты, созданные программистом, находятся в пакете Dclusr70.dpk.

    Во время добавления компонента в пакет Delphi использует модуль компонента и файл ресурсов компонента, в котором должен находиться битовый образ значка компонента. Имя файла ресурсов компонента должно обязательно совпадать с именем файла модуля компонента. Файл ресурсов имеет расширение dcr (Dynamic Component Resource). Битовый образ, находящийся внутри файла ресурсов, должен иметь имя, совпадающее с именем класса компонента.

    Установка

    Установка

    После создания файла ресурсов компонента, в котором находится битовый образ значка компонента, можно приступить к установке компонента. Для этого надо из меню Component выбрать команду Install Component и заполнить поля открывшегося окна Install Component (Рисунок 16.5).

    Вкладка Samples после установки компонента NkEdit

    Рисунок 16.8. Вкладка Samples после установки компонента NkEdit


    Вкладка Samples после установки компонента NkEdit



    Выбор базового класса

    Выбор базового класса

    Приступая к разработке нового компонента, следует четко сформулировать назначение компонента. Затем необходимо определить, какой из компонентов Delphi наиболее близок по своему назначению, виду и функциональным возможностям к компоненту, который разрабатывается. Именно этот компонент следует выбрать в качестве базового.

    Выбор компонента удаляемого из пакета

    Рисунок 16.14. Выбор компонента, удаляемого из пакета

     Выбор компонента удаляемого из пакета
    После удаления компонента из пакета нужно обязательно выполнить перекомпиляцию пакета. Для этого необходимо в окне редактора пакета нажать кнопку Compile. После перекомпиляции пакета Delphi информирует о том, что удаленный компонент больше не зарегистрирован (Рисунок 16.15).

    Выбор пакета для редактирования

    Рисунок 16.11. Выбор пакета для редактирования

     Выбор пакета для редактирования
    В открывшемся окне Confirm (Рисунок 16.12) в ответ на запрос: cancel this dialog box and open... (Закрыть этот диалог и открыть пакет...) надо нажать кнопку Yes.

    Запрос подтверждения обновления пакета в процессе установки компонента

    Рисунок 16.5. Запрос подтверждения обновления пакета в процессе установки компонента

    Запрос подтверждения обновления пакета в процессе установки компонента
    После нажатия кнопки Yes процесс установки продолжается. Если он завершается успешно, то на экране появляется информационное сообщение (Рисунок 16.6) о том, что в результате обновления пакета палитра компонентов обновлена, т. е. в нее добавлен значок компонента, и новый компонент зарегистрирован.

    Отладка программы в Delphi

    Диалоговое окно New Database Alias

    Рисунок 17.3. Диалоговое окно New Database Alias

    Диалоговое окно New Database Alias
    После выбора драйвера и щелчка на кнопке ОК в список псевдонимов будет добавлен новый элемент (Рисунок 17.4).

    Динамически создаваемые псевдонимы

    Динамически создаваемые псевдонимы

    Использование псевдонима для доступа к базе данных обеспечивает независимость программы от размещения данных в системе, позволяет размещать программу работы с данными и базу данных на разных дисках компьютера, в том числе и на сетевом. Вместе с тем, для простых баз данных типичным решением является размещение базы данных в отдельном подкаталоге того каталога, в котором находится программа работы с базой данных. Таким образом, программа работы с базой данных всегда "знает", где находятся данные. При таком подходе можно отказаться от создания псевдонима при помощи BDE Administrator и возложить задачу создания псевдонима на программу работы с базой данных. Причем, псевдоним будет создаваться автоматически во время запуска программы и уничтожаться во время завершения ее работы. Очевидно, что такой подход облегчает администрирование базы данных.

    В качестве иллюстрации сказанного в листинге 17.3 приведен вариант программы работы с базой данных "Школа", которая для доступа к базе данных использует динамически создаваемый псевдоним.



    Доступ к базе данных (таблице)

    Доступ к базе данных (таблице)

    Доступ к базе данных обеспечивают компоненты Database, Table, Query и DataSource, значки которых находятся на вкладках Data Access и BDE палитры компонентов (Рисунок 17.6).

    После этого программу можно откомпилировать

    Рисунок 17.16. Форма после настройки компонента DBGrid1

    После этого программу можно откомпилировать
    После этого программу можно откомпилировать и запустить. Следует обратить внимание, что для того чтобы после запуска программы в окне появилась информация или, если база данных пустая, можно было вводить новую информацию, свойство Active таблицы-источника данных должно иметь значение True.

    Работа с базой данных, представленной в виде таблицы, во многом похожа на работу с электронной таблицей Microsoft Excel. Используя клавиши перемещения курсора вверх и вниз, а также клавиши листания текста страницами ( и ), можно, перемещаясь от строки к строке, просматривать записи базы данных. Нажав клавишу , можно добавить запись, а нажав клавишу — удалить запись. Для того чтобы внести изменения в поле записи, нужно, используя клавиши перемещения курсора влево и вправо, выбрать необходимое поле и нажать клавишу .


    Форма приложения Архитектурные памятники СанктПетербурга

    Рисунок 17.9. Форма приложения Архитектурные памятники Санкт-Петербурга

    Форма приложения Архитектурные памятники СанктПетербурга
    Создается форма следующим образом. Сначала в пустую форму надо добавить компоненты Tаblе и Datasource и установить значения их свойств (табл. 17.10). Значения свойств следует устанавливать в том порядке, в котором они следуют в таблице.



    Форма приложения База данных Школа

    Рисунок 17.19. Форма приложения База данных Школа

     Форма приложения База данных Школа


    Форма приложения после добавления компонента DBGrid

    Рисунок 17.14. Форма приложения после добавления компонента DBGrid

     Форма приложения после добавления компонента DBGrid
    Компонент DBGrid обеспечивает представление базы данных в виде таблицы. Свойства компонента DBGridl определяют вид таблицы и действия, которые могут быть выполнены над данными во время работы программы. В табл. 17.15 перечислены некоторые свойства компонента DBGrid.



    файлы данных) находятся на одном

    Локальная база данных

    Данные локальной базы данных ( файлы данных) находятся на одном (локальном) устройстве, в качестве которого может выступать диск компьютера или сетевой диск (диск другого компьютера, работающего в сети).

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

    Paradox, dBase, FoxPro и Access — это локальные базы данных.


    Классификация баз данных

    Классификация баз данных

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

    Компонент DBNavigator

    Рисунок 17.11. Компонент DBNavigator

     Компонент DBNavigator
    Табл. 17.12 содержит описания действий, которые выполняются в результате щелчка на соответствующей кнопке компонента DBNavigator.

    Свойства компонента DBNavigator перечислены в табл. 17.13.



    Компонент

    Компонент

    FieldName

    Title . Caption

    DBGrid1. Columns [0]
    DBGrid1. Columns [1]

    Fam

    Name

    Фамилия
    Имя

    Компонент

    FieldName

    Title . Caption

    DBGrid1. Columns [2]
    DBGrid1 . Columns [ 3 ]

    Class
    Adr

    Класс
    Адрес,телефон

    Последнее, что надо сделать — добавить к форме компонент DBNavigator, настроив его на работу с таблицей-источником данных (свойству DataSource Нужно Присвоить значение Table1).

    Окончательный вид формы приложения приведен на Рисунок 17.16.

    Компоненты просмотра и редактирования полей базы данных

    Рисунок 17.8. Компоненты просмотра и редактирования полей базы данных


    Компоненты просмотра и редактирования полей базы данных



    Компоненты вкладок Data Access и BDE обеспечивают доступ к данным

    Рисунок 17.6. Компоненты вкладок Data Access и BDE обеспечивают доступ к данным

    Компоненты вкладок Data Access и BDE обеспечивают доступ к данным
    Компонент Database представляет базу данных как единое целое, т. е. совокупность таблиц, а компонент Table — одну из таблиц базы данных. Компонент DataSource (источник данных) обеспечивает связь компонента отображения-редактирования данных (например, компонента DBGrid) и источника данных, в качестве которого может выступать таблица (компонент Tаblе) или результат выполнения SQL-запроса к таблице (компонент SQL). Компонент DataSource позволяет оперативно выбирать источник данных, использовать один и тот же компонент, например, DBGrid для отображения данных из таблицы или результата выполнения SQL-запроса к этой таблице. Механизм взаимодействия компонентов отображения-редактирования данных с данными через компонент DataSource иллюстрирует Рисунок 17.7.

    База данных "Архитектурные памятники СанктПетербурга"

    Листинг 17.1. База данных "Архитектурные памятники Санкт-Петербурга"

    unit peter_;
    interface

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls, Forms,
    Dialogs, ExtCtrls, StdCtrls,
    DBCtrls, Mask, Db, DBTables,
    jpeg; // чтобы можно было выводить JPG-иллюстрации;

    type

    TForml = class(TForm)

    Tablel: TTable; . // база данных — таблица

    DataSourcel: TDataSource; // источник данных для полей

    // редактирования-просмотра

    Label1: TLabel;

    Label2: TLabel;

    Label3: TLabel;

    DBEditl: TDBEdit;

    DBEdit2: TDBEdit;

    DBMemo1: TDBMemo;

    Image1: ТImage;

    DBEdit3: TDBEdit;

    DBNavigatorl: TDBNavigator;

    Label4: TLabel;

    procedure TablelAfterScroll(DataSet: TDataSet);


    procedure DBEdit3KeyPress(Sender: TObject; var Key: Char);


    procedure DBNavigatorlClick(Sender: TObject; Button: TNavigateBtn)

    procedure TablelBeforeOpen(DataSet: TDataSet);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Forml: TForml;

    BmpPath: string; // Путь к файлам иллюстраций. Иллюстрации

    // находятся в подкаталоге Data каталога программы.

    implementation

    ($R *.DFM}

    // выводит фотографию в поле Imagel
    procedure ShowFoto(foto: string);

    begin
    try


    Forml.Imagel.Picture.LoadFromFile(BmpPath+foto);

    Forml.Imagel.Visible:=True;
    except

    on EFOpenError do
    begin


    MessageDlg('Файл иллюстрации '+foto+' не найден.',

    mtlnformation, [mbOk], 0) ;
    end;
    end;
    end;


    // переход к другой записи (следующей, предыдущей,
    // первой или последней)

    procedure TForm1.TablelAfterScroll(DataSet: TDataSet);

    begin.

    if form1.DBEdit3.Visible then
    begin


    form1.DBEditS.Visible := False;
    form1.Label4.Visible:=False;
    end;
    if
    Forml.DBEditS.Text <>
    "

    then ShowFoto(Form1.DBEditS.Text)
    else form1.Imagel.Visible:=False;
    end;

    // нажатие клавиши в поле Фото

    procedure TForml.DBEdit3KeyPress(Sender: TObject; var Key: Char);

    begin

    if (key = #13) then

    if Forml.DBEdit3.Text <>
    ''

    then ShowFoto(Forml.DBEdit3.Text) // показать иллюстрацию
    else forml,Imagel.Visible:=False;
    end;

    // щелчок на компоненте Навигатор

    procedure TForml.DBNavigatorlClick(Sender: TObject; Button:
    TNavigateBtn);


    begin

    case Button of
    nblnsert: begin

    Imagel.Visible:=False;// скрыть область вывода иллюстрации
    DBEdit3.Visible:=True; // показать поле Фото
    Label4.Visible:=True; // показать метку Фото
    end;
    nbEdit: begin // редактирование записи

    DBEdit3.Visible:=True; // показать поле Фото
    Label4.Visible:=True; // показать метку Фото
    end;

    end;

    end;

    // перед открытием таблицы

    procedure TForml.TablelBeforeOpen(DataSet: TDataSet);


    begin

    BmpPath:=ExtractFilePath(ParamStr(0))+'data\';
    end;

    end.

    end.

    Вызов процедуры вывода фотографии (showFoto) во время просмотра базы данных выполняет процедура TForm1.Table1AfterScroll, которая обеспечивает обработку события AfterScrool для компонента Table1. Событие AfterScrool происходит всякий раз после перехода к другой (следующей, предыдущей, первой, последней) записи таблицы как результат щелчка пользователя на соответствующей кнопке компонента DBNavigator. Процедура TForml.Table1AfterScroll анализирует содержимое поля (photo) Form1.DBEdit3.Text и, если оно не пустое, что свидетельствует о наличии ссылки на файл фотографии, выводит иллюстрацию.

    При просмотре базы данных поле имени файла иллюстрации (DBEdits) и его заголовок (Label4) на форме не отображаются. Если пользователь нажимает одну из кнопок компонента DBNavigator, то как результат обработки события onclick вызывается процедура TForm1.DBNavigatorlciick, которая при щелчке кнопки Добавить или Редактировать делает доступным поле DBEdits, тем самым позволяя пользователю ввести или изменить имя файла иллюстрации.

    Процедура TForm1.DBEdit3KeyPress обрабатывает событие OnKeyPress для компонента DBEdits. Если пользователь ввел в поле Edits (photo) имя файла иллюстрации и нажал клавишу
    (ее код равен 13), то процедура TForm1.DBEdit3KeyPress выводит иллюстрацию путем вызова процедуры ShowFoto.

    База данных "Школа"

    Листинг 17.2. База данных "Школа"

    unit school2_;
    interface
    uses
    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms,
    Dialogs,Grids, DBGrids, Db,
    DBTables, ExtCtrls, DBCtrls, StdCtrls;
    type
    TForm1 = class(TForm)
    Table1: TTable; // таблица (вся база данных)
    Query1: TQuery; // запрос (записи БД, удовлетворяющие критерию выбора)
    DataSource1: TDataSource; // источник данных - таблица или запрос
    DBGrid1: TDBGrid; // таблица для отображения БД или результата выполнения запроса
    DBNavigator1: TDBNavigator;
    DBText1: TDBText;
    Button1: TButton; // кнопка запрос
    Button2: TButton; // кнопка Все записи
    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

    procedure FormActivate(Sender: TObject);

    private
    { Private declarations }
    public
    { Public declarations }
    end;
    var
    Form1: TForm1;
    implementation
    {$R *.DFM}
    // щелчок на кнопке Запрос
    procedure TForm1.Button1Click(Sender: TObject);

    var
    fam: string[30];
    begin
    fam:=InputBox('Выборка информации из БД',
    'Укажите фамилию и щелкните на OK.', '');

    if fam <>
    '' // пользователь ввел фамилию
    then
    begin
    with form1.Query1 do begin
    Close; // закрыть файл-результат выполнения предыдущего запроса
    SQL.Clear; // удалить текст предыдущего запроса
    // записываем новый запрос в свойство SQL
    SQL.Add('SELECT Fam, Name, Class');

    SQL.Add('FROM ":Школа:school.db"');

    SQL.Add('WHERE');

    SQL.Add('(Fam = "'+ fam + '")');

    SQL.Add('ORDER BY Name, Fam');

    Open; // активизируем выполнение запроса
    end;
    { *** другой вариант изменения критерия запроса
    begin
    Query1.Close;
    Query1.SQL[3]:='(Fam="'+ fam + '")';
    Query1.Open;
    DataSource1.DataSet:=Query1;
    end;
    }
    if Query1.RecordCount <>
    0 then
    DataSource1.DataSet:=Query1 // отобразить рез-т выполнения запроса
    else begin
    ShowMessage('В БД нет записей, удовлетворяющих критерию запроса.');

    DataSource1.DataSet:=Table1;
    end;
    end;
    end;

    // щелчок на кнопке Все записи
    procedure TForm1.Button2Click(Sender: TObject);

    begin
    DataSource1.DataSet:=Table1; // источник данных - таблица
    end;
    // активизация формы
    procedure TForm1.FormActivate(Sender: TObject);

    begin
    DataSource1.DataSet := Table1;
    Table1.Active := True;
    end;
    end.
    Процедура TForm1.Button1Click запускается щелчком кнопки Запрос. Она принимает от пользователя строку (фамилии) и записью (добавлением) строк в свойство SQL формирует текст запроса. Затем эта процедура вызовом метода Open активизирует выполнение запроса.

    Следует обратить внимание на то, что перед изменением свойства SQL-запрос должен быть закрыт при помощи метода close (здесь надо вспомнить, что результат выполнения запроса — это файл данных (таблица), который создается в результате выполнения запроса).

    Процедура TForm1.Button2Click, которая запускается щелчком кнопки Все записи, устанавливает в качестве источника данных для компонента DataSourcel компонент Table1, тем самым обеспечивая переход в режим просмотра всей базы данных.

    Если запрос записан в свойство SQL во время разработки формы приложения, то во время работы программы критерий запроса можно изменить простой заменой соответствующей строки текста запроса.

    Например, для запроса

    SELECT DISTINCT Fam, Name, Class FROM ":Школа:school.db" WHERE

    (Class= '10а') ORDER BY Name, Fam

    инструкция замены критерия запроса может быть такой:

    forml.Query1.SQL[3]:='(Fam="' + fam+ '")'

    Следует обратить внимание на то, что свойство SQL является структурой типа TStrings, в которой строки нумеруются с нуля.

    База данных "Школа" (псевдоним БД создается динамически)

    Листинг 17.3. База данных "Школа" (псевдоним БД создается динамически)

    unit school3_;
    interface
    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
    Dialogs, Grids, DBGrids, Db, DBTables, ExtCtrls, DBCtrls, StdCtrls;
    type
    TForm1 = class(TForm)
    Table1: TTable; // таблица (вся база данных)
    Query1: TQuery; // запрос (записи БД, удовлетворяющие критерию выбора)
    DataSource1: TDataSource; // источник данных - таблица или запрос
    DBGrid1: TDBGrid; // таблица для отображения БД или результата выполнения запроса
    DBNavigator1: TDBNavigator;
    DBText1: TDBText;
    Button1: TButton; // кнопка запрос
    Button2: TButton; // кнопка Все записи
    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

    procedure FormActivate(Sender: TObject);

    private
    { Private declarations }
    public
    { Public declarations }
    end;
    var
    Form1: TForm1;
    implementation
    {$R *.DFM}
    // щелчок на кнопке Запрос
    procedure TForm1.Button1Click(Sender: TObject);

    var
    fam: string[30];
    begin
    fam:=InputBox('Выборка информации из БД',
    'Укажите фамилию и щелкните на OK.', '');

    if fam <>
    '' // пользователь ввел фамилию
    then
    begin

    with form1.Query1 do begin
    Close; // закрыть файл-результат выполнения предыдущего запроса
    SQL.Clear; // удалить текст предыдущего запроса
    // записываем новый запрос в свойство SQL
    SQL.Add('SELECT Fam, Name, Class');

    SQL.Add('FROM ":Школа:school.db"');

    SQL.Add('WHERE');

    SQL.Add('(Fam = "'+ fam + '")');

    SQL.Add('ORDER BY Name, Fam');

    Open; // активизируем выполнение запроса
    end;
    if Query1.RecordCount <>
    0 then
    DataSource1.DataSet:=Query1 // отобразить рез-т выполнения запроса
    else begin
    ShowMessage('В БД нет записей, удовлетворяющих критерию запроса.');

    DataSource1.DataSet:=Table1;
    end;
    end;
    end;

    // щелчок на кнопке Все записи
    procedure TForm1.Button2Click(Sender: TObject);

    begin
    DataSource1.DataSet:=Table1; // источник данных - таблица
    end;
    // активизация формы
    procedure TForm1.FormActivate(Sender: TObject);

    begin
    with Session do
    begin
    ConfigMode := cmSession;
    try
    { Если файл данных находиться в том же каталоге,
    что и выполняемый файл программы, то в программе
    путь к файлу данных может быть получен из командной
    строки при помощи функции ExtractFilePath(ParamStr(0)).
    В приведенном примере файл данных находиться в подкаталоге
    DATA каталога программы. }
    // создадим временный псевдоним для базы данны
    AddStandardAlias( 'Школа',
    ExtractFilePath(ParamStr(0))+'DATA\',
    'PARADOX');

    Table1.Active:=True; // откроем базу данных
    finally
    ConfigMode := cmAll;
    end;
    end;
    end;

    end.

    В рассматриваемом варианте программы предполагается, что база данных содержится в подкаталоге DATA того каталога, в котором находится выполняемый файл программы. Создает псевдоним процедура TForm1.FormActivate. Непосредственное создание псевдонима выполняет процедура AddstandardAlias, которой в качестве параметра передается имя псевдонима и соответствующее ему имя каталога. Так как во время разработки программы нельзя знать, в каком каталоге будет размещена программа работы с базой данных и, следовательно, подкаталог базы данных -DATA, имя каталога определяется во время работы программы путем обращения к функциям ParamStr(0) и ExtractFilePatch. Значение первой -полное имя выполняемого файла программы, второй — путь к этому файлу. Таким образом, процедуре AddstandardAiias передается полное имя каталога базы данных.

    Модель базы данных в Delphi

    Модель базы данных в Delphi

    Каждая таблица физически хранится в отдельном файле. Однако отождествлять базу данных и таблицу нельзя, так как довольно часто поля одной записи распределены по нескольким таблицам и, следовательно, находятся в разных файлах.

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

    Окно BDE Administrator

    Рисунок 17.2. Окно BDE Administrator

    Окно BDE Administrator
    В левой части окна, на вкладке Databases, перечислены псевдонимы, зарегистрированные на данном компьютере. Для того чтобы создать новый псевдоним, необходимо из меню Object выбрать команду New. Затем в открывшемся диалоговом окне New Database Alias (Новый псевдоним базы данных) из списка Database Driver Name, в котором перечислены зарегистрированные в системе драйверы доступа к базам данных, нужно выбрать драйвер для создаваемой базы данных (Рисунок 17.3), т. е. фактически выбрать тип создаваемой базы данных.

    При создании псевдонима по умолчанию предлагается драйвер STANDARD (default driver), который обеспечивает доступ к таблицам в формате Paradox.

    Окончательный вид формы приложения Архитектурные памятники СанктПетербурга

    Рисунок 17.12. Окончательный вид формы приложения Архитектурные памятники Санкт-Петербурга

     Окончательный вид формы приложения Архитектурные памятники СанктПетербурга
    В принципе, после добавления в форму компонента DBNavigator простейшая программа управления базой данных готова. Эта программа обеспечивает просмотр, редактирование, добавление новых и удаление ненужных записей.

    Теперь рассмотрим, что надо сделать, чтобы в поле imagei появилось изображение памятника, информация о котором выведена в форме. Разрабатываемое приложение предполагает, что изображения (фотографии) архитектурных памятников находятся в файлах в том же каталоге, что и таблица базы данных. Во время добавления информации в базу данных пользователь вводит в поле Photo имя файла фотографии, а во время просмотра фотография автоматически появляется в поле image 1.

    В листинге 17.1 приведен текст модуля программы Архитектурные памятники Санкт-Петербурга.



    Памятник

    Памятник

    Архитектор

    Историческая справка

    1

    Адмиралтейство

    А. Д. Захаров

    Здание Адмиралтейства таким, как оно выглядит сейчас, стало после перестройки в 1806 — 1823 годах. Автор проекта — гениальный русский зодчий А. Д. Захаров. Высота шпиля: 72 метра

    2

    Александровская колонна

    Огюст Монферран

    Памятник победы России над войсками Наполеона в Отечественной войне 1812 года. Открыта 30 августа 1834 года. Высота: 47,5 метра; вес гранитного ствола: 600 тонн

    3

    Зимний дворец

    Ф. Б. Растрелли

    Зимний дворец много раз менял свой облик. Последний раз он перестраивался по проекту Растрелли. Строительство дворца продолжалось более семи лет (1754 — 1762 годы)

    4

    Ростральные колонны

    Тома де Томон

    32-метровые ростральные колонны, органично вошедшие в архитектурный ансамбль Стрелки Васильевского острова, были сооружены в 1810 году. Они напоминают о существовавшем в древнем Риме обычае — украшать триумфальные колонны рострами захваченных кораблей

    5

    Исаакиевский собор

    Огюст Монферран

    Исаакиевский собор, четвертый по счету, стали возводить в 1818 году. Строился собор 40 лет и был окончен в 1 858 году. Автор проекта — Огюст Монферран



    Перенос программы управления базой данных на другой компьютер

    Перенос программы управления базой данных на другой компьютер

    Довольно часто возникает необходимость переноса созданной программы управления базой данных на другой компьютер, например, для того чтобы продемонстрировать ее своим друзьям или знакомым. В отличие от процесса переноса обычной программы, когда, как правило, достаточно скопировать только выполняемый файл (ЕХЕ-файл), при переносе программы управления базой данных необходимо выполнить перенос BDE.

    Здесь следует вспомнить, что BDE представляет собой набор программ, библиотек и драйверов, обеспечивающих работу прикладной программы с базой данных. Выполнить перенос BDE на другой компьютер вручную практически невозможно.

    Поэтому Borland рекомендует создавать установочную программу, которая выполнит копирование всех необходимых файлов, в том числе и компонентов BDE. В качестве средства создания установочной программы Borland настоятельно рекомендует использовать утилиту InstallShield Express, которая входит в состав всех наборов Delphi. Поставляемая с Delphi версия этой утилиты специально адаптирована к задаче переноса и настройки BDE.

    Можно попытаться установить BDE вручную. Ниже перечислены файлы (их имена определены опытным путем), необходимые для работы с базой данных Paradox:

  • BLW32.DLL
  • IDAPI32.DLL
  • IDBAT32.DLL
  • IDPDX32.DLL
  • IDR20009.DLL
  • USA.BLL
  • CHARSET.BLL
  • Эти файлы нужно установить на компьютер пользователя, затем проверить, что в реестре Windows есть перечисленные ниже разделы и параметры:

  • Раздел HKEY_LOCAL_MACHINE\Software\Borland\Database engine — параметр DLLPATH должен содержать путь к DLL-файлам BDE;
  • Раздел HKEY_LOCAL_MACHINE\Software\Borland\BLW32 — параметр BLAPIPATH должен содержать путь к BLL-файлам BDE.


  • Поле

    Поле

    Тип

    Размер



    Monument

    A

    60

    Название архитектурного памятника

    Architect

    A

    40

    Имя архитектора

    Note

    A

    255

    Краткая историческая справка

    Photo

    A

    12

    Имя файла иллюстрации



    Представление БД в виде таблицы

    Рисунок 17.1. Представление БД в виде таблицы


    Пример запроса к базе данных "Школа"

    Рисунок 17.18. Пример запроса к базе данных "Школа"

     Пример запроса к базе данных
    Свойство SQL представляет собой список строк. Поэтому чтобы сформировать запрос во время работы программы, нужно, используя метод Add, добавить строки (SQL-инструкции) в список SQL.

    Ниже приведен фрагмент кода, который формирует запрос на поиск информации о конкретном человеке (критерий выбора — содержимое поля Fam должно совпадать со значением переменной fam).

    with forml.Queryl do begin

    Close; // закрыть файл — результат выполнения

    // предыдущего запроса

    SQL.Clear; // удалить текст предыдущего запроса

    // записываем новый запрос в свойство SQL

    SQL.Add('SELECT Fam, Name, Class1);

    SQL.Add('FROM ":Школа:school.db"');

    SQL.Add('WHERE');

    SQL.Add('(Fam = '" + fam + '")');

    SQL.Add('ORDER BY Name, Fam');

    Open; // активизируем выполнение запроса

    end;

    Следующая программа, ее текст приведен в листинге 17.2, а диалоговое окно — на Рисунок 17.19, демонстрирует возможность изменения запроса, точнее, критерия запроса, во время работы программы. Программа обеспечивает вывод как всего списка учеников, так и его части. Например, посредством выполнения запроса выводится информация только о конкретном ученике.

    Для просмотра базы данных и результата выполнения запроса используется компонент DBGrid1, который через компонент DataSourcel взаимодействует с компонентом Table1 (при просмотре всей базы данных) или с компонентом Query (при просмотре результата выполнения запроса).

    Программа управления базой данных

    Программа управления базой данных

    Процесс создания программы управления базой данных рассмотрим на примере создания базы данных "Архитектурные памятники Санкт-Петербурга".

    Перед тем как приступить непосредственно к разработке приложения управления базой данных, необходимо, используя утилиту Database Desktop, создать файл данных (таблицу) и добавить в нее несколько записей. В табл. 17.3 перечислены поля таблицы monuments (monuments — монументы, памятники). В таблицу monuments можно внести информацию о памятниках Санкт-Петербурга (табл. 17.4).



    Просмотр базы данных

    Просмотр базы данных

    Пользователь может просматривать базу данных в режиме формы или в режиме таблицы. В режиме формы можно видеть только одну запись, а в режиме таблицы -- несколько записей одновременно. Довольно часто эти два режима комбинируют. Краткая информация (содержимое некоторых ключевых полей) выводится в табличной форме, а при необходимости видеть содержимое всех полей записи выполняется переключение в режим формы.

    Компоненты, обеспечивающие просмотр и редактирование содержимого полей базы данных, находятся на вкладке Data Controls (Рисунок 17.8).

    Псевдоним базы данных

    Псевдоним базы данных

    Разрабатывая программу работы с базой данных, программист не может знать, на каком диске и в каком каталоге будут находиться файлы базы данных во время ее использования. Например, пользователь может поместить базу данных в один из каталогов дисков С:, D: или на сетевой диск. Поэтому возникает проблема передачи в программу информации о месте нахождения файлов базы данных.

    В Delphi проблема передачи в программу информации о месте нахождения файлов базы данных решается путем использования псевдонима базы данных. Псевдоним (Alias) — это короткое имя, поставленное в соответствие реальному, полному имени каталога базы данных. Например, псевдонимом каталога C:\data\spetersburg может быть имя Peterburg. Программа работы с базой данных для доступа к данным использует не реальное имя, а псевдоним.

    Для доступа к информации программа, обеспечивающая работу с базой данных, подключает библиотеку Borland Database Engine (BDE), которая, в свою очередь, использует конфигурационный файл, содержащий информацию о всех зарегистрированных в системе псевдонимах.

    Псевдоним базы данных может быть создан (зарегистрирован) при помощи утилиты BDE Administrator. Эта же утилита позволяет изменить каталог, связанный с псевдонимом.

    Редактор колонок

    Рисунок 17.15. Редактор колонок

     Редактор колонок
    Для того чтобы в компонент DBGrid добавить колонку, обеспечивающую просмотр содержимого поля записи файла данных, необходимо нажать кнопку Add New, находящуюся на панели инструментов в верхней части окна (это единственная доступная после запуска редактора кнопка), выделить добавленный элемент и, используя Object Inspector, установить значения свойств этой колонки (табл. 17.16). Свойство columns компонента DBGrid представляет собой массив компонентов типа TCoiumn. Каждой колонке соответствует элемент массива. Устанавливая значения свойств компонентов column, программист задает вид колонок компонента DBGrid, тем самым определяет вид всей таблицы.



    Регистрация нового псевдонима

    Рисунок 17.4. Регистрация нового псевдонима

    Регистрация нового псевдонима
    После этого нужно изменить автоматически созданное администратором имя псевдонима и задать путь к файлам базы данных, для которой создается псевдоним.

    Имя псевдонима можно изменить обычным для Windows способом: щелкнуть правой кнопкой мыши на имени псевдонима (на вкладке Databases), в появившемся контекстном меню выбрать команду Rename (Переименовать) и в открывшемся диалоговом окне ввести новое имя.

    Путь к файлам базы данных можно ввести на вкладке Definition в поле Path с клавиатуры или воспользоваться стандартным диалоговым окном Select Directory (Выбор каталога), которое открывается щелчком на кнопке с тремя точками, находящейся в конце поля Path.

    В качестве примера на Рисунок 17.5 приведен вид, окна BDE Administrator после создания псевдонима Peterburg для базы данных "Архитектурные памятники Санкт-Петербурга".

    Для того чтобы созданный псевдоним был зарегистрирован в файле конфигурации (Idapi.cfg), необходимо в меню Object выбрать команду Apply (Применить). В открывшемся диалоговом окне Confirm следует подтвердить необходимость сохранения изменений в файле конфигурации.

    Режим формы

    Режим формы

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

    Компонент DBText позволяет только просматривать содержимое поля, а компоненты DBEdit и DBMеmо — просматривать и редактировать. В табл. 17.9 перечислены некоторые свойства этих компонентов. Свойства перечислены в том порядке, в котором следует устанавливать их значения после добавления в форму приложения.



    Режим таблицы

    Режим таблицы

    Программа работы с базой данных "Архитектурные памятники Санкт-Петербурга" выводит информацию в режиме формы, в каждый момент времени пользователь может видеть только одну запись. Такой режим работы с базой данных не всегда удобен. Если необходимо видеть одновременно несколько записей базы данных, то нужно обеспечить просмотр данных в режиме таблицы.

    Процесс создания приложения, обеспечивающего просмотр базы данных в режиме таблицы, рассмотрим на примере программы работы с базой данных "Школа".

    Пусть база данных "Школа" (псевдоним школа), представляет собой таблицу, которая находится в файле School.db. Записи таблицы school состоят из полей: Name (Имя), Fam (Фамилия), class (Класс), Adr (Адрес) и N (Личный номер). Поля Name, Fam, class и Adr являются полями символьного типа (тип А), а поле N — числовое, с автоувеличением.

    Примечание

    Псевдоним Школа следует создать при помощи BDE Administrator, а таблицу (файл school.db) — при помощи Database Desktop.

    Сначала в форму разрабатываемого приложения нужно добавить компоненты Table и DataSource, которые обеспечивают доступ к файлу данных, и установить значения их свойств (табл. 17.14).



    Создание базы данных

    Создание базы данных

    База данных — это набор файлов (таблиц), в которых находится информация. Как правило, база данных состоит из нескольких таблиц, которые размещают в одном каталоге. Каталог для новой базы данных создается обычным образом, например, при помощи Проводника. Таблицу можно создать, воспользовавшись входящей в состав Delphi утилитой Borland Database Desktop или организовав SQL-запрос к серверу базы данных.

    Так как для доступа к файлам (таблицам) базы данных библиотека BDE использует не имя каталога, в котором находятся файлы, а его псевдоним, то перед тем, как приступить к созданию таблиц новой базы данных, необходимо создать псевдоним для этой базы данных.

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

    1. Создание каталога.

    2. Создание псевдонима.

    3. Создание таблиц.

    Создание каталога

    Создание каталога

    Каталог (папка) для файлов базы данных создается обычным образом, например, при помощи Проводника. Обычно файлы локальной базы данных помещают в отдельном подкаталоге каталога программы работы с базой данных.

    Примечание

    Для дальнейшей работы с рассматриваемой в качестве примера базой данных "Архитектурные памятники Санкт-Петербурга" следует в каталоге \ Проекты создать каталог Петербург и в нем — подкаталог Data.


    Создание псевдонима

    Создание псевдонима

    Псевдоним базы данных создается при помощи входящей в Delphi утилиты BDE Administrator, которая запускается из Windows выбором из меню Программы | Borland Delphi 7 команды BDE Administrator.

    Вид диалогового окна BDE Administrator после запуска приведен на Рисунок 17.2

    Создание таблицы

    Создание таблицы

    Важным моментом при создании базы данных является распределение информации между полями записи. Очевидно, что информация может быть распределена между полями различным образом.

    Например, сведения об исторических памятниках Санкт-Петербурга могут быть организованы в виде записей, состоящих из полей "Памятник" и "Историческая справка" или из полей "Памятник", "Архитектор", "Год" и "Историческая справка".

    В первом варианте поле "Памятник" будет содержать название памятника, например Эрмитаж, а поле "Историческая справка" - - всю остальную информацию. При этом пользователь сможет найти информацию об интересующем его памятнике только по названию. При втором варианте организации записи пользователь сможет найти информацию о памятниках, архитектором которых является конкретный зодчий, или о памятниках, возведенных в данный исторический период.

    Можно сформулировать следующее правило: если предполагается, что во время использования базы данных будет выполняться выборка информации по некоторому критерию, то информацию, обеспечивающую возможность этой выборки, следует поместить в отдельное поле.

    После того как определены поля записи, необходимо выполнить распределение полей по таблицам. В простой базе данных все поля можно разместить в одной таблице. В сложной базе данных поля распределяют по нескольким таблицам, и вводом некоторой дополнительной информации, однозначно идентифицирующей каждую запись, обеспечивается связь между таблицами.

    Примечание

    Базы данных, состоящие из нескольких, связанных между собой таблиц, называются реляционными. В реляционных базах данных, для того чтобы избежать дублирования информации в таблицах, к основной информации добавляется некоторая служебная информация, которая однозначно идентифицирует запись. Подробное рассмотрение организации реляционных баз данных в задачу этой книги не входит. Читатель может самостоятельно ознакомиться с вопросами организации реляционных баз данных, обратившись к литературе.

    После того как определена структура записей базы данных, можно приступить непосредственно к созданию таблицы. Таблицы создаются при помощи входящей в состав Delphi утилиты Database Desktop.

    Утилита Database Desktop позволяет выполнять все необходимые при работе с базами данных действия. Она обеспечивает создание, просмотр и модификацию таблиц баз данных различных форматов (Paradox, dBASE, Microsoft Access). Кроме того, утилита позволяет выполнять выборку информации путем создания запросов.

    Для того чтобы создать новую таблицу, нужно выбором из меню Tools команды Database Desktop запустить Database Desktop. Затем в появившемся окне утилиты Database Desktop надо из меню File выбрать команду New и в появившемся списке выбрать тип создаваемого файла — Table. Затем в открывшемся диалоговом окне Create Table следует выбрать тип создаваемой таблицы (значением по умолчанию является тип Paradox 7).

    В результате открывается диалоговое окно Create Paradox 7 Table, в котором можно определить структуру записей таблицы.

    Для каждого поля таблицы необходимо задать имя, тип и, если нужно, размер поля. Имя поля используется для доступа к данным. В качестве имени поля, которое вводится в колонку Field Name, можно использовать последовательность из букв латинского алфавита и цифр длиной не более 25 символов.

    Тип поля определяет тип данных, которые могут быть помещены в поле. Тип задается вводом в колонку Туре символьной константы. Типы полей и соответствующие им константы приведены в табл. 17.1.



    Структура базы данных

    Структура базы данных

    База данных — это набор однородной, как правило, упорядоченной по некоторому критерию, информации. База данных может быть представлена в "бумажном" или в компьютерном виде.

    Типичным примером "бумажной" базы данных является каталог библиотеки — набор бумажных карточек, содержащих информацию о книгах. Информация в этой базе однородная (содержит сведения только о книгах) и упорядоченная (карточки расставлены, например, в соответствии с алфавитным порядком фамилий авторов). Другими примерами "бумажной" базы данных являются телефонный справочник и расписание движения поездов.

    Компьютерная база данных представляет собой файл (или набор связанных файлов), содержащий информацию.

    База данных состоит из записей. Каждая запись содержит информацию об одном экземпляре. Например, каждая запись базы данных "Архитектурные памятники Санкт-Петербурга" содержит информацию только об одном экземпляре — историческом памятнике.

    Записи состоят из полей. Каждое поле содержит информацию об одной характеристике экземпляра. Например, запись базы данных "Архитектурные памятники Санкт-Петербурга" состоит из следующих полей: "Памятник", "Архитектор" и "Историческая справка", где "Памятник", "Архитектор" и "Историческая справка" — это имена полей. Содержимое этих полей характеризует конкретный памятник.

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

    На бумаге базу данных удобно представить в виде таблицы (Рисунок 17.1). Каждая строка таблицы соответствует записи, а ячейка таблицы — полю. При этом заголовок столбца таблицы — это имя поля, а номер строки таблицы — номер записи.

    Информацию компьютерных баз данных обычно выводят на экран в виде таблиц. Поэтому в литературе довольно часто вместо словосочетания "файл данных" используется словосочетание "таблица данных" или просто "таблица".





    Свойство

    Свойство

    Определяет

    Name

    Имя компонента. Используется для доступа к свойствам компонента

    DataSet

    Имя компонента, представляющего собой входные данные

    Свойство DataSet обеспечивает связь между компонентом, представляющим собой таблицу или запрос, и компонентами, предназначенными для доступа к записям. Наличие этого свойства позволяет выбирать источник данных. Например, база данных может быть организована таким образом, что таблица, состоящая из большого числа записей, разделена на несколько подтаблиц, имеющих одинаковую структуру. В этом случае в приложении каждой подтаблице будет соответствовать свой компонент Table, а выбор конкретной подтаблицы можно осуществить установкой значения свойства DataSet.

    В табл. 17.7 и 17.8 приведены значения свойств компонентов Table и DataSource для разрабатываемого приложения.



    Тип поля определяет тип информации которая может в нем находиться

    Таблица 17.1. Тип поля определяет тип информации, которая может в нем находиться

    Тип

    Константа

    Содержимое поля

    Alpha

    A

    Строка символов. Максимальная длина строки определяется характеристикой Size, значения которой находятся в диапазоне 1—255

    Number

    N

    Число из диапазона 10-307— 10308 с 15-ю значащими цифрами

    Money

    $

    Число в денежном формате. Цифры числа делятся на группы при помощи разделителя групп разрядов. Также выводится знак денежной единицы

    Short

    S

    Целое число из диапазона -32767—32767

    Long Integer

    I

    Целое число из диапазона -2 147 483 648-2 147 483 647

    Date

    D

    Дата

    Time

    Т

    Время с полуночи, выраженное в миллисекундах

    Time stamp

    @

    Время и дата

    Memo

    M

    Строка символов произвольной длины. Поле типа Memo используется для хранения текстовой информации, которая не может быть сохранена в поле типа Alpha. Размер поля (1—240) определяет, сколько символов хранится в таблице. Остальные символы хранятся в файле, имя которого совпадает с именем файла таблицы, а расширение файла — mb

    Formatted Memo

    F

    Строка символов произвольной длины (как у типа Memo). Имеется возможность указать тип и размер шрифта, способ оформления и цвет символов

    Graphic

    G

    Графика

    Logical

    L

    Логическое значение "истина" (True) или "ЛОЖЬ" (False)

    Auto-increment

    +

    Целое число. При добавлении к таблице очередной записи в поле записывается число на единицу большее, чем находится в соответствующем поле последней добавленной записи



    Значения свойств компонентов Tablel И DataSourcel

    Таблица 17.10. Значения свойств компонентов Tablel И DataSourcel

    Свойство

    Значение

    Комментарий

    Tablel . DatabaseName

    Peterburg

    Псевдоним базы данных (создается утилитой BDE Administrator)

    Tablel . TableName

    monuments . db



    Так как значению свойства Active

    Таблица 17.11. Значения свойств компонентов DBEdit1 -DBEdit3 и DBMemo1

    Свойство

    Компонент

    DBEdit1

    DBEdit2

    DBEdit3

    DBMemo1

    DataSource

    DataSource1

    DataSource1

    DataSource1

    DataSource1

    DataFieid

    Monument

    Architect

    Photo

    Note

    Так как значению свойства Active компонента Tаblе1 присвоено значение True, то сразу после того, как будет присвоено значение свойству DataFieid, в поле компонента DBEdit появится содержимое соответствующего поля первой записи таблицы базы данных. Если таблица не содержит данных, поле остается незаполненным. Если значение свойства Active компонента Tabiei равно False, то в поле компонента DBEdit появляется его имя, значение свойства Name.

    Кроме компонентов просмотра-редактирования полей базы данных, в форму нужно добавить компонент image, который используется для просмотра иллюстраций, и четыре компонента Label для вывода пояснительного текста. свойству Visible компонентов Image1, Label4 и DBEdit3 следует присвоить значение False.

    Теперь, если откомпилировать и запустить программу, на экране появится форма, в полях которой будет находиться содержимое первой записи файла данных.

    Для того чтобы иметь возможность просматривать другие записи файла данных, в форму приложения нужно добавить компонент DBNavigator, значок которого находится на вкладке Data Controls (Рисунок 17.10). Компонент DBNavigator (Рисунок 17.11) представляет собой набор кнопок, при щелчках на которых во время работы программы происходит перемещение указателя текущей записи к следующей, предыдущей, первой или последней записи базы данных, а также добавление к файлу данных новой записи, удаление текущей записи.

    Кнопки компонента DBNavigator

    Таблица 17.12. Кнопки компонента DBNavigator

    Кнопка

    Обозначение

    Действие



    Свойства компонента DBNavigator

    Таблица 17.13. Свойства компонента DBNavigator

    Свойства компонента DBNavigator
    Свойство

    Определяет

    VisibleButton3 Видимые командные кнопки
    Name
    DataSource

    Имя компонента. Используется для доступа к свойствам компонента

    Имя компонента, являющегося источником данных. В качестве источника данных может выступать база данных (компонент Database), таблица (компонент Table) или результат выполнения запроса (компонент Query)

    Следует обратить внимание на свойство visibieButtons. Оно позволяет скрыть некоторые кнопки компонента DBNavigator и тем самым запретить выполнение соответствующих операций над файлом данных. Например, присвоив значение False свойству VisibieButtons.nbDelete можно скрыть кнопку nbDelete и тем самым запретить удаление записей.

    На Рисунок 17.12 приведен вид формы приложения Архитектурные памятники Санкт-Петербурга после добавления компонента DBNavigator. Свойству DataSource компонента DBNavigator1 следует присвоить значение Table1.

    в форму приложения надо добавить

    Таблица 17.14. Значения свойств компонентов Table1 и DataSource1

    Свойство

    Значение

    Tablel . DatabaseName

    Tablel . TableName

    Tablel. Active DataSourcel . Dataset

    Школа school . db

    True

    Tablel

    Для обеспечения просмотра и редактирования данных в режиме таблицы в форму приложения надо добавить компонент DBGrid, значок которого находится на вкладке Data Controls (Рисунок 17.13). Вид формы разрабатываемого приложения после добавления компонента DBGrid приведен на Рисунок 17.14.

    Свойства компонента DBGrid

    Таблица 17.15. Свойства компонента DBGrid

    Свойство

    Определяет

    Name

    Имя компонента

    DataSource

    Источник отображаемых в таблице данных

    Columns

    Отображаемую в таблице информацию

    Options . dgTitles

    Разрешает вывод строки заголовка столбцов

    Options . dgIndicator

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

    Options . dgColumnResize

    Разрешает менять во время работы программы ширину колонок таблицы

    Options . dgColLines

    Разрешает выводить линии, разделяющие колонки таблицы

    Options . dgRowLines

    Разрешает выводить линии, разделяющие строки таблицы

    Для того чтобы задать, какая информация будет отображена в таблице во время работы программы, нужно сначала определить источник данных для таблицы (установить значения свойства DataSource), затем — установить значения уточняющих параметров свойства Columns. Значение свойства DataSource задается обычным образом, то есть в окне Object Inspector. Чтобы установить значение свойства Columns, надо в окне Object Inspector выбрать это свойство и щелкнуть на кнопке с тремя точками. В результате открывается окно редактора колонок (Рисунок 17.15).

    Свойства компонента column

    Таблица 17.16. Свойства компонента column

    Свойство

    Определяет

    FieldName

    Поле записи, содержимое которого выводится в колонке

    Width

    Ширину колонки в пикселах

    Font

    Шрифт, используемый для вывода текста в ячейках колонки

    Color

    Цвет фона колонки

    Alignment

    Способ выравнивания текста в ячейках колонки. Текст может быть выровнен по левому краю (taLeftJustify), по центру (taCenter) или по правому краю (taRight Justify)

    Title. Caption

    Заголовок колонки. Значением по умолчанию является имя поля записи

    Title .Alignment

    Способ выравнивания заголовка колонки. Заголовок может быть выровнен по левому краю (taLeftJustify), по центру (taCenter) или по правому краю (taRight Justify)

    Title. Color

    Цвет фона заголовка колонки

    Title. Font

    Шрифт заголовка колонки

    В простейшем случае для каждой колонки достаточно установить значение свойства FieldName, которое определяет имя поля записи, содержимое которого будет отображаться в колонке, а также значение свойства Title.Caption, определяющего заголовок колонки. В табл. 17.17 приведены значения свойств columns компонента DBGridl.



    Значения свойств компонента

    Таблица 17.17. Значения свойств компонента DBGrid1



    Свойства компонента Query

    Таблица 17.18. Свойства компонента Query

    Свойство

    Определяет

    Name

    SQL
    Active

    Имя компонента. Используется компонентом Datasource для связи результата выполнения запроса (набора записей) с компонентом, обеспечивающим просмотр записей, например DBGrid

    Записанный на языке SQL запрос к базе данных (к таблице)

    При присвоении свойству значения True активизирует выполнение запроса

    Для того чтобы во время разработки программы задать, какая информация будет выделена из базы данных в результате выполнения запроса, свойство SQL должно содержать представленный на языке SQL запрос на выборку данных.

    В общем виде запрос на выборку из таблицы данных выглядит так:

    SELECT Список-Полей FROM

    Специальные символы используемые при записи шаблонов

    Таблица 17.2. Специальные символы, используемые при записи шаблонов

    Символ шаблона

    Допустимый при вводе символ

    *

    &

    @

    *.

    Цифра Любая буква (прописная или строчная) Любая буква (автоматически преобразуется в прописную) Любая буква (автоматически преобразуется в строчную) Любой символ

    Любой символ (если введена буква, то она автоматически преобразуется в прописную)

    Символ, следующий за символом "точка с запятой", интерпретируется как обычный символ, а не символ шаблона

    Любое количество повторяющихся, определяемых следующим за "звездочкой" символом шаблона

    Некоторые элементы данных поля могут быть необязательными, например, код города для номера телефона. Элементы шаблона, обеспечивающие ввод необязательных данных, заключают в квадратные скобки. Например, шаблон [(###)]###-##-## позволяет вводить в поле номер телефона как с заключенным в скобки кодом города, так и без кода.

    Шаблоны позволяют не только контролировать правильность вводимых в поле данных путем блокирования ввода неверных символов, но и обеспечивают автоматизацию ввода данных. Это достигается путем указания в шаблоне в квадратных или фигурных скобках списка допустимых значений содержимого поля.

    Например, если для поля Address задать шаблон {Санкт-Петербург, Москва, Воронеж}*@ или [Санкт-Петербург, Москва, Воронеж]*@, то во время ввода данных в это поле название соответствующего города будет появляться сразу после ввода одной из букв: с, м или в. Отличие фигурных скобок от квадратных и, следовательно, этих шаблонов друг от друга состоит в том, что в первом шаблоне содержимое поля обязательно должно начинаться с названия одного из перечисленных в списке городов, а во втором — город может называться по-другому, однако его название придется вводить полностью.

    После того как будет определена структура таблицы, таблицу следует сохранить. Для этого необходимо нажать кнопку Save As. В результате открывается окно Save Table As. В этом окне из списка Alias нужно выбрать псевдоним базы данных, частью которой является созданная таблица, а в поле Имя файла ввести имя файла, в котором нужно сохранить созданную таблицу.

    Если перед тем как нажать кнопку Сохранить установить флажок Display table, то в результате нажатия кнопки Сохранить открывается диалоговое окно Table , в котором можно ввести данные в только что созданную таблицу.

    Если таблица базы данных недоступна, то для того чтобы ввести данные в таблицу, таблицу нужно открыть. Для этого надо из меню File выбрать команду Open | Table, затем в появившемся диалоговом окне Open table в списке Alias выбрать псевдоним нужной базы данных и таблицу. Следует обратить внимание, что таблица будет открыта в режиме просмотра, в котором изменить содержимое таблицы нельзя. Для того чтобы в таблицу можно было вводить данные, нужно активизировать режим редактирования таблицы, для чего необходимо из меню Table выбрать команду Edit Data.

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

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

    Если при вводе данных в таблицу буквы русского алфавита отображаются неверно, то надо изменить шрифт, используемый для отображения данных. Для этого необходимо в меню Edit выбрать команду Preferences и в появившемся диалоговом окне, во вкладке General, щелкнуть на кнопке Change. В результате этих действий откроется диалоговое окно Change Font, в котором нужно выбрать русифицированный шрифт. Следует обратить внимание, что в Windows 2000 (Windows XP) используются шрифты типа Open Type, в то время как программа Database Desktop ориентирована на работу со шрифтами TrueType. Поэтому в списке шрифтов нужно выбрать русифицированный шрифт именно TrueType. После этого надо завершить работу с Database Desktop, так как внесенные в конфигурацию изменения будут действительны только после перезапуска утилиты.

    Памятники СанктПетербурга

    Таблица 17.4. Памятники Санкт-Петербурга

    Памятник

    Архитектор

    Историческая справка

    Иллюстрация

    Адмиралтейство

    А. Д. Захаров

    Здание Адмиралтейства таким, как оно выглядит сейчас, стало после перестройки в 1806—1823 годах. Автор проекта — гениальный русский зодчий А. Д. Захаров. Высота шпиля: 72 метра

    admiral.bmp

    Александровская колонна

    Огюст Монферран

    Памятник победы России над войсками Наполеона в Отечественной войне 1812 года. Открыта 30 августа 1 834 года. Высота: 47,5 метра; вес гранитного ствола: 600 тонн

    aleks.bmp

    Зимний дворец

    Ф. Б. Растрелли

    Зимний дворец много раз менял свой облик. Последний раз он перестраивался по проекту Растрелли. Строительство дворца продолжалось более семи лет (1754— 1 762 годы)

    herm.bmp

    Памятник

    Архитектор

    Историческая справка

    Иллюстрация

    Исаакиевский собор

    Огюст Монферран

    Исаакиевский собор, четвертый по счету, стали возводить в 1818 году. Строился собор 40 лет и был окончен в 1 858 году. Автор проекта— Огюст Монферран

    isaak.bmp

    Ростральные

    Тома де Томон

    32-метровые ростральные ко-

    rostr.bmp

    колонны



    лонны, органично вошедшие в архитектурный ансамбль Стрелки Васильевского острова, были сооружены в 1810 году. Они напоминают о существовавшем в древнем Риме обычае: украшать триумфальные колонны рострами захваченных кораблей



    Примечание

    На прилагаемой к книге дискете есть файлы, содержащие изображения исторических памятников Санкт-Петербурга.

    Теперь можно приступить к разработке приложения. Методика разработки приложения работы с базой данных ничем не отличается от методики создания обычной программы: к форме добавляются необходимые компоненты, устанавливаются значения свойств компонентов, разрабатываются необходимые процедуры обработки событий.

    Приложение работы с базой данных должно содержать компоненты, обеспечивающие доступ к данным, возможность просмотра и редактирования содержимого полей. Компоненты доступа к данным находятся на вкладке Data Access палитры компонентов, а компоненты отображения данных — на вкладке Data Controls.

    Свойства компонента Table

    Таблица 17.5. Свойства компонента Table

    Свойство

    Определяет

    Name Database
    NameTable
    Name Table
    Type

    Active

    Имя компонента. Используется для доступа к свойствам компонента

    Имя базы данных, частью которой является таблица (файл данных), для доступа к которой используется компонент. В качестве значения свойства следует использовать псевдоним базы данных

    Имя файла данных (таблицы данных), для доступа к которому используется компонент

    Тип таблицы.


    Значения свойств компонента Table

    Таблица 17.7. Значения свойств компонента Table

    Свойство

    Значение

    Name

    Table1

    DatabaseName

    Peterburg

    TableName

    monuments . db

    Active

    True



    Значения свойств компонента DataSource

    Таблица 17.8. Значения свойств компонента DataSource

    Свойство

    Значение

    Name
    DataSet

    DataSourcel
    Table1



    Свойства компонентов DBText DBEdit и DBMеmо

    Таблица 17.9. Свойства компонентов DBText, DBEdit и DBMеmо

    Свойство

    Определяет

    Name

    DataSource

    DataField

    Имя компонента. Используется для доступа к свойствам компонента

    Компонент-источник данных

    Поле базы данных, для отображения или редактирования которого используется компонент

    В качестве примера использования компонентов DBEdit и овмето рассмотрим программу, которая обеспечивает работу с базой данных "Архитектурные памятники Санкт-Петербурга". Вид формы приложения приведен на Рисунок 17.9.

    Таблица базы данных (создается утилитой Database Desktop)

    Таблица базы данных (создается утилитой Database Desktop)

    Tablel. Active

    True



    DataSource1 . Dataset

    Tablel



    После настройки компонентов Table и Datasource в форму нужно добавить три компонента DBEdit и компонент овмето. Компоненты DBEdit предназначены для просмотра и редактирования полей Name, Architect и Photo,

    компонент овмето — для просмотра и редактирования поля Note. Значения свойств компонентов просмотра-редактирования полей базы данных приведены в табл. 17.11.



    Таблица может быть набором данных

    Таблица может быть набором данных в формате Paradox ("Paradox), dBase (ttDBase), FoxPro ("FoxPro) или представлять собой форматированный текстовый файл (ttASCII).

    Признак активизации файла данных (таблицы). В результате присваивания свойству значения True происходит открытие файла таблицы

    Во время разработки формы приложения значения свойств DatabaseName и TabieName задаются путем выбора из списков. В списке DatabaseName перечислены все зарегистрированные псевдонимы, а в списке TabieName -имена файлов таблиц, которые находятся в соответствующем псевдониму каталоге.



    Таблица WHERE (Критерий) ORDER BY СписокПолей

    Таблица WHERE (Критерий) ORDER BY СписокПолей

    где:

  • SELECT — команда выбора записей из таблицы и вывода содержимого полей, имена которых указаны в списке;
  • FROM — параметр команды, который определяет имя таблицы, из которой нужно сделать выборку;
  • WHERE — параметр, который задает критерий выбора. В простейшем случае критерий — это инструкция проверки содержимого поля;
  • ORDER BY - параметр, который задает условие, в соответствии с которым будут упорядочены записи, удовлетворяющие критерию запроса.
  • Например, запрос

    SELECT Fam, Name FROM ':Школа:school.db' WHERE

    (Class = '10a') ORDER BY Name, Fam

    обеспечивает выборку из базы данных "Школа" (из таблицы School.db) записей, у которых в поле class находится текст 10а, т. е. формирует упорядоченный по алфавиту список учеников 10-а класса.

    Другой пример. Запрос

    SELECT Fam, Name FROM ":Школа:school.db" WHERE

    (Fam > 'K') and (Fam < 'Л') ORDER BY Name, Fam

    обеспечивает выбор информации об учениках, фамилии которых начинаются на букву К.

    Запрос может быть сформирован и записан в свойство SQL во время разработки формы или во время работы программы.

    Для записи запроса в свойство SQL во время разработки формы используется редактор списка строк (Рисунок 17.18), окно которого открывается в результате щелчка на кнопке с тремя точками в строке свойства SQL окна Object Inspector.

    Тип

    Тип

    Константа

    Содержимое поля Bytes

    Y

    Двоичные данные. Поле этого типа используется для хранения данных, которые не могут быть интерпретированы Database Desktop

    Binary

    В

    Двоичные данные. Поле этого типа используется для хранения данных, которые не могут быть интерпретированы Database Desktop. Как и данные типа Memo, эти данные не находятся в файле таблицы. Поля типа Binary, как правило, содержат audio-данные

    Константа, определяющая тип поля, может быть введена с клавиатуры или путем выбора типа поля из списка, который появляется при щелчке правой кнопкой мыши в колонке Туре или при нажатии клавиши < Пробел >.

    Одно или несколько полей можно пометить как ключевые. Ключевое поле определяет логический порядок следования записей в таблице. Например, если символьное (тип Alpha) поле Fam (Фамилия) пометить как ключевое, то при выводе таблицы записи будут упорядочены в соответствии с алфавитным порядком фамилий. Если поле Fam не помечать как ключевое, то записи будут выведены в том порядке, в котором они были введены в таблицу. Следует обратить внимание на то, что в таблице не может быть двух записей с одинаковым содержимым ключевых полей. Поэтому в рассматриваемом примере ключевыми полями должны быть поля Fam (Фамилия) и Name (Имя). Тогда в таблицу можно будет ввести информацию об однофамильцах. Однако по-прежнему нельзя будет ввести однофамильцев, у которых совпадают имена. Поэтому в качестве ключевого поля обычно выбирают поле, которое содержит уникальную информацию. Для таблицы, содержащей список людей, в качестве ключевого можно выбрать поле Pasp (Паспорт).

    Для того чтобы пометить поле как ключевое, необходимо выполнить двойной щелчок в колонке Key. Следует обратить внимание на то, что ключевые поля должны быть сгруппированы в верхней части таблицы.

    Если данные, для хранения которых предназначено поле, должны обязательно присутствовать в записи, то следует установить флажок Required Field. Например, очевидно, что поле Fam (Фамилия) обязательно должно быть заполнено, в то время как поле Tel (Телефон) может оставаться пустым.

    Если значение, записываемое в поле, должно находиться в определенном диапазоне, то вводом значений в поля Minimum value (Минимальное значение) и Maximum value (Максимальное значение) можно задать границы диапазона.

    Поле Default value позволяет задать значение по умолчанию, которое будет автоматически записываться в поле при добавлении к таблице новой записи.

    Поле Picture позволяет задать шаблон, используя который можно контролировать правильность вводимой в поле информации. Шаблон представляет собой последовательность обычных и специальных символов. Специальные символы перечислены в табл. 17.2.

    Во время ввода информации в позицию поля, которой соответствует специальный символ, будут появляться только символы, допустимые для данного символа шаблона. Например, если в позиции шаблона стоит символ #, то в соответствующую этому символу позицию можно ввести только цифру. Если в позиции шаблона стоит обычный символ, то во время ввода информации в данной позиции будет автоматически появляться указанный символ.

    Например, пусть поле Tel типа А (строка символов) предназначено для хранения номера телефона, и программа, работающая с базой данных, предполагает, что номер телефона должен быть представлен в обычном виде, т. е. в виде последовательности сгруппированных, разделенных дефисами цифр. В этом случае в поле Picture следует записать шаблон: ###-##-##. При вводе информации в поле Tel будут появляться только цифры (нажатия клавиш с другими символами игнорируются), причем после ввода третьей и пятой цифр в поле будут автоматически добавлены дефисы.



    Удаленная база данных

    Удаленная база данных

    Данные (файлы) удаленной базы данных находятся на удаленном компьютере. (Следует обратить внимание, что каталоги удаленного компьютера не могут рассматриваться как сетевые диски.)

    Программа работы с удаленной базой данных состоит из двух частей: клиентской и серверной. Клиентская часть программы, работающая на компьютере пользователя, обеспечивает взаимодействие с серверной программой: посредством запросов, передаваемых на удаленный компьютер, предоставляет доступ к данным.

    Серверная часть программы, работающая на удаленном компьютере, принимает запросы, выполняет их и пересылает данные клиентской программе. Запросы представляют собой команды, представленные на языке SQL (Structured Query Language) — языке структурированных запросов.

    Программа, работающая на удаленном сервере, проектируется таким образом, чтобы обеспечить одновременный доступ к информации нескольким пользователям. При этом для обеспечения доступа к данным вместо механизма блокировки файлов используют механизм транзакций.

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

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

    Выбор информации из базы данных

    Выбор информации из базы данных

    При работе с базой данных пользователя, как правило, интересует не все ее содержимое, а некоторая конкретная информация. Найти нужные сведения можно последовательным просмотром записей. Однако такой способ поиска неудобен и малоэффективен.

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

    Для выборки из базы данных записей, удовлетворяющих некоторому критерию, предназначен компонент Query (Рисунок 17.17).

    Взаимодействие компонентов отображения и доступа к данным

    Рисунок 17.7. Взаимодействие компонентов отображения и доступа к данным

    Взаимодействие компонентов отображения и доступа к данным
    В простейшем случае, когда база данных представляет собой одну-единственную таблицу, приложение работы с базой данных должно содержать один компонент Table и один компонент DataSource.

    В табл. 17.5 перечислены свойства компонента Table, а в табл. 17.6 — свойства компонента DataSource. Свойства перечислены в том порядке, в котором следует устанавливать их значения после добавления компонентов в форму приложения.



    Значок компонента DBNavigator находится на вкладке Data Controls

    Рисунок 17.10. Значок компонента DBNavigator находится на вкладке Data Controls


     Значок компонента DBNavigator находится на вкладке Data Controls

    Значок компонента Query

    Рисунок 17.17. Значок компонента Query

     Значок компонента Query
    Компонент Query похож на компонент Table, но, в отличие от последнего, он представляет не всю базу данных (все записи), а только ее часть — записи, удовлетворяющие критерию запроса.

    В табл. 17.18 перечислены некоторые свойства компонента Query.



    Отладка программы в Delphi

    Активизация создантя образа установочного CDROM

    Рисунок 18.18. Активизация создантя образа установочного CD-ROM


     Активизация создантя образа установочного CDROM

    /B> В левой части окна проекта

    Рисунок 18.2. В левой части окна проекта перечислены этапы и команды процесса создания инсталляционной программы

    /B> В левой части окна проекта
    Команды настройки объединены в группы, название и последовательность которых отражает суть процесса создания инсталляционной программы. Заголовки групп пронумерованы. Настройка программы установки выполняется путем последовательного выбора команд. В результате выбора команды в правой части главного окна появляется список параметров. Команды, которые были выполнены, помечаются галочками.

    Ярлык создан теперь можно выполнить его настройку

    Рисунок 18.12. Ярлык создан, теперь можно выполнить его настройку


     Ярлык создан теперь можно выполнить его настройку



    Команда Setup Types позволяет задать возможные варианты установки программы

    Рисунок 18.5. Команда Setup Types позволяет задать возможные варианты установки программы


    Команда Setup Types позволяет задать возможные варианты установки программы



    Команды группы Configure the Target System

    Рисунок 18.9. Команды группы Configure the Target System

    Команды группы Configure the Target System
    Команда Shortcuts/Folders позволяет указать, куда нужно поместить ярлык, обеспечивающий запуск устанавливаемой программы. В результате выбора этой команды в правой части окна открывается иерархический список, в котором перечислены меню и папки, куда можно поместить ярлык программы. В этом списке необходимо выбрать меню, в которое должен быть помещен ярлык, щелкнуть правой кнопкой мыши и в появившемся списке выбрать команду New Shortcut (Рисунок 18.10).

    Команды группы Customize the Setup Appearance

    Рисунок 18.13. Команды группы Customize the Setup Appearance


     Команды группы Customize the Setup Appearance

    Команды группы Define Setup Requirements and Actions

    Рисунок 18.15. Команды группы Define Setup Requirements and Actions

     Команды группы Define Setup Requirements and Actions
    В результате выбора команды Requirements на экране появляется таблица (Рисунок 18.16), в которую надо ввести значения параметров, характеризующих систему: версию операционной системы (OS Version), тип процессора (Processor), объем оперативной памяти (RAM), разрешение экрана (Screen Resolution) и цветовую палитру (Color Depth). Значения характеристик задаются путем выбора из раскрывающегося списка, значок которого появляется в результате щелчка в поле значения параметра.

    Команды группы Organize Your Setup

    Рисунок 18.3. Команды группы Organize Your Setup

    Команды группы Organize Your Setup
    Значения большинства параметров, за исключением тех, которые идентифицируют устанавливаемую программу и ее разработчика, можно оставить без изменения. Параметры, значения которых нужно изменить, приведены в табл. 18.2.



    Команды группы Prepare for Release

    Рисунок 18.17. Команды группы Prepare for Release

     Команды группы Prepare for Release
    Для того чтобы активизировать процесс создания образа установочного диска (CD-ROM), нужно выбрать команду Build Your Release, щелкнуть правой кнопкой мыши на значке носителя, на который предполагается поместить программу установки, и из появившегося контекстного меню выбрать команду Build (Рисунок 18.18).

    В результате этих действий на диске компьютера в папке проекта будет создан образ установочного диска. Если в качестве носителя выбран CD-ROM, то образ будет помещен в подкаталог \Express\Cd_rom\DiskImages\Disk1.

    Команды группы Specify Application Data

    Рисунок 18.6. Команды группы Specify Application Data

    Команды группы Specify Application Data
    В результате выбора команды Files правая часть окна будет разделена на области (Рисунок 18.7). В области Source computer's files можно выбрать файлы, которые необходимо перенести на компьютер пользователя. В области Destination computer's folders надо выбрать папку, в которую эти файлы должны быть помещены. Для того чтобы указать, какие файлы нужно установить на компьютер пользователя, следует просто "перетащить" требуемые файлы из области Source computer's files в область Destination computer's files. Если в группе Features несколько элементов, то надо определить файлы для каждого элемента.

    Конфигурирование системы пользователя

    Конфигурирование системы пользователя

    Команды группы Configure the Target System (Рисунок 18.9) позволяют задать, какие изменения нужно внести в систему пользователя, чтобы настроить систему на работу с устанавливаемой программой.

    Начало работы над новым проектом

    Рисунок 18.1. Начало работы над новым проектом

    Начало работы над новым проектом
    После щелчка на кнопке ОК открывается окно проекта создания инсталляционной программы (Рисунок 18.2). В левой части окна перечислены этапы процесса создания и команды, при помощи которых задаются параметры создаваемой инсталляционной программы.

    Настройка диалогов

    Настройка диалогов

    Для взаимодействия с пользователем программа установки использует стандартные диалоговые окна. Разрабатывая программу инсталляции, программист может задать, какие диалоги увидит пользователь в процессе инсталляции программы.

    Чтобы задать диалоговые окна, которые будут появляться на экране монитора во время работы инсталляционной программы, надо в группе Customize the Setup Appearance (Рисунок 18.13) выбрать команду Dialogs и в открывшемся списке Dialogs (Рисунок 18.14) отметить диалоги, которые нужно включить в программу установки.

    Несколько элементов в группе Features обеспечивают возможность многовариантной установки

    Рисунок 18.4. Несколько элементов в группе Features обеспечивают возможность многовариантной установки

    Несколько элементов в группе Features обеспечивают возможность многовариантной установки
    Команда Setup Types позволяет задать, будет ли пользователю во время установки программы предоставлена возможность выбрать (в диалоговом окне Setup Type) вариант установки. Установка может быть обычной (Typical), минимальной (Minimal) или выборочной (Custom). Если устанавливаемая программа сложная, состоит из нескольких независимых компонентов, то эта возможность обычно предоставляется.

    Для программы Сапер 2002 предполагается только один вариант установки — Typical. Поэтому флажки Minimal и Custom нужно сбросить (Рисунок 18.5).

    Новый проект

    Новый проект

    После того как будет составлен список файлов, нужно запустить InstallShield Express, из меню File выбрать команду New и в поле Project Name and Location ввести имя файла проекта (Рисунок 18.1).

    Параметры характеризующие систему

    Рисунок 18.16. Параметры, характеризующие систему

     Параметры характеризующие систему
    Если программа не предъявляет особых требований к конфигурации системы, то команды группы Define Setup Requirements and Actions можно пропустить.

    Программа InstallShield Express

    Программа InstallShield Express

    Одним из популярных инструментов создания инсталляционных программ является пакет InstallShield Express. Borland настоятельно рекомендует использовать именно эту программу, поэтому она есть на установочном диске Borland Delphi 7 Studio.

    Процесс установки программы InstallShield Express обычный. Для того чтобы его активизировать, нужно запустить программу установки Delphi (вставить установочный CD-ROM в дисковод) и в открывшемся диалоговом окне Delphi Setup Launcher выбрать команду InstallShield Express — Borland Limited Edition. В результате этого будет запущен мастер установки. По завершении процесса установки в меню Пуск | Программы | InstallShield появляется команда Express, выбор которой запускает InstallShield Express.

    Процесс создания инсталляционного диска (CD-ROM) при помощи InstallShield Express рассмотрим на примере.

    Пусть нужно создать инсталляционный диск для программы Сапер 2002. Перед тем как непосредственно приступить к созданию установочной программы в InstallShield Express, нужно выполнить подготовительную работу — составить список файлов, которые должны быть установлены на компьютер пользователя; используя редактор текста, подготовить RTF-файлы лицензионного соглашения (EULA — End User Licensia Agreement) и краткой справки (Readme-файл). Список файлов программы Сапер 2002, которые должны быть перенесены на компьютер пользователя, приведен в табл. 18.1.



    Псевдоним

    Псевдоним

    Каталог

    [WindowsVolume]
    [Windows Folder]
    [SystemFolder]

    [ProgramFilesFolder]

    [PersonalFolder]

    Корневой каталог диска, на котором находится Windows
    Каталог Windows, например C:\Winnt
    Системный каталог Windows, например C:\Winnt\System32
    Каталог программ, например C:\Program Files

    Папка Мои документы на рабочем столе (расположение папки зависит от версии ОС и способа входа в систему)

    Очевидно, что возможности инсталлированной программы определяются составом установленных компонентов. Например, если установлены файлы справочной системы, то пользователю в процессе работы с программой доступна справочная информация. Команда Features (возможности) позволяет создать (определить) группы компонентов, которые определяют возможности программы и которые могут устанавливаться по отдельности. Разделение компонентов на группы позволяет организовать многовариантную, в том числе и определяемую пользователем, установку программы.

    В простейшем случае группа Features состоит из одного элемента Always Install. Чтобы добавить элемент в группу Features, нужно щелкнуть правой кнопкой мыши на слове Features, из появившегося контекстного меню выбрать команду New Feature Ins и ввести имя новой группы, например Help Files and Samples. После этого в поле Description следует ввести краткую характеристику элемента, а в поле Comments — комментарий (Рисунок 18.4).

    Выбор файлов которые нужно перенести на компьютер пользователя

    Рисунок 18.7. Выбор файлов, которые нужно перенести на компьютер пользователя

    Выбор файлов которые нужно перенести на компьютер пользователя
    Команда Object/Merge Modules позволяет задать, какие объекты, например динамические библиотеки или пакеты компонентов, должны быть помещены на компьютер пользователя и, следовательно, на установочную дискету. Объекты, которые нужно поместить на установочную дискету, выбираются в списке InstallShield Objects/Merge Modules (Рисунок 18.8).

    Системные требования

    Системные требования

    Если устанавливаемая программа предъявляет определенные требования к ресурсам системы, то, используя команды группы Define Setup Requirements and Actions (Рисунок 18.15), эти требования можно задать.

    Создание образа установочного диска

    Создание образа установочного диска

    Команды группы Prepare for Release (Рисунок 18.17) позволяют создать образ установочного диска (CD-ROM) и проверить, как работает программа установки.

    Структура

    Структура

    Команды группы Organize Your Setup (Рисунок 18.3) позволяют задать структуру программы установки.

    Файлы программы Сапер 2002 которые нужно установить на компьютер пользователя

    Таблица 18.1. Файлы программы Сапер 2002, которые нужно установить на компьютер пользователя

    Файл

    Назначение

    Куда устанавливать

    Saper.exe
    Saper.chm
    Readme.rtf
    Eula.rtf

    Программа
    Файл справочной информации
    Краткая справка о программе
    Лицензионное соглашение

    Program Files\Saper 2002
    Program Files\Saper 2002
    Program Files\Saper 2002
    Program Files\Saper 2002



    Параметры команды General Information

    Таблица 18.2. Параметры команды General Information

    Параметр

    Определяет

    Значение

    Product Name

    Название устанавливаемой программы

    Saper 2002

    Product Version

    Версия устанавливаемой программы

    1.01.0001

    INSTALLDIR

    Каталог компьютера пользователя, в который будет установлена программа

    [ProgramFiiesFolder] Saper 2002

    Следует обратить внимание на параметр INSTALLDIR. По умолчанию предполагается, что программа будет установлена в каталог, предназначенный для программ. Поскольку во время создания инсталляционной программы нельзя знать, как на компьютере пользователя называется каталог программ и на каком диске он находится, то вместо имени реального каталога используется его псевдоним — [ProgramFiiesFolder]. В процессе установки программы на компьютер пользователя инсталляционная программа получит из реестра Windows имя каталога программ и заменит псевдоним на это имя.

    Другие псевдонимы, которые используются в программе InstallShield Express, приведены в табл. 18.3



    Некоторые псевдонимы каталогов Windows

    Таблица 18.3. Некоторые псевдонимы каталогов Windows



    Диалоговые окна процесса установки

    Таблица 18.4. Диалоговые окна процесса установки

    Диалоговое окно

    Назначение

    Splash Bitmap

    Вывод иллюстрации, которая может служить в качестве информации об устанавливаемой программе. Размер иллюстрации — 465x281 пиксел, формат — BMP

    Install Welcome

    Вывод информационного сообщения на фоне иллюстрации (размер 499x312 пикселов)

    License Agreement

    Вывод находящегося в RFT-файле лицензионного сообщения. Позволяет прервать процесс установки программы в случае несогласия пользователя с предлагаемыми условиями

    Readme

    Вывод краткой информации об устанавливаемой программе

    Customer Information

    Запрашивает информацию о пользователе (имя, название организации) и, возможно, серийный номер устанавливаемой копии

    Destination Folder

    Предоставляет пользователю возможность изменить предопределенный каталог, в который устанавливается программа

    Database Folder

    Предоставляет пользователю возможность изменить предопределенный каталог, предназначенный для баз данных

    Setup Type

    Предоставляет пользователю возможность выбрать тип установки программы (Typical — обычная установка, Minimal — минимальная установка, Custom — выборочная установка)

    Custom Setup

    Предоставляет пользователю возможность выбрать устанавливаемые компоненты при выборочной (Custom) установке

    Setup Complete Success Информирует пользователя о завершении процесса установки. Позволяет задать программу, которая должна быть запущена после завершения установки (как правило, это сама установленная программа), а также возможность вывода содержимого Readme-срайла.
    Setup Progress
    Показывает процент выполненной работы во время установки программы
    Ready to Install

    Вывод информации, введенной пользователем на предыдущих шагах, с целью ее проверки перед началом непосредственной установки программы

    Для того чтобы диалоговое окно появлялось во время работы -инсталляционной программы, необходимо установить флажок, расположенный слева от названия диалогового окна. Для окон License Agreement и Readme нужно задать имена RTF-файлов, в которых находится соответствующая информация.

    В простейшем случае программа инсталляции может ограничиться выводом следующих диалогов:

  • Readme;
  • Destination Folder;
  • Ready to Install;
  • Setup Progress;
  • Setup Complete Success.


  • В списке Dialogs нужно отметить

    Рисунок 18.14. В списке Dialogs нужно отметить диалоги, которые должны появиться в процессе установки программы на компьютер пользователя

     В списке Dialogs нужно отметить
    В таблице Properties (справа от списка диалогов) перечислены свойства выбранного диалога. Программист может изменить значение этих свойств и, тем самым, выполнить настройку диалога. Например, для диалога Readme нужно задать имя файла (свойство Readme File), в котором находится краткая справка об устанавливаемой программе.

    Для большинства диалогов можно определить баннер (свойство Banner Bitmap) — иллюстрацию, которая отображается в верхней части окна диалога. Формат файла баннера — BMP, размер — 499x58 пикселов.

    В табл. 18.4 перечислены диалоговые окна, которые могут появиться во время работы инсталляционной программы.



    В списке Shortcuts нужно выбрать меню в которое должен быть помещен ярлык запуска программы

    Рисунок 18.10. В списке Shortcuts нужно выбрать меню, в которое должен быть помещен ярлык запуска программы

     В списке Shortcuts нужно выбрать меню в которое должен быть помещен ярлык запуска программы
    Затем, в диалоговом окне Browse for Shortcut Target, нужно выбрать файл программы (Рисунок 18.11), щелкнуть на кнопке Open и ввести имя ярлыка. После этого можно выполнить окончательную настройку ярлыка, например, в поле Arguments ввести параметры командной строки, а в поле Working Directory — рабочий каталог (Рисунок 18.12).

    Выбор файла для которого создается ярлык

    Рисунок 18.11. Выбор файла, для которого создается ярлык


     Выбор файла для которого создается ярлык

    Выбор объектов которые должны быть установлены на компьютер пользователя

    Рисунок 18.8. Выбор объектов, которые должны быть установлены на компьютер пользователя


    Выбор объектов которые должны быть установлены на компьютер пользователя



    Выбор устанавливаемых компонентов

    Выбор устанавливаемых компонентов

    Команды группы Specify Application Data (Рисунок 18.6) позволяют определить компоненты программы, которые должны быть установлены на компьютер пользователя. Если в проекте определены несколько групп компонентов (см. команду Features), то нужно определить компоненты для каждой группы.

    

        Программирование: Языки - Технологии - Разработка