От Delphi 4 к Delphi 5 часть 26
От Delphi 4 к Delphi 5.
Последовательность обработки исключений
Составляя программный блок, вы можете использовать вложенные защищенные блоки, чтобы организовать локальную и глобальную обработку исключительных ситуаций.
Это можно представить следующим образом:
try {самый верхний уровень обработки исключительной ситуации}
{операторы, обращающиеся к операторам вложенной секции}
try {внешняя секция except... end. }
try {вложенная секция except...end. }
{операторы с локальной защитой от ошибок}
except
on EUnderflow do {локальная обработка исключительных ситуаций}
on EOverflow do
on EZeroDivide do
end;
except
on EMathError do {обработка исключительной ситуации внешней секцией}
end;
except
on EAbort do {окончательная обработка исключительной ситуации}
end;
Исключительные ситуации вложенного защищенного блока обрабатываются вложенной секцией except...end. Если она не может обработать исключительную ситуацию, то управление передается внешней секции except...end. Если и она не справляется с обработкой, то управление передается обработчику исключительной ситуации вызывающей подпрограммы.
Теория, как известно, должна подкрепляться практикой. Рассмотрим пример с вложенными защищенными блоками.
procedure TForm1.Button1Click(Sender: TObject);
var
X,Y:Real;
begin
try
try
try
X:= StrToFloat(Edit1.Text);
Y:= StrToFloat(Edit2.Text);
X:=X/Y;
Edit1.Text:=FloatToStr(X);
except
on EUnderflow do
MessageDlg ('Потеря старших разрядов',
mtWarning, [mbOk],0);
end;
except
on EZeroDivide do
MessageDlg ('Произошло деление на нуль; повторите ввод',
mtWarning, [mbOk],0);
end;
except
on EConvertError do
MessageDlg ('Осуществите правильный ввод',
mtWarning, [mbOk],0);
end;
end;
end.
Чтобы посмотреть работу, вложенных блоков защиты, произведите генерацию исключительной ситуации. Для этого введите нулевое значение в текстовый редактор Edit2 и любое числовое значение в текстовый редактор Edit1. При генерации данного исключения осуществляется поиск соответствующего ему обработчика on в том блоке try...except, в котором создалась исключительная ситуация. Для данного примера это секция on UnderFlow do. Если соответствующий обработчик не найден, поиск продолжается и производится в обрамляющем блоке try...except. Для нашего примера — это обработчик события деление на нуль числа с плавающей запятой, on EZeroDivide do, соответствует сгенерированной ситуации. Выдается сообщение, организованное вами в программном коде: " Произошло деление на нуль, повторите ввод".
Сгенерируйте другую исключительную ситуацию, введите буквенное значение в любой редактор текста Edit1, Edit2. Произведите деление, данная исключительная ситуация будет обработана на самом верхнем уровне, это секция try ...except с обработчиком on EConvertError do (ошибка преобразования строк или объектов, в частности StrToFloat ) . Вы получите сообщение, созданное вами, "Осуществите правильный ввод". Как только оператор on, соответствующий данному исключению, найден и выполнен, объект исключения разрушается и управление передается оператору, следующему за тем блоком try...except, в котором осуществлен перехват.
Возможен такой вариант, когда в самом обработчике исключения в процессе обработки возникла исключительная ситуация. В этом случае обработка прерывается, прежнее исключение разрушается и генерируется новое исключение. Его обработчик ищется в блоке try except, внешнем по отношению к тому, в котором возникло новое исключение.
Этот поиск продолжается по всем уровням. И только если он закончился безрезультатно, выполняется стандартная обработка исключения, заключающаяся в выдаче пользователю сообщения о типе исключения.
Для нашего случая произведите замену оператора on EConvertError do на on EmathError do, сгенерируйте исключительную ситуацию вводом буквенного выражения в текстовый редактор Edit1 — вы получите сообщение (рисунок 1) о необходимости ввода вещественного числа.
Преднамеренная генерация исключений, оператор raise.
В ряде случаев возникает необходимость сгенерировать исключительную ситуацию искусственно. Например, вы обработали какое-то исключение, но хотите, чтобы его обработка была завершена обработчиком внешнего по отношению к данному блоку try...except. Т.е. в этом случае необходимо сгенерировать повторно исключение того же типа, что и прежнее, ввиду того, что прежнее разрушено обработчиком исключения.
Повторная генерация исключительной ситуации осуществляется ключевым словом raise.
try {внешняя секция except... end. }
try {вложенная секция except...end. }
{операторы с локальной защитой от ошибок}
except
on < тип исключения > {локальная обработка исключительных ситуаций}
begin
< обработка исключений внутренней секцией >
raise
end;
end;
except
on <операторы внешнего блока> do {обработка исключительной ситуации внешней секцией}
end;
С помощью ключевого слова raise можно сгенерировать не только повторно исключение, но и исключение любого типа в любом месте программы.
Можно указать тип исключения и один из его конструкторов:
raise < тип исключения >.Create (<текст сообщения>);
Тип исключения может быть любым из определенных в Delphi.
Рассмотрим пример:
if (Edit1.Text='') then
raise EZeroDivide.Create(' Сделайте правильный ввод ')
при неправильном вводе прерывается расчет, генерируется исключение типа EZeroDivide.
Таким образом, можно использовать генерацию исключительных ситуаций, не связанную с их первоначальным смыслом, для своих целей.
Создание своего типа исключения.
Конечно, лучше всего создать свой класс исключительных ситуаций, чтобы не вносить путаницу в программный код.
Классы исключительных ситуаций в Delphi являются производными от класса Exception. Созданное вами исключение будет содержать свойства и методы класса Exception, но они могут содержать дополнительную информацию, определенную вами. Если нет дополнительной информации, то объявление нового класса исключений производится в разделе type следующим образом:
type
< имя класса исключения > class(Exception)
end;
Имена новых классов исключений должны начинаться с символа E.
Рассмотрим пример создания собственного типа исключения. В приложении производится анализ содержимого окна текстового редактора Edit1, на ввод выражения "Слово". В случае неправильного ввода произойдет генерация исключительной ситуации с выдачей сообщения (рисунок 2).
type
EOwn = class(Exception)
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
if Edit1.Text = 'Слово' then
Edit1.Text:='Ввод правильный'
else
raise EOwn.Create('Введите кодовое слово');
end;
end.
Класс Exception наследует все функции родителя TObject. В интерфейсе класса Exception описаны восемь конструкторов, которые наследуют все исключения.
Конструктор Create(const Msg: string) передает строку сообщения Msg свойству Message.
Конструктор CreateFmt(const Msg: string; const Args: array of const) формирует строку свойства Message, исходя из строки описания формата Msg и массива аргументов Args.
Конструктор CreateRes(Ident: Integer) задает строку свойства Message идентификатором Ident строки сообщения в ресурсах проекта.
Конструктор CreateResFmt(Ident: Integer; const Args: array of const) задает строку свойства Message идентификатором Ident строки описания формата в ресурсах проекта и массивом аргументов Args.
Конструктор CreateHelp(const Msg: string; HelpContext: Integer) передает строку сообщения Msg свойству Message; передает свойству HelpContext идентификатор HelpContext экрана контекстно-зависимой справки по этому исключению.
Конструктор CreateFmtHelp(const Msg: string; const Args: array of const: HelpContext: Integer) формирует строку свойства Message, исходя из строки описания формата Msg и массива аргументов Args. Передает свойству HelpContext экрана контекстно-зависимой справки по этому исключению.
Конструктор CreateResHelp(Ident, HelpContext: Integer) задает строку свойства Message идентификатором Ident строки сообщения в ресурсах проекта; передает свойству HelpContext идентификатор HelpContext экрана контекстно-зависимой справки по этому исключению.
Конструктор CreateResFmtHelp(Ident: Integer; const Args: array of const; HelpContext: Integer) формирует строку свойства Message исходя из строки описания формата в ресурсах проекта, указываемой идентификатором Ident, и массива аргументов Args. Передает свойству HelpContext идентификатор HelpContext экрана контекстно-зависимой справки по этому исключению.
Таким образом, конструкторы, не имеющие в своем имени компонентов Fmt или Res, принимают параметр Msg типа string, являющийся текстом, который заносится в свойство Message и в дальнейшем при обработке исключения системным обработчиком отображается в окне сообщений. Вы уже использовали конструктор такого типа в примере
{генерация собственного исключения}
raise EOwn.Create('Введите кодовое слово'); или
{генерация стандартного исключения с измененным сообщением}
raise EZeroDivide.Create('Произошло деление на нуль');.
Конструкторы с именем Fmt принимают параметр Msg типа string, являющийся строкой описания формата текста, и параметр Args, являющийся массивом переменных, значения которых включаются в текст в соответствии с форматом, записанным в Msg. Значение свойства Message формируется обращением к функции Format в модуле SysUtils, которая и формирует текст сообщения в соответствии со строкой описания формата и списком массива.
Строка описания формата .
Строка описания формата определяет способ форматирования данных и используется в таких функциях, как Format, FormatBuf, FmtStr, StrFmt, StrLFmt конструкторах исключений и др.
Строка описания формата содержит два типа объектов: обычные символы, которые непосредственно копируются в форматированную строку, и спецификаторы формата, которые определяют формат записи в результирующую строку списка аргументов.
Спецификатор формата имеет вид
%[<индекс>:][-][<ширина>][ <точность>]<тип>
Спецификатор формата начинается с символа "%". Затем без пробелов следует ряд необязательных полей:
[<индекс>:] определяет индекс (номер) аргумента в заданном списке, к которому относится данный спецификатор формата.
[-] индикатор выравнивания влево.
[<ширина>] устанавливает ширину поля.
[<точность>] спецификатор точности.
Затем так же без пробела размещается обязательное единственное поле <тип>, определяющее, как и в каком формате будет интерпретироваться аргумент.
Ниже приводится таблица спецификаторов типа:
d — десятичное целое. Значение преобразуется в строку десятичных цифр;
e — н аучный формат значения с плавающей запятой. Значение преобразуется в формат вида "-d.ddd...E+ddd", где d означает цифру;
f — формат с фиксированной точкой значения с плавающей запятой. Значение преобразуется в формат вида "-ddd.ddd...";
g — обобщенный формат чисел с плавающей запятой. Значение преобразуется в формат научный или с фиксированной точкой, в зависимости от того, какой из них дает более короткую запись;
n — формат, подобный формату с фиксированной точкой для чисел с плавающей запятой, но отличающийся наличием в результирующей строке разделителей тысяч. Иными словами, число представляется в форме "-d,ddd,ddd.ddd...";
m — монетарный формат чисел с плавающей запятой. Значение преобразуется в строку, представляющую собой денежную сумму;
p — формат отображения указателей. Значение преобразуется в строку вида "XXXX:YYYY", где XXXX and YYYY — сегмент и смещение указателя, выражаемые четырьмя шестнадцатеричными цифрами;
s — формат строки для аргументов вида символ, строка или строка типа PChar . Строка или символ просто вставляются в результирующую строку. Если задан спецификатор точности, то он определяет максимальное число вставляемых символов. Если вставляемая строка длиннее, она усекается;
x — шестнадцатеричный формат целых чисел. Значение аргумента преобразуется в строку шестнадцатеричных цифр. Если задан спецификатор точности, то он указывает минимальное число цифр в строке; если строка оказывается короче, она дополняется слева нулями.
Функция Format возвращает отформатированную строку, представляющую собой результат применения строки описания формата Format к открытому массиву аргументов Args. Например, оператор
s:=Format('Задано %d параметров из %d ', [N1, N2]);
при переменных N1=5 и N2=10 присвоит переменной s значение "Задано 5 параметров из 10".
Использование функции формат:
raise EOwn.Create(Format)(' 'Задано %d параметров из %d ', [N1, N2]);
Функция формат используется для форматированного вывода информации о значениях переменных N1 и N2.
Компонент DrawGrid.
Данный компонент является мощным инструментом для создания и обслуживания табличных структур данных. Он обеспечивает двумерное представление данных, упорядоченных по столбцам и рядам. Для обеспечения работоспособности таблицы в ней необходимо определить обработчик события OnDrawCell, которое возникает при необходимости прорисовать ту или иную ячейку.
Компонент DrawGrid является родителем для строковой таблицы, поэтому описанные свойства для компонента StringGrid полностью подходят и для компонента DrawGrid, кроме относящихся к тексту, т.е. кроме свойств Cells, Cols, Rows, Objects. С этой точки зрения компонент StringGrid обладает большими возможностями, чем DrawGrid.
В основном компонент DrawGrid используется для создания в приложении таблицы, которая может содержать графические изображения.
Рассмотрим пример использования компонента DrawGrid для отображения картинок.
public
slBitMap: TStringList;
{ Это поле будет использоваться для хранения текстовых строк
и картинок }
end;
var
fmDrawGrid: TfmDrawGrid;
implementation
{$R *.DFM}
procedure TfmDrawGrid.FormCreate(Sender: TObject);
{Создание и наполнение списка slBitMap}
const
FNames: array [0..3] of String = ('Самолет.bmp','Яхта.bmp','Натуралист.bmp',
'Программист.bmp'); {имена файлов с картинками}
var
K:Integer;
begin
{Создание списка строк}
slBitmap:= TStringList.Create;
{Вставка названия файлов и картинок}
with slBitMap do for K:= 0 to 3 do
begin
Add(Fnames[K]);
Objects[K]:= TBitMap.Create;
(Objects[K] as TBitMap). LoadFromFile(FNames[K]);
end;
end;
procedure TFmDrawGrid.FormDestroy(Sender: TObject);
begin
{Уничтожение списка строк}
slBitMap.Free;
end;
{Редактирование текста}
procedure TfmDrawGrid.dgDrawGetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
Value:= slBitMap[2* ACol + ARow];
end;
procedure TfmDrawGrid.dgDrawSetEditText(Sender: TObject; ACol,
ARow: Integer; const Value: String);
begin
{Прорисовка картинки из slBitmap. Objects и текста из slBitMap}
slBitMap[2* ACol + ARow]:= Value;
end;
procedure TfmDrawGrid.dgDrawDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
K:Integer;
begin
{Пересчет координат ячейки в индекс списка}
K:=2*ACol + ARow;
with dgDraw.Canvas, Rect, slBitMap do
begin
{Уменьшение высоты картинки для вывода под ней текста}
Bottom:=Bottom — TextHeight('1') -2;
{Рисование картинки}
StretchDraw(Rect,(Objects[K] as TBitMap));
{Рисование текста по горизонтали и его вывод}
TextOut(Left + (Right — Left — TextWidth(slBitMap[K])) div 2,
Bottom + 1, slBitMap[K]);
end;
end;
procedure TfmDrawGrid.dgDrawResize(Sender: TObject);
begin
{Изменение размера ячеек при изменении размеров окна, запас в один пиксель необходим для предотвращения автопрокрутки}
with dgDraw do
begin
DefaultColWidth:=ClientRect.Right div 2 -1;
DefaultRowHeight:=ClientRect.Bottom div 2 — 1;
end;
end;
end.
На рисунке 3 показан результат работы программы Accomodation.
Литература:
(c) компьютерная газета
Последовательность обработки исключений
Составляя программный блок, вы можете использовать вложенные защищенные блоки, чтобы организовать локальную и глобальную обработку исключительных ситуаций.
Это можно представить следующим образом:
try {самый верхний уровень обработки исключительной ситуации}
{операторы, обращающиеся к операторам вложенной секции}
try {внешняя секция except... end. }
try {вложенная секция except...end. }
{операторы с локальной защитой от ошибок}
except
on EUnderflow do {локальная обработка исключительных ситуаций}
on EOverflow do
on EZeroDivide do
end;
except
on EMathError do {обработка исключительной ситуации внешней секцией}
end;
except
on EAbort do {окончательная обработка исключительной ситуации}
end;
Исключительные ситуации вложенного защищенного блока обрабатываются вложенной секцией except...end. Если она не может обработать исключительную ситуацию, то управление передается внешней секции except...end. Если и она не справляется с обработкой, то управление передается обработчику исключительной ситуации вызывающей подпрограммы.
Теория, как известно, должна подкрепляться практикой. Рассмотрим пример с вложенными защищенными блоками.
procedure TForm1.Button1Click(Sender: TObject);
var
X,Y:Real;
begin
try
try
try
X:= StrToFloat(Edit1.Text);
Y:= StrToFloat(Edit2.Text);
X:=X/Y;
Edit1.Text:=FloatToStr(X);
except
on EUnderflow do
MessageDlg ('Потеря старших разрядов',
mtWarning, [mbOk],0);
end;
except
on EZeroDivide do
MessageDlg ('Произошло деление на нуль; повторите ввод',
mtWarning, [mbOk],0);
end;
except
on EConvertError do
MessageDlg ('Осуществите правильный ввод',
mtWarning, [mbOk],0);
end;
end;
end.
Чтобы посмотреть работу, вложенных блоков защиты, произведите генерацию исключительной ситуации. Для этого введите нулевое значение в текстовый редактор Edit2 и любое числовое значение в текстовый редактор Edit1. При генерации данного исключения осуществляется поиск соответствующего ему обработчика on в том блоке try...except, в котором создалась исключительная ситуация. Для данного примера это секция on UnderFlow do. Если соответствующий обработчик не найден, поиск продолжается и производится в обрамляющем блоке try...except. Для нашего примера — это обработчик события деление на нуль числа с плавающей запятой, on EZeroDivide do, соответствует сгенерированной ситуации. Выдается сообщение, организованное вами в программном коде: " Произошло деление на нуль, повторите ввод".
Сгенерируйте другую исключительную ситуацию, введите буквенное значение в любой редактор текста Edit1, Edit2. Произведите деление, данная исключительная ситуация будет обработана на самом верхнем уровне, это секция try ...except с обработчиком on EConvertError do (ошибка преобразования строк или объектов, в частности StrToFloat ) . Вы получите сообщение, созданное вами, "Осуществите правильный ввод". Как только оператор on, соответствующий данному исключению, найден и выполнен, объект исключения разрушается и управление передается оператору, следующему за тем блоком try...except, в котором осуществлен перехват.
Возможен такой вариант, когда в самом обработчике исключения в процессе обработки возникла исключительная ситуация. В этом случае обработка прерывается, прежнее исключение разрушается и генерируется новое исключение. Его обработчик ищется в блоке try except, внешнем по отношению к тому, в котором возникло новое исключение.
Этот поиск продолжается по всем уровням. И только если он закончился безрезультатно, выполняется стандартная обработка исключения, заключающаяся в выдаче пользователю сообщения о типе исключения.

Преднамеренная генерация исключений, оператор raise.
В ряде случаев возникает необходимость сгенерировать исключительную ситуацию искусственно. Например, вы обработали какое-то исключение, но хотите, чтобы его обработка была завершена обработчиком внешнего по отношению к данному блоку try...except. Т.е. в этом случае необходимо сгенерировать повторно исключение того же типа, что и прежнее, ввиду того, что прежнее разрушено обработчиком исключения.
Повторная генерация исключительной ситуации осуществляется ключевым словом raise.
try {внешняя секция except... end. }
try {вложенная секция except...end. }
{операторы с локальной защитой от ошибок}
except
on < тип исключения > {локальная обработка исключительных ситуаций}
begin
< обработка исключений внутренней секцией >
raise
end;
end;
except
on <операторы внешнего блока> do {обработка исключительной ситуации внешней секцией}
end;
С помощью ключевого слова raise можно сгенерировать не только повторно исключение, но и исключение любого типа в любом месте программы.
Можно указать тип исключения и один из его конструкторов:
raise < тип исключения >.Create (<текст сообщения>);
Тип исключения может быть любым из определенных в Delphi.
Рассмотрим пример:
if (Edit1.Text='') then
raise EZeroDivide.Create(' Сделайте правильный ввод ')
при неправильном вводе прерывается расчет, генерируется исключение типа EZeroDivide.
Таким образом, можно использовать генерацию исключительных ситуаций, не связанную с их первоначальным смыслом, для своих целей.
Создание своего типа исключения.
Конечно, лучше всего создать свой класс исключительных ситуаций, чтобы не вносить путаницу в программный код.
Классы исключительных ситуаций в Delphi являются производными от класса Exception. Созданное вами исключение будет содержать свойства и методы класса Exception, но они могут содержать дополнительную информацию, определенную вами. Если нет дополнительной информации, то объявление нового класса исключений производится в разделе type следующим образом:
type
< имя класса исключения > class(Exception)
end;
Имена новых классов исключений должны начинаться с символа E.

type
EOwn = class(Exception)
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
if Edit1.Text = 'Слово' then
Edit1.Text:='Ввод правильный'
else
raise EOwn.Create('Введите кодовое слово');
end;
end.
Класс Exception наследует все функции родителя TObject. В интерфейсе класса Exception описаны восемь конструкторов, которые наследуют все исключения.
Конструктор Create(const Msg: string) передает строку сообщения Msg свойству Message.
Конструктор CreateFmt(const Msg: string; const Args: array of const) формирует строку свойства Message, исходя из строки описания формата Msg и массива аргументов Args.
Конструктор CreateRes(Ident: Integer) задает строку свойства Message идентификатором Ident строки сообщения в ресурсах проекта.
Конструктор CreateResFmt(Ident: Integer; const Args: array of const) задает строку свойства Message идентификатором Ident строки описания формата в ресурсах проекта и массивом аргументов Args.
Конструктор CreateHelp(const Msg: string; HelpContext: Integer) передает строку сообщения Msg свойству Message; передает свойству HelpContext идентификатор HelpContext экрана контекстно-зависимой справки по этому исключению.
Конструктор CreateFmtHelp(const Msg: string; const Args: array of const: HelpContext: Integer) формирует строку свойства Message, исходя из строки описания формата Msg и массива аргументов Args. Передает свойству HelpContext экрана контекстно-зависимой справки по этому исключению.
Конструктор CreateResHelp(Ident, HelpContext: Integer) задает строку свойства Message идентификатором Ident строки сообщения в ресурсах проекта; передает свойству HelpContext идентификатор HelpContext экрана контекстно-зависимой справки по этому исключению.
Конструктор CreateResFmtHelp(Ident: Integer; const Args: array of const; HelpContext: Integer) формирует строку свойства Message исходя из строки описания формата в ресурсах проекта, указываемой идентификатором Ident, и массива аргументов Args. Передает свойству HelpContext идентификатор HelpContext экрана контекстно-зависимой справки по этому исключению.
Таким образом, конструкторы, не имеющие в своем имени компонентов Fmt или Res, принимают параметр Msg типа string, являющийся текстом, который заносится в свойство Message и в дальнейшем при обработке исключения системным обработчиком отображается в окне сообщений. Вы уже использовали конструктор такого типа в примере
{генерация собственного исключения}
raise EOwn.Create('Введите кодовое слово'); или
{генерация стандартного исключения с измененным сообщением}
raise EZeroDivide.Create('Произошло деление на нуль');.
Конструкторы с именем Fmt принимают параметр Msg типа string, являющийся строкой описания формата текста, и параметр Args, являющийся массивом переменных, значения которых включаются в текст в соответствии с форматом, записанным в Msg. Значение свойства Message формируется обращением к функции Format в модуле SysUtils, которая и формирует текст сообщения в соответствии со строкой описания формата и списком массива.
Строка описания формата .
Строка описания формата определяет способ форматирования данных и используется в таких функциях, как Format, FormatBuf, FmtStr, StrFmt, StrLFmt конструкторах исключений и др.
Строка описания формата содержит два типа объектов: обычные символы, которые непосредственно копируются в форматированную строку, и спецификаторы формата, которые определяют формат записи в результирующую строку списка аргументов.
Спецификатор формата имеет вид
%[<индекс>:][-][<ширина>][ <точность>]<тип>
Спецификатор формата начинается с символа "%". Затем без пробелов следует ряд необязательных полей:
[<индекс>:] определяет индекс (номер) аргумента в заданном списке, к которому относится данный спецификатор формата.
[-] индикатор выравнивания влево.
[<ширина>] устанавливает ширину поля.
[<точность>] спецификатор точности.
Затем так же без пробела размещается обязательное единственное поле <тип>, определяющее, как и в каком формате будет интерпретироваться аргумент.
Ниже приводится таблица спецификаторов типа:
d — десятичное целое. Значение преобразуется в строку десятичных цифр;
e — н аучный формат значения с плавающей запятой. Значение преобразуется в формат вида "-d.ddd...E+ddd", где d означает цифру;
f — формат с фиксированной точкой значения с плавающей запятой. Значение преобразуется в формат вида "-ddd.ddd...";
g — обобщенный формат чисел с плавающей запятой. Значение преобразуется в формат научный или с фиксированной точкой, в зависимости от того, какой из них дает более короткую запись;
n — формат, подобный формату с фиксированной точкой для чисел с плавающей запятой, но отличающийся наличием в результирующей строке разделителей тысяч. Иными словами, число представляется в форме "-d,ddd,ddd.ddd...";
m — монетарный формат чисел с плавающей запятой. Значение преобразуется в строку, представляющую собой денежную сумму;
p — формат отображения указателей. Значение преобразуется в строку вида "XXXX:YYYY", где XXXX and YYYY — сегмент и смещение указателя, выражаемые четырьмя шестнадцатеричными цифрами;
s — формат строки для аргументов вида символ, строка или строка типа PChar . Строка или символ просто вставляются в результирующую строку. Если задан спецификатор точности, то он определяет максимальное число вставляемых символов. Если вставляемая строка длиннее, она усекается;
x — шестнадцатеричный формат целых чисел. Значение аргумента преобразуется в строку шестнадцатеричных цифр. Если задан спецификатор точности, то он указывает минимальное число цифр в строке; если строка оказывается короче, она дополняется слева нулями.
Функция Format возвращает отформатированную строку, представляющую собой результат применения строки описания формата Format к открытому массиву аргументов Args. Например, оператор
s:=Format('Задано %d параметров из %d ', [N1, N2]);
при переменных N1=5 и N2=10 присвоит переменной s значение "Задано 5 параметров из 10".
Использование функции формат:
raise EOwn.Create(Format)(' 'Задано %d параметров из %d ', [N1, N2]);
Функция формат используется для форматированного вывода информации о значениях переменных N1 и N2.
Компонент DrawGrid.
Данный компонент является мощным инструментом для создания и обслуживания табличных структур данных. Он обеспечивает двумерное представление данных, упорядоченных по столбцам и рядам. Для обеспечения работоспособности таблицы в ней необходимо определить обработчик события OnDrawCell, которое возникает при необходимости прорисовать ту или иную ячейку.
Компонент DrawGrid является родителем для строковой таблицы, поэтому описанные свойства для компонента StringGrid полностью подходят и для компонента DrawGrid, кроме относящихся к тексту, т.е. кроме свойств Cells, Cols, Rows, Objects. С этой точки зрения компонент StringGrid обладает большими возможностями, чем DrawGrid.
В основном компонент DrawGrid используется для создания в приложении таблицы, которая может содержать графические изображения.
Рассмотрим пример использования компонента DrawGrid для отображения картинок.
- Запустите Delphi.
- Запомните файл модуля под именем Accomodation_.pas, а файл проекта под именем Accomodation.dpr.
- Для отображения картинок в компоненте DrawGrid необходимо скопировать файлы картинок, например, из папки Clipart или из папки, в которой хранятся картинки, созданные вами, в папку, в которой вы сохранили свой проект. Таким образом, вы освобождаетесь от указания маршрута поиска файлов.
- Поместите на форму компонент DrawGrid, установите следующие атрибуты. Свойству Align определите значение AlClient. Свойствам ColCount и RowCount установите значение 2. Свойствам FixedCols, FixedRows установите значение 0. Установите в комплексном свойстве Options свойству goEditing значение True. Свойство Scrollbars установите в ssNone, т.е. полосы прокрутки не вставлять. Определите размер для ячеек компонента DrawGrid (DefaultRowHeight = 300, DefaultColWidth = 400). Ниже представлен программный код с комментариями действий.
public
slBitMap: TStringList;
{ Это поле будет использоваться для хранения текстовых строк
и картинок }
end;
var
fmDrawGrid: TfmDrawGrid;
implementation
{$R *.DFM}
procedure TfmDrawGrid.FormCreate(Sender: TObject);
{Создание и наполнение списка slBitMap}
const
FNames: array [0..3] of String = ('Самолет.bmp','Яхта.bmp','Натуралист.bmp',
'Программист.bmp'); {имена файлов с картинками}
var
K:Integer;
begin
{Создание списка строк}
slBitmap:= TStringList.Create;
{Вставка названия файлов и картинок}
with slBitMap do for K:= 0 to 3 do
begin
Add(Fnames[K]);
Objects[K]:= TBitMap.Create;
(Objects[K] as TBitMap). LoadFromFile(FNames[K]);
end;
end;
procedure TFmDrawGrid.FormDestroy(Sender: TObject);
begin
{Уничтожение списка строк}
slBitMap.Free;
end;
{Редактирование текста}
procedure TfmDrawGrid.dgDrawGetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
Value:= slBitMap[2* ACol + ARow];
end;
procedure TfmDrawGrid.dgDrawSetEditText(Sender: TObject; ACol,
ARow: Integer; const Value: String);
begin
{Прорисовка картинки из slBitmap. Objects и текста из slBitMap}
slBitMap[2* ACol + ARow]:= Value;
end;
procedure TfmDrawGrid.dgDrawDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
K:Integer;
begin
{Пересчет координат ячейки в индекс списка}
K:=2*ACol + ARow;
with dgDraw.Canvas, Rect, slBitMap do
begin
{Уменьшение высоты картинки для вывода под ней текста}
Bottom:=Bottom — TextHeight('1') -2;
{Рисование картинки}
StretchDraw(Rect,(Objects[K] as TBitMap));
{Рисование текста по горизонтали и его вывод}
TextOut(Left + (Right — Left — TextWidth(slBitMap[K])) div 2,
Bottom + 1, slBitMap[K]);
end;
end;
procedure TfmDrawGrid.dgDrawResize(Sender: TObject);
begin
{Изменение размера ячеек при изменении размеров окна, запас в один пиксель необходим для предотвращения автопрокрутки}

begin
DefaultColWidth:=ClientRect.Right div 2 -1;
DefaultRowHeight:=ClientRect.Bottom div 2 — 1;
end;
end;
end.
На рисунке 3 показан результат работы программы Accomodation.
Литература:
- Марко Канту. Delphi 2 для Windows 95/NT. Москва. ООО "Малип". 1997 г.
- Джон Матчо. Дэвид Р. Фолкнер. Delphi. Москва. БИНОМ. 1995 г.
- Эндрю Возневич. Delphi. Освой самостоятельно. Москва. Восточная книжная компания. 1996 г.
- В.В.Фаронов. Delphi 5. Учебный курс. Москва. Издательство Нолидж. 2000 г.
- А. Я. Архангельский. Программирование в Delphi 5. Москва. ЗАО "Издательство Бином". 2000 г.
(c) компьютерная газета
Компьютерная газета. Статья была опубликована в номере 35 за 2001 год в рубрике программирование :: delphi