Delphi для начинающих. Часть 2.
Delphi для начинающих. Часть 2. Сегодняшнюю статью я хочу, в первую очередь, посвятить интерфейсу среды разработки Delphi. Этот вопрос достаточно остро стоит и среди программистов, недавно начавших изучение Delphi, и среди матерых прогеров, которые сутками не спят, погрузившись в процесс создания очередной программы.
Начнем по порядку. Создавая очередную программу, пользователь компонует интерфейс, исходя из имеющихся у него подручных объектов, при этом он неизбежно сталкивается с необходимостью изменить то или иное его свойство. Как помнит наш читатель, свойства объектов на этапе разработки программы изменяются с использованием инспектора объектов. Этих свойств существует достаточно много. На них-то мы сейчас и остановимся.
Инспектор Объектов (рис. 1). В окне инспектора объектов имеются выпадающее меню и две вкладки. Выпадающее меню показывает нам, конфигурация какого объекта нам в настоящий момент представлена, а вкладки, собственно, эту конфигурацию помогают нам созерцать и изменять. Во вкладке Свойства ( Properties ) указано не что иное, как свойства формы проекта:). Рассмотрим некоторые основные свойства поподробнее:
Action — назначает для объекта действие;
ActiveControl — указывает на элемент формы, который имеет фокус;
Align — устанавливает положение объекта:
— AlNone — положение объекта определяется вручную пользователем;
— AlBottom ( AlTop ) — объект расположен внизу формы (если речь идет о форме проекта, то — внизу экрана). При этом высота объекта остается неизменной, а его ширина увеличивается до ширины формы (экрана);
— AlLeft ( AlRight ) — объект расположен в левой части формы (если речь идет о форме проекта, то — в левой части экрана). При этом ширина объекта остается неизменной, а его высота увеличивается до высоты формы (экрана);
— AlClient — объект занимает всю предоставленную площадь. Например, при установке данного свойства форме проекта, при запуске программы, окно будет растянуто на весь экран;
BiDiMode — это свойство используется для локализации приложения. Оно позволяет установить направление чтения текста в программе;
BorderStyle — свойство, отвечающее за тип формы. Включает в себя:
— bsNone — на форме полностью отсутствуют все системные элементы управления. Форма выглядит как прямоугольник без бортов и заголовка. При выполнении программы размер формы изменить нельзя;
— bsSingle — стандартное окно, но при этом отсутствует возможность изменения размеров формы. Набор системных кнопок зависит от свойства BorderIcon;
— bsDialog — стандартное диалоговое окно;
— bsToolWindow — панель инструментов. Похожа на стиль bsSingle, но при этом все системные элементы уменьшены;
— bsSizeToolWin — панель инструментов. Похожа на стиль bsSingle, но при этом все системные элементы уменьшены, возможно изменение размеров формы;
BorderIcons — группа свойств, отвечающих за видимость системных элементов — кнопок: свернуть, закрыть, развернуть, помощь и системное меню;
Caption — содержит текст названия формы проекта;
CurrentHelpFile — содержит имя файла контекстной помощи, используемого приложением;
HelpFile — задает имя файла помощи для приложения;
ShowHint — включает либо отключает показ всплывающих ярлыков подсказок;
Hint — содержит строку ярлыка подсказки;
Icon — указывает на значок приложения;
Cursor — устанавливает тип курсора, который будет установлен при наведении мыши на область объекта;
Visible — устанавливает такое свойство объекта, как видимость;
Enabled — указывает на состояние объекта. При значении False объект недоступен;
Font — группа свойств, характеризующих отображение текста, используемого объектом. С помощью этих свойств можно изменять цвет, размер, стиль, кодировку и шрифт текста;
Height — устанавливает высоту объекта в пикселях;
Width — устанавливает ширину объекта в пикселях;
Left — устанавливает отступ левого края объекта от левого края формы проекта в пикселях;
Top — устанавливает отступ верхнего края объекта от верхнего края формы проекта в пикселях;
Name — внутреннее имя объекта программы;
TabOrder — указывает направление перемещения фокуса при нажатии клавиши Tab (от начала к концу или от конца к началу, но при этом хочу заметить, что порядок перемещения фокуса можно изменять с помощью диалога TabOrder (Edit/TabOrder...);
TabStop — при установленном значении False фокус при нажатии клавиши Tab на данный объект не переводится (при этом фокус переходит к объекту, стоящему следующим в списке TabOrder).
Выше описаны свойства, которые присущи многим компонентам. Однако стоит отметить, что, помимо вышеупомянутых параметров, компоненты имеют и специфические свойства. Их мы будем рассматривать по мере изучения материала.
Во второй вкладке Действия ( Events ) указаны методы-обработчики событий. Познакомимся с ними поближе:
OnActivate — вызывается при передаче фокуса форме проекта;
OnDeactivate — вызывается при потере фокуса формой проекта;
OnClose — вызывается при закрытии формы. Предназначен для выполнения операций, позволяющих пользователю принять решение о закрытии формы либо продолжении работы;
OnCreate — вызывается при создании формы;
OnDestroy — вызывается при уничтожении формы;
OnHide — вызывается при исчезновении формы с экрана;
OnPaint — вызывается при перерисовке формы;
OnShow — вызывается при появлении формы на экране;
OnClick — вызывается при нажатии на объект;
OnMouseDown — вызывается при нажатии кнопки мыши.
К сведению: для создания обработчика событий достаточно дважды нажать мышкой на пустое поле, соответствующее названию метода.
Окно редактора кода. Как наш любознательный читатель мог уже заметить, окно редактора кода представлено тремя частями:
— панель модулей описания переменных и используемых модулей;
— панель кода программы;
— панель найденных ошибок программы (на этапе создания программы данное окно является невидимым, активизируется, если это необходимо, при компиляции программы).
Думаю, на этом с интерфейсом можно остановиться и перейти к конкретным проблемам программирования. Начать я бы хотел с раздела Delphi, который обратил на себя внимание через наших читателей. Итак, диалоги . Казалось бы, достаточно простой раздел. Однако меня с десяток человек спросили, каким образом можно произвести операции над файлом, который должен выбрать пользователь. Какие только варианты решения мне ни приходилось читать: и создавали дополнительную форму объекта, и пытались заставить пользователя от руки написать адрес файла, и предлагали воспользоваться компонентами Treeview, OutLine и им подобным. При этом читатели сами понимали, что они делают лишнюю работу и что существует более короткий и простой путь для решения проблемы. Как оказывается, внутреннее чувство наших читателей их не повело. Достаточно было воспользоваться компонентом OpenDialog (страница Dialogs). Данный компонент легко устанавливается на форму проекта в виде квадрата. При запуске программы он невидим. Квадрат лишь указывает нам на то, что компонент установлен и помогает нам обращаться к его свойствам при помощи инспектора объектов. Рассмотрим их поподробнее.
Итак, после установки компонента на форму проекта диалоговое окно можно активизировать с помощью функции Execute:Boolean. При этом, если пользователь выбрал файл или несколько файлов и нажал кнопку ОК, то функция возвращает True. Свойство компонента FileName содержит имя последнего файла из списка выбранных в диалоге. Свойство Files — список всех файлов, выбранных в диалоге. Свойство InitialDir задает каталог, к которому диалог обращается при открытии. Свойство Title содержит заголовок диалогового окна. Следует также отметить свойство Filter. С его помощью при выборе и сохранении файлов удобно осуществлять отбор файлов только с заданными расширениями. Например, для создания фильтра для исполняемых файлов свойство должно содержать следующую строку:
'Исполняемые файлы | *.EXE'
В одном фильтре можно отбирать файлы и с различными расширениями:
'Графические изображения | *.JPG; *.GIF; *.PNG'
Фильтр также можно создать в простом редакторе, который связан со свойством Filter в инспекторе объектов.
Очень интересные свойства и при этом одни из самых важных для диалоговых компонентов (OpenDialog, SaveDialog, OpenPictureDialog, SavePictureDialog) представлены в группе Options. Они рассмотрены в следующей таблице:
Как и у многих других компонентов, у диалогов тоже существуют и свои методы-обработчики событий. Среди них наиболее интересными являются OnClose, OnFolderChange, OnSelectionChange, OnTypeChange (думаю, в пояснениях эти методы не нуждаются).
Исходя из всего вышесказанного, опишем процедуру (дабы увидеть все на конкретном примере), которая будет вызываться при нажатии на кнопку Button1, выполняющую запуск диалога OpenDialog1 и передающую путь к выбранному файлу в поле ввода Edit1:
procedure TForm1.Button1Click(Sender: TObject);
begin
opendialog1.execute; {запуск диалога с помощью функции execute}
{во время активации диалога выполнение процедуры приостанавливается}
edit1.text:=opendialog1.filename; {присваивание полю ввода Edit1 пути к файлу}
end;
На этом раздел диалогов работы с файлами заканчивается. Всего вышеописанного вполне достаточно для создания полноценных приложений. Мной были специально опущены некоторые моменты, о которых я не счел нужным писать. Они редко используются в программировании, однако расширяют возможности работы с программой. При огромном вашем желании я могу написать о них персонально. Заявки — на e-mail:).
Следующей остановкой я выбрал сообщения . Согласитесь, сообщения играют далеко не последнюю роль в работе программы. С помощью сообщений программист может извещать об ошибках пользователя при задании исходных данных для работы программы, система сообщает о некорректной работе приложений, благодаря сообщениям программные продукты доводят до нашего сведения информацию о своей версии, о разработчиках и фирме-производителе, наконец, планировщики сообщают пользователю о запланированных встречах, событиях. Реализовать сообщения можно несколькими способами: с помощью процедуры ShowMessage, функции MessageDlg, создания дополнительного окна.
Процедура showmessage позволяет вывести пользователю простое сообщение. При этом появится дополнительное окно с названием проекта и кнопкой ОК. Выглядит все это следующим образом:
Синтаксис:
ShowMessage(Msg: string);
Пример:
ShowMessage('Все задачи выполнены успешно');
Функция messageDlg позволяет создавать сложные диалоговые запросы с использованием обратной связи. Имеет вид дополнительного окна, дополненного изображением. При этом возможно использовать диалоговые запросы. Название окна зависит от типа запроса.
Синтаксис:
MessageDlg(Msg: string; AType: TMsgDlgType; AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
Msg — строковой параметр. Задает выводимое сообщение;
Atype — внутренний параметр функции. Задает тип сообщения:
— mtWarning — сообщение о предупреждении;
— mtError — сообщение об ошибке;
— mtInformation — информационное сообщение;
— mtConfirmation — сообщение о подтверждении;
— mtCustom — сообщение не содержит в углу изображения. Название окна соответствует названию исполняемого файла (аналогично showmessage).
Abuttons — задает имена кнопок, которые будут отображаться на диалоговом запросе. Возможны значения: mbYes, mbNo, mbOK, mbCancel, mbHelp, mbAbort, mbRetry, mbIgnore, mbAll.
HelpCtx — содержит номер раздела, который будет показан пользователю, если он вызовет справку, когда диалог активизирован.
Пример:
MessageDlg('Продолжить выполнение программы', mtConfirmation, [mbYes, mbNo], 0);
Для того чтобы определить, какой вариант ответа выбрал пользователь, можно воспользоваться простой проверкой. Тогда исходный код будет иметь следующий вид:
If MessageDlg('Закончить выполнение задачи?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
then
begin
MessageDlg('Выполнение задачи закончено.', mtInformation, [mbOk], 0);
Close;
end;
Создание сообщения с помощью дополнительного окна достаточно трудоемко. Этот способ используется для создания сложных запросов, когда одного только "Да" и "Нет" мало. Примером может служить ситуация, когда от пользователя необходимо получить код продолжения, в зависимости от которого приложение будет выполнять те или иные операции. Рассмотрением данного способа создания сообщений и использования дополнительных окон для вспомогательных задач мы займемся в следующей статье.
Станислав Лаптенок
Last@tut.by
(c) компьютерная газета
Начнем по порядку. Создавая очередную программу, пользователь компонует интерфейс, исходя из имеющихся у него подручных объектов, при этом он неизбежно сталкивается с необходимостью изменить то или иное его свойство. Как помнит наш читатель, свойства объектов на этапе разработки программы изменяются с использованием инспектора объектов. Этих свойств существует достаточно много. На них-то мы сейчас и остановимся.
Инспектор Объектов (рис. 1). В окне инспектора объектов имеются выпадающее меню и две вкладки. Выпадающее меню показывает нам, конфигурация какого объекта нам в настоящий момент представлена, а вкладки, собственно, эту конфигурацию помогают нам созерцать и изменять. Во вкладке Свойства ( Properties ) указано не что иное, как свойства формы проекта:). Рассмотрим некоторые основные свойства поподробнее:
Action — назначает для объекта действие;
ActiveControl — указывает на элемент формы, который имеет фокус;
Align — устанавливает положение объекта:
— AlNone — положение объекта определяется вручную пользователем;
— AlBottom ( AlTop ) — объект расположен внизу формы (если речь идет о форме проекта, то — внизу экрана). При этом высота объекта остается неизменной, а его ширина увеличивается до ширины формы (экрана);
— AlLeft ( AlRight ) — объект расположен в левой части формы (если речь идет о форме проекта, то — в левой части экрана). При этом ширина объекта остается неизменной, а его высота увеличивается до высоты формы (экрана);
— AlClient — объект занимает всю предоставленную площадь. Например, при установке данного свойства форме проекта, при запуске программы, окно будет растянуто на весь экран;
BiDiMode — это свойство используется для локализации приложения. Оно позволяет установить направление чтения текста в программе;
BorderStyle — свойство, отвечающее за тип формы. Включает в себя:
— bsNone — на форме полностью отсутствуют все системные элементы управления. Форма выглядит как прямоугольник без бортов и заголовка. При выполнении программы размер формы изменить нельзя;
— bsSingle — стандартное окно, но при этом отсутствует возможность изменения размеров формы. Набор системных кнопок зависит от свойства BorderIcon;
— bsDialog — стандартное диалоговое окно;
— bsToolWindow — панель инструментов. Похожа на стиль bsSingle, но при этом все системные элементы уменьшены;
— bsSizeToolWin — панель инструментов. Похожа на стиль bsSingle, но при этом все системные элементы уменьшены, возможно изменение размеров формы;
BorderIcons — группа свойств, отвечающих за видимость системных элементов — кнопок: свернуть, закрыть, развернуть, помощь и системное меню;
Caption — содержит текст названия формы проекта;
CurrentHelpFile — содержит имя файла контекстной помощи, используемого приложением;
HelpFile — задает имя файла помощи для приложения;
ShowHint — включает либо отключает показ всплывающих ярлыков подсказок;
Hint — содержит строку ярлыка подсказки;
Icon — указывает на значок приложения;
Cursor — устанавливает тип курсора, который будет установлен при наведении мыши на область объекта;
Visible — устанавливает такое свойство объекта, как видимость;
Enabled — указывает на состояние объекта. При значении False объект недоступен;
Font — группа свойств, характеризующих отображение текста, используемого объектом. С помощью этих свойств можно изменять цвет, размер, стиль, кодировку и шрифт текста;
Height — устанавливает высоту объекта в пикселях;
Width — устанавливает ширину объекта в пикселях;
Left — устанавливает отступ левого края объекта от левого края формы проекта в пикселях;
Top — устанавливает отступ верхнего края объекта от верхнего края формы проекта в пикселях;
Name — внутреннее имя объекта программы;
TabOrder — указывает направление перемещения фокуса при нажатии клавиши Tab (от начала к концу или от конца к началу, но при этом хочу заметить, что порядок перемещения фокуса можно изменять с помощью диалога TabOrder (Edit/TabOrder...);
TabStop — при установленном значении False фокус при нажатии клавиши Tab на данный объект не переводится (при этом фокус переходит к объекту, стоящему следующим в списке TabOrder).
Выше описаны свойства, которые присущи многим компонентам. Однако стоит отметить, что, помимо вышеупомянутых параметров, компоненты имеют и специфические свойства. Их мы будем рассматривать по мере изучения материала.
Во второй вкладке Действия ( Events ) указаны методы-обработчики событий. Познакомимся с ними поближе:
OnActivate — вызывается при передаче фокуса форме проекта;
OnDeactivate — вызывается при потере фокуса формой проекта;
OnClose — вызывается при закрытии формы. Предназначен для выполнения операций, позволяющих пользователю принять решение о закрытии формы либо продолжении работы;
OnCreate — вызывается при создании формы;
OnDestroy — вызывается при уничтожении формы;
OnHide — вызывается при исчезновении формы с экрана;
OnPaint — вызывается при перерисовке формы;
OnShow — вызывается при появлении формы на экране;
OnClick — вызывается при нажатии на объект;
OnMouseDown — вызывается при нажатии кнопки мыши.
К сведению: для создания обработчика событий достаточно дважды нажать мышкой на пустое поле, соответствующее названию метода.
Окно редактора кода. Как наш любознательный читатель мог уже заметить, окно редактора кода представлено тремя частями:
— панель модулей описания переменных и используемых модулей;
— панель кода программы;
— панель найденных ошибок программы (на этапе создания программы данное окно является невидимым, активизируется, если это необходимо, при компиляции программы).
Думаю, на этом с интерфейсом можно остановиться и перейти к конкретным проблемам программирования. Начать я бы хотел с раздела Delphi, который обратил на себя внимание через наших читателей. Итак, диалоги . Казалось бы, достаточно простой раздел. Однако меня с десяток человек спросили, каким образом можно произвести операции над файлом, который должен выбрать пользователь. Какие только варианты решения мне ни приходилось читать: и создавали дополнительную форму объекта, и пытались заставить пользователя от руки написать адрес файла, и предлагали воспользоваться компонентами Treeview, OutLine и им подобным. При этом читатели сами понимали, что они делают лишнюю работу и что существует более короткий и простой путь для решения проблемы. Как оказывается, внутреннее чувство наших читателей их не повело. Достаточно было воспользоваться компонентом OpenDialog (страница Dialogs). Данный компонент легко устанавливается на форму проекта в виде квадрата. При запуске программы он невидим. Квадрат лишь указывает нам на то, что компонент установлен и помогает нам обращаться к его свойствам при помощи инспектора объектов. Рассмотрим их поподробнее.
Итак, после установки компонента на форму проекта диалоговое окно можно активизировать с помощью функции Execute:Boolean. При этом, если пользователь выбрал файл или несколько файлов и нажал кнопку ОК, то функция возвращает True. Свойство компонента FileName содержит имя последнего файла из списка выбранных в диалоге. Свойство Files — список всех файлов, выбранных в диалоге. Свойство InitialDir задает каталог, к которому диалог обращается при открытии. Свойство Title содержит заголовок диалогового окна. Следует также отметить свойство Filter. С его помощью при выборе и сохранении файлов удобно осуществлять отбор файлов только с заданными расширениями. Например, для создания фильтра для исполняемых файлов свойство должно содержать следующую строку:
'Исполняемые файлы | *.EXE'
В одном фильтре можно отбирать файлы и с различными расширениями:
'Графические изображения | *.JPG; *.GIF; *.PNG'
Фильтр также можно создать в простом редакторе, который связан со свойством Filter в инспекторе объектов.
Очень интересные свойства и при этом одни из самых важных для диалоговых компонентов (OpenDialog, SaveDialog, OpenPictureDialog, SavePictureDialog) представлены в группе Options. Они рассмотрены в следующей таблице:
OfReadOnly | Устанавливает значение флажка Open As Read Only (открыть только для чтения) |
ofOvewWritePrompt | Диалог выводит предупреждение, если выбирается уже используемый файл |
OfHideReadOnly | Устанавливает видимость флажка Open As Read Only (открыть только для чтения) |
OfNoChangeDir | После выбора файла и закрытия диалога устанавливается каталог, который был задан в диалоге до открытия |
OfShowHelp | Добавляет к диалогу кнопку помощи |
OfNoValidate | Отключает проверку имени файла |
OfAllowMultiSelect | Позволяет выбирать в диалоге несколько файлов |
OfExtensionDifferent | Устанавливается в True во время выполнения приложения, если расширение выбранного файла отличается от расширения по умолчанию |
OfCreatePrompt | Генерирует предупреждение в случае выбора несуществующего файла и предлагает создать его |
OfShareAware | Позволяет выбирать файлы, которые используются другими процессами |
OfNoReadOnlyReturn | Генерирует сообщение, если был выбран файл с атрибутом "только для чтения" |
OfNoTestFileCreate | Отключает проверку на существование выбранного файла и доступность сетевого диска |
OfNoNetworkButton | Удаляет из диалогового окна кнопку Network доступа к сетевым дискам |
OfNoLongNames | Диалог не отображает файлы с длинными именами |
OfOldStyleDialog | Представляет диалог в стиле windows 3.1x |
OfNoDereferenceLinks | Не различает файлы и ссылки на файлы (расширение LNK) |
OfEnableSizing | Позволяет изменять размеры диалога |
Как и у многих других компонентов, у диалогов тоже существуют и свои методы-обработчики событий. Среди них наиболее интересными являются OnClose, OnFolderChange, OnSelectionChange, OnTypeChange (думаю, в пояснениях эти методы не нуждаются).
Исходя из всего вышесказанного, опишем процедуру (дабы увидеть все на конкретном примере), которая будет вызываться при нажатии на кнопку Button1, выполняющую запуск диалога OpenDialog1 и передающую путь к выбранному файлу в поле ввода Edit1:
procedure TForm1.Button1Click(Sender: TObject);
begin
opendialog1.execute; {запуск диалога с помощью функции execute}
{во время активации диалога выполнение процедуры приостанавливается}
edit1.text:=opendialog1.filename; {присваивание полю ввода Edit1 пути к файлу}
end;
На этом раздел диалогов работы с файлами заканчивается. Всего вышеописанного вполне достаточно для создания полноценных приложений. Мной были специально опущены некоторые моменты, о которых я не счел нужным писать. Они редко используются в программировании, однако расширяют возможности работы с программой. При огромном вашем желании я могу написать о них персонально. Заявки — на e-mail:).
Следующей остановкой я выбрал сообщения . Согласитесь, сообщения играют далеко не последнюю роль в работе программы. С помощью сообщений программист может извещать об ошибках пользователя при задании исходных данных для работы программы, система сообщает о некорректной работе приложений, благодаря сообщениям программные продукты доводят до нашего сведения информацию о своей версии, о разработчиках и фирме-производителе, наконец, планировщики сообщают пользователю о запланированных встречах, событиях. Реализовать сообщения можно несколькими способами: с помощью процедуры ShowMessage, функции MessageDlg, создания дополнительного окна.
Процедура showmessage позволяет вывести пользователю простое сообщение. При этом появится дополнительное окно с названием проекта и кнопкой ОК. Выглядит все это следующим образом:
Синтаксис:
ShowMessage(Msg: string);
Пример:
ShowMessage('Все задачи выполнены успешно');
Функция messageDlg позволяет создавать сложные диалоговые запросы с использованием обратной связи. Имеет вид дополнительного окна, дополненного изображением. При этом возможно использовать диалоговые запросы. Название окна зависит от типа запроса.
Синтаксис:
MessageDlg(Msg: string; AType: TMsgDlgType; AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
Msg — строковой параметр. Задает выводимое сообщение;
Atype — внутренний параметр функции. Задает тип сообщения:
— mtWarning — сообщение о предупреждении;
— mtError — сообщение об ошибке;
— mtInformation — информационное сообщение;
— mtConfirmation — сообщение о подтверждении;
— mtCustom — сообщение не содержит в углу изображения. Название окна соответствует названию исполняемого файла (аналогично showmessage).
Abuttons — задает имена кнопок, которые будут отображаться на диалоговом запросе. Возможны значения: mbYes, mbNo, mbOK, mbCancel, mbHelp, mbAbort, mbRetry, mbIgnore, mbAll.
HelpCtx — содержит номер раздела, который будет показан пользователю, если он вызовет справку, когда диалог активизирован.
Пример:
MessageDlg('Продолжить выполнение программы', mtConfirmation, [mbYes, mbNo], 0);
Для того чтобы определить, какой вариант ответа выбрал пользователь, можно воспользоваться простой проверкой. Тогда исходный код будет иметь следующий вид:
If MessageDlg('Закончить выполнение задачи?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
then
begin
MessageDlg('Выполнение задачи закончено.', mtInformation, [mbOk], 0);
Close;
end;
Создание сообщения с помощью дополнительного окна достаточно трудоемко. Этот способ используется для создания сложных запросов, когда одного только "Да" и "Нет" мало. Примером может служить ситуация, когда от пользователя необходимо получить код продолжения, в зависимости от которого приложение будет выполнять те или иные операции. Рассмотрением данного способа создания сообщений и использования дополнительных окон для вспомогательных задач мы займемся в следующей статье.
Станислав Лаптенок
Last@tut.by
(c) компьютерная газета
Компьютерная газета. Статья была опубликована в номере 48 за 2000 год в рубрике программирование :: delphi