1 Министерство образования и науки Челябинской области государственное бюджетное образовательное учреждение

advertisement
1
Министерство образования и науки Челябинской области
государственное бюджетное образовательное учреждение
среднего профессионального образования
(среднее специальное учебное заведение)
«Южно-Уральский многопрофильный колледж»
Методические указания
для выполнения практических работ
по МДК 01. 02 Разработка прикладного программного обеспечения
для студентов специальности 230115 Программирование в
компьютерных системах.
2014
2
Одобрена
Составлена в соответствии с
цикловой комиссией
Федеральным государственными
Председатель комиссии
требованиями
_____________Л.В.Сухорослова
подготовки
к
уровню
выпускника
по
специальности:230115
Программирование
в
компьютерных системах.
Заместитель
директора
по
инновациям и информатизации
___________И.Н. Тихонова
Автор:
Воропанова
И.О.
преподаватель
Уральского
–
Южно-
государственного
колледжа
Рецензент:
Кулиненко И.М. – методист
Южно-Уральского
многопрофильного колледжа
Редактор:
3
Содержание
Введение ............................................................................................................... 7
Урок 1. Основные принципы ООП. Классы и обекты. ................................... 8
Урок 2. Иерархия базовых классов ................................................................. 21
Урок 3. Базовые классы элементов управления............................................. 28
Урок 4. Свойства компонентов. События мыши и клавиатуры ................... 38
Урок 5. Обработка событий. Динамическое изменение свойств ................. 48
Урок 6. Компоненты ввода-вывода и редактирования. ................................ 50
Урок 7. Компоненты для работы со списками ............................................... 62
Урок 8 Работа с таблицами .............................................................................. 70
Урок 9. Кнопочные компоненты, переключатели ......................................... 81
Урок 10. Работа с кнопками и переключателями .......................................... 89
Урок 11. Контейнеры ........................................................................................ 94
Урок 12. Инструментальные панели ............................................................. 102
Урок 13 Формы ................................................................................................ 109
Урок 14. Невизуальные компоненты ............................................................ 120
Урок 15. Главное и контекстное меню ......................................................... 130
Урок 16. Класс Exception. Стандартные классы исключений.
Операторы обработки исключений. ............................................................. 141
Урок 17 Отображение графики на канве Canvas ......................................... 153
Урок 18 Полоса состояния StatusBar ............................................................. 167
4
Урок 19 Горячие клавиши-HotKey ................................................................ 176
Урок 20 Воспроизведение немых видео клипов — компонент Animate ... 184
Литература ...................................................................................................... 190
5
Аннотация
Методические указания предназначены для студентов специальности
230115 «Программирование в компьютерных системах» при выполнении
практических работ по МДК 01. 02. Разработка прикладного программного
обеспечения
Целью выполнения данных практических работ является:
-закрепление теоретических знаний по объектно-ориентированному
программированию;
- развитие и закрепление студентами навыков программирования в
среде Delphi;
-получение навыков работы для конструирования пользовательского
интерфейса в Delphi;
-закрепление навыков работы с офисными программами;
-закрепление
навыков
работы
с
методической
и
справочной
литературой.
Перед выполнения работ студент отвечает на вопросы для контроля.
Защищает каждую практическую работу.
При оценке знаний студента необходимо учитывать
качество
выполнения студентом заданий и ответов на вопросы для контроля. Для
этого введены следующие критерии оценки:
Объем выполненного задания
Оценка
Полное выполнение работы с полными Отлично
ответами
на
все
теоретические
и
практические вопросы (90%-100%)
Выполнение работы с полными ответами Хорошо
на вопросы
и частичное выполнение
6
практических работ (80%-90%)
Выполнение работы без ответов на Удовлетворительно
вопросы (70%-80%)
Частичное выполнение работы (ниже Неудовлетворительно
70%)
7
Введение
Учебно-методическое пособие представляет собой комплексный набор
заданий по освоению МДК Прикладное программирование. Задания
предусмотрены для работы в интегрированной среде Delphi.
Пособие рассчитано на 90 часов.
Для проверки качества выполнения работы необходимо создать папку
Прикладное программирование, в которой для каждого урока создаётся
папка с названием урока.
В пособии предусмотрены два вида заданий:
-теоритеческие вопросы, ответы на которые неоходимо найти в
пособии и сохранить в текстором файле.
-практические задания, выполняются в интегрированной среде
Delphi. Проекты сохраняются в папке соответструющей уроку, а скрин-шоты
программного кода и результат выполнения программы необходимо
сохранить в текстовый файл, созданный для ответов на вопросы по данному
уроку.
Желаем успеха в работе.
8
Урок 1. Принципы ООП. Классы и объекты.
ПРИРОДА ОБЪЕКТА
Об объектах можно думать как о существах, которые «живут» в вашей
программе и коллективно решают некоторую прикладную задачу. Вы
создаете
этих
существ,
распределяете
между
ними
обязанности
и
устанавливаете правила их взаимодействия.
В общем случае каждый объект «помнит» необходимую информацию,
«умеет» выполнять некоторый набор действий и характеризуется набором
свойств.
То, что объект «помнит», хранится в его полях. То, что объект «умеет
делать», реализуется в виде его внутренних процедур и функций,
называемых методами. Свойства объектов аналогичны свойствам, которые
мы
наблюдаем
у
обычных
предметов.
Значения
свойств
можно
устанавливать и читать. Программно свойства реализуются через поля и
методы.
Пример:
Объект «кнопка» имеет свойство «цвет». Значение цвета кнопка
запоминает в одном из своих полей. При изменении значения свойства
«цвет» вызывается метод, который перерисовывает кнопку.
Этот пример позволяет сделать важный вывод: свойства имеют
первостепенное значение для программиста, использующего объект. Чтобы
понять суть и назначение объекта, вы обязательно должны знать его
свойства, иногда — методы, очень редко — поля (объект и сам знает, что с
ними делать).
ОБЪЕКТЫ И КОМПОНЕНТЫ
Компоненты в Delphi — это особые объекты, которые являются
строительными кирпичиками среды визуальной разработки и приспособлены
к визуальной установке свойств. Чтобы превратить объект в компонент,
9
первый разрабатывается по определенным правилам, а затем помещается в
Палитру Компонентов. Конструируя приложение, вы берете компоненты из
Палитры Компонентов, располагаете на форме и устанавливаете их свойства
в окне Инспектора Объектов. Внешне все выглядит просто, но чтобы достичь
такой простоты, потребовалось создать механизмы, обеспечивающие
функционирование объектов-компонентов уже на этапе проектирования
приложения! Все это было придумано и блестяще реализовано в среде
Delphi. Таким образом, компонентный подход значительно упростил
создание приложений с графическим пользовательским интерфейсом и дал
толчок развитию новой индустрии компонентов.
КЛАССЫ ОБЪЕКТОВ
Каждый объект всегда принадлежит некоторому классу. Класс — это
обобщенное (абстрактное) описание множества однотипных объектов.
Объекты являются конкретными представителями своего класса, их принято
называть экземплярами класса. Например, класс СОБАКИ — понятие
абстрактное, а экземпляр этого класса МОЙ ПЕС БОБИК — понятие
конкретное.
ТРИ КИТА ООП
Весь мир ООП держится на трех китах: инкапсуляции, наследовании и
полиморфизме.
Инкапсуляция. Наблюдаемое в объектах объединение данных и
операций в одно целое было обозначено термином инкапсуляция.
Применение инкапсуляции сделало объекты похожими на маленькие
программные модули и обеспечило сокрытие их внутреннего устройства. Для
объектов появилось понятие интерфейса, что значительно повысило их
надежность и целостность.
Наследование. Этот простой принцип означает, что если вы хотите
создать новый класс, лишь немногим отличающийся от того, что уже
существует, то нет необходимости в переписывании заново всех полей,
10
методов и свойств. Вы объявляете, что новый класс является потомком (или
дочерним
классом)
имеющегося
класса,
называемого
предком
(или
родительским классом), и добавляете к нему новые поля, методы и свойства.
Иными словами добавляется то, что нужно для перехода от общего к
частному. Процесс порождения новых классов на основе других классов
называется наследованием. Новые классы имеют как унаследованные
признаки, так и, возможно, новые. Например, класс СОБАКИ унаследовал
многие свойства своих предков — ВОЛКОВ.
Полиморфизм. Означает, что в производных классах вы можете изменять
работу уже существующих в базовом классе методов. При этом весь
программный код, управляющий объектами родительского класса, пригоден
для управления объектами дочернего класса без всякой модификации.
Например, вы можете породить новый класс кнопок с рельефной надписью,
переопределив метод отрисовки кнопки. Новую кнопку можно «подсунуть»
вместо стандартной в какую-нибудь подпрограмму, вызывающую отрисовку
кнопки. При этом подпрограмма «думает», что работает со стандартной
кнопкой, но на самом деле кнопка принадлежит производному классу и
отображается в новом стиле.
КЛАССЫ
Для поддержки ООП в язык Object Pascal введены объектные типы
данных, с помощью которых одновременно описываются данные и операции
над ними. Объектные типы называют классами, а их экземпляры —
объектами.
Классы объектов определяются в секции type глобального блока.
Описание класса начинается словом class и заканчивается словом end. По
форме объявления классы похожи на обычные записи, но помимо полей
данных могут содержать объявления пользовательских процедур и функций.
Такие процедуры и функции обобщенно называют методами, они
предназначены для выполнения над объектами различных операций.
11
Пример объявления класса:
type
{измеритель дискового пространства}
TDiskGauge = class
DriveLetter:
{буква
Char;
PercentCritical:
дискового
{критический
Integer;
накопителя}
процент
свободного
пространства}
function GetPercentFree: Integer;
procedure CheckStatus;
end;
Заголовки методов, следующие за списком полей, играют роль
предварительных
(forward)
объявлений.
Программный
код
методов
помещается ниже определения класса и будет приведен позже.
Класс обычно описывает сущность, моделируемую в программе.
Например, класс TDiskGauge описывает измеритель дискового ресурса.
Класс содержит два поля: DriveLetter — буква находящегося под
наблюдением
накопителя,
и
PercentCritical
—
процент
свободного
пространства на диске, с которым работает программа. Когда объем
свободных ресурсов снижается до этого порога, пользователю выдается
звуковое предупреждение. Функция GetPercentFree определена как метод
работы над любым объектом класса TDiskGauge и возвращает процент
свободного пространства на диске. Процедура CheckStatus служит для
проверки состояния ресурса и выдачи звукового предупреждения.
Обратите внимание, что приведенное выше описание является не чем
иным, как декларацией интерфейса для управления объектами класса
TDiskGauge. Реализация методов GetPercentFree и CheckStatus отсутствует,
но для создания и использования экземпляров класса она пока и не нужна. В
этом как раз и состоит сила инкапсуляции, Которая делает объекты
аналогичными
программным
модулям.
Для
использования
модуля
необходимо изучить лишь его интерфейсную часть, раздел реализации для
12
этого изучать не требуется. Поэтому дальше от описания класса мы перейдем
не к реализации методов, а к созданию на их основе объектов.
ОБЪЕКТЫ
Чтобы от описания класса перейти к объекту, следует выполнить
соответствующее объявление в секции var:
var DiskGauge: TDiskGauge;
При работе с обычными типами данных этого объявления было бы
достаточно для получения экземпляра типа. Однако объекты в Delphi
являются динамическими данными, т.е. распределяются в «куче» (heap).
Поэтому переменная DiskGauge — это просто ссылка на экземпляр объекта,
которого физически еще не существует. Чтобы сконструировать объект
класса TDiskGauge и связать с ним переменную DiskGauge, нужно в тексте
программы поместить следующий оператор (statement):
DiskGauge: = TDiskGauge.Create;
Create —
это
так
называемый
конструктор
объекта;
он
всегда
присутствует в классе и служит для создания и инициализации экземпляров.
К сведению профессионалов заметим, что в памяти выделяется место только
для полей объекта. Методы, так же как и обычные процедуры и функции,
помещаются в область кода программы; они умеют работать с любыми
экземплярами своего класса и в памяти никогда не дублируются,
Использование объекта
После создания объект можно использовать в программе — читать и
устанавливать его поля, вызывать методы. Доступ к полям и методам объекта
происходит с помощью уточненных имен, например:
DiskGauge.DriveLetter: = 'С';
DiskGauge. PercentCritical: = 10;
DiskGauge.CheckStatus;
Допустимо использование оператора with, например:
13
with DiskGauge do
begin
DriveLetter: = 'С';
PercentCritical: = 10;
CheckStatus;
end;
Если наступает время, когда объект становится не нужен, в программе, он
должен быть удален вызовом специального метода Destroy, например:
DiskGauge.Destroy;
Destroy — это так называемый деструктор объекта; он присутствует в
классе наряду с конструктором и служит для удаления объекта из
динамической памяти. После вызова деструктора переменная DiskGauge
становится несвязанной и не должна использоваться для доступа к полям и
методам уже несуществующего объекта. Чтобы отличать в программе
связанные объектные переменные от несвязанных, последние следует
инициализировать значением nil. Например, в следующем фрагменте
обращение к деструктору Destroy выполняется только в том случае, если
объект реально существует.
DiskGauge: = nil;
if DiskGauge <> nil then DiskGauge.Destroy;
Вызов деструктора для несуществующих объектов недопустим и при
выполнении программы приведет к ошибке. Чтобы избавить программистов
от лишних ошибок, в объекты ввели предопределенный метод Free, который
следует вызывать вместо деструктора. Метод Free сам вызывает деструктор
Destroy, но только в том случае, если значение объектной переменной не
равно nil. Поэтому последнюю строчку в приведенном выше примере можно
переписать следующим образом:
DiskGauge.Free;
14
Значение одной объектной переменной можно присвоить другой. При
этом объект не копируется в памяти, а вторая переменная просто связывается
с тем же объектом, что и первая:
Var DiskGauge1, DiskGauge2: TDiskGauge;
begin
{Переменные DiskGauge1
и DiskGauge2 не связаны с объектом}
DiskGauge1:=TDiskGauge.Create;{ DiskGauge1 связана с объектом, а
DiskGauge2 — нет}
DiskGauge2: = DiskGauge1; {Обе переменные связаны с одним объектом}
DiskGauge2.Free; {Объект удален, переменные DiskGauge1 и DiskGauge2 с
ним не связаны}
end;
Задание: Ответьте на вопросы.
1) Что такое класс?
2) Что такое объект?
3) Для чего нужны поля в объекте?
4) Что представляют собой методы объекта
5) Что называют экземплятом класса?
6) Опишите класс СОБАКИ.
7) Перечислите три основных принципа ООП.
8) Описать каждый из принципов ООП.
9) Как описывается класс?
10) Что называют конструктором и деструктором объекта?
11) Как объявляется объект?
12) Как работать с объектом, пример.
15
Задание 1. В момент создания формы должна динамически
создаваться кнопка в левом верхнем углу формы. При нажатии на кнопку
должно выдаваться сообщение «Проверка».
Ход решения:
1. Создайте новое приложение
2. Щелкните дважды по форме. Откроется заготовка события onCreate
для формы. В тело процедуры внесите следующий код:
MyButton:=TButton.Create(Form1);//Создаем
новую
кнопку
MyButton.Parent:=Form1;//Устанавливаем расположение новой кнопки
MyButton.Top:=5;
MyButton.Left:=10;
MyButton.Width:=100;
MyButton.Height:=25;
MyButton.Caption:='Новая кнопка';
MyButton.OnClick:=MyAction;
3. Опишите в разделе Var переменную (объект)
MyButton: TButton;
4. Добавьте процедуру MyAction.
procedure TForm1.MyAction(Sender: TObject);
begin
ShowMessage('Проверка');
end;
5. В разделе private класса формы внесите объявление этой процедуры.
…
{ Private declarations }
16
procedure MyAction(Sender:TObject);
public
…
Запустите программу. На форме появится кнопка, при нажатии на
которую выдастся сообщение «Проверка».
Задание 2. Добавить в программу из задания 1 динамическое
создание компонента Edit рядом с кнопкой.
Задание 3. При нажатии на кнопку "Создать объект" программа
должна будет создать круг со случайными параметрами (размер, цвет) и
поместить его в произвольном месте панели. При нажатии на кнопку
"Удалить объект" программа должна выполнить два действия:
1.удалить изображение объекта с экрана
2.освободить память, выделенную объекту конструктором.
Ход работы
Начните новый проект в Delphi и сохраните его в отдельной папке под
названием “Figures”. Разместите на форме компоненты, показанные на
рисунке.
17
Созданные объекты будем хранить в списке TList, т.к. мы не знаем
заранее,
сколько
объектов
создадим
(это
массив, размер
которого
увеличивается в процессе заполнения). В его свойстве Items хранятся
указатели типа Pointer, поэтому элементами списка могут быть объекты
любого типа.
Вставьте в модуль объявление переменной List типа TList:
Var
Form1: TForm1;
List : TList;
Implementation
{$R *.DFM}
Поскольку список является классом Delphi, то его (список) тоже
необходимо создать по общим правилам. Для этого дважды щелкните по
пустому месту формы, таким образом вы создадите обработчик события
onCreate для формы. Добавьте в него строку, выделенную жирным
шрифтом:
procedure TForm1.FormCreate(Sender: TObject);
begin
List:=TList.Create;
end;
Количество элементов в списке фиксируется в свойстве Count.
Добавление нового объекта в список вне зависимости от его типа
производится методом Add (при этом Count увеличивается на единицу),
удаление – методом Delete(при этом Count уменьшается на единицу).
Однако нужно помнить, что элементами списка являются указатели,
следовательно, удаление указателя из списка не удаляет сам объект из
памяти. Поэтому при закрытии формы, прежде чем удалить список, следует
освободить память, занятую созданными объектами.
Щелкните дважды по кнопке Button1 («Создать объект») и добавьте в
созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:
18
procedure TForm1.Button1Click(Sender: TObject);
var AObj : TShape; delta : word;
begin
AObj:=TShape.Create(Panel1); // Создаем объект AObj типа TShape на
панели Panel1
AObj.Parent:=Panel1; // Указываем ссылку на объект-владелец (место
«рождения»)
AObj.Shape:=stCircle // форма фигуры – круг ;
delta:=10+random(50); // диаметр круга - случайное число от 10 до 60
AObj.Width:=delta;
AObj.Height:=delta;
// "разыгрываем" место круга внутри панели
AObj.Left:=random(Panel1.Width-AObj.Width);
AObj.Top:=random(Panel1.Height-AObj.Height);
// задаем цвет круга
AObj.Brush.Color:=RGB(random(256),random(256),random(256));
// добавляем созданную фигуру в список
List.Add(AObj);
end;
Задание 4. Продолжение проекта «Фигуры»
Щелкните дважды по кнопке Button2 («Удалить объект») и добавьте в
созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:
procedure TForm1.Button2Click(Sender: TObject);
var Temp: TShape;
begin
19
with List do
if Count>0 then begin
Temp:=Items[Count-1]; // В Temp – ссылка на последний созданный
объект
Temp.Free;
Delete(Count-1);
end;
end;
Щелкните дважды по кнопке Button3 («Удалить все») и добавьте в
созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:
procedure TForm1.Button3Click(Sender: TObject);
var Temp: TShape;
begin
with List do
while Count>0 do begin
Temp:=Items[Count-1];
Temp.Free;
Delete(Count-1);
end;
end;
Щелкните по пустому месту формы, перейдите на вкладку Events
инспектора, щелкните дважды по полю ввода события OnCloseи добавьте в
созданный Delphi шаблон строки, отмеченные ниже жирным шрифтом:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Button3.Click; //
запускаем
процедуру
удаления
объектов
List.Free; //удаляем список указателей
end;
И, наконец, поскольку фигуры на панели будут возникать случайным
образом, необходимо будет вызвать один раз в программе процедуру
20
Randomize, которая подготавливает к работе датчик случайных чисел.
Можно сделать это в событии OnCreate формы, но мы для разнообразия
используем секцию initialization нашего модуля. Для этого поместим в
самый конец модуля перед end с точкой следующие строки:
…………………..
initialization
randomize;
end.
На рисунке приведен примерный вид окна программы после запуска.
Задание 5. Переделать программу так, чтобы кроме кругов на панели
появлялись фигуры и другой формы.
21
Урок 2. Иерархия базовых классов
Все классы библиотеки визуальных компонентов произошли от группы
базовых классов, которые лежат в основе иерархии VCL. Самый общий
предок компонентов — это класс TObject, инкапсулирующий простейший
объект. Как известно, каждый объект наследует свойства и методы
родительского класса. К объекту можно добавить новые свойства и методы,
но нельзя удалить унаследованные. Объект-наследник в свою очередь может
стать родительским для нового класса, который унаследует возможности
всех своих предков.
Иерархия базовых классов
В основе всего многообразия классов и компонентов, используемых в
Delphi, лежат всего лишь пять базовых классов. Они обеспечивают
выполнение основных функций любого объекта — будь это стандартный
компонент VCL или специализированный объект, выполняющий некоторые
операции в приложении.
Благодаря механизму наследования свойств и методов, потомки базовых
классов умеют "общаться" друг с другом; работают в среде разработки,
22
взаимодействуя
с Палитрой
компонентов и
Инспектором объектов;
распознаются операционной системой как элементы управления и окна.
Класс TObject
Класс TObject является родоначальником всей иерархии использующихся
в Delphi классов VCL. Он реализует функции, которые обязательно будет
выполнять любой объект, который может быть создан в среде разработки.
В первую очередь — это создание экземпляра объекта и его уничтожение.
Любой объект выполняет эти две операции в обязательном порядке. Обычно
разработчик даже не задумывается о том, как объект будет создан и что
необходимо сделать для его корректного уничтожения. Компоненты VCL
создаются и освобождают занимаемые ресурсы автоматически.
Кроме
этого,
класс
TObject
обеспечивает
создание
и
хранение
информации об экземпляре объекта и обслуживание очереди сообщений.
Каждый объект должен содержать некоторую информацию о себе,
которая используется приложением и средой разработки. Поэтому класс
TObject содержит ряд методов, обеспечивающих представление этой
информации в потомках.
Метод
class function Classlnfo: Pointer;
возвращает указатель на таблицу информации времени выполнения
(RTTI). Эта информация используется в среде разработки и в приложении.
Функция
class function ClassName: ShortString;
возвращает имя типа объекта, которое может быть использовано для
идентификации.
Метод
class function ClassNameIs(const Name: string): Boolean;
позволяет определить, является ли данный объект того типа, имя которого
передано в параметре Name. В случае положительного ответа функция
возвращает True.
23
Как известно, программирование для Windows основано на событиях.
Каждое приложение и каждый программный объект должны уметь
реагировать на сообщение о событиях и, в свою очередь, рассылать
сообщения. В выполнении этих операций заключается третья общая для всех
объектов функция.
Метод procedure Dispatch(var Message); virtual; осуществляет обработку
сообщений, поступающих объекту. Он определяет, сможет ли объект
обработать сообщение при помощи собственных обработчиков событий. В
случае отсутствия таких методов сообщение передается аналогичному
методу Dispatch класса-предка (если он есть). Класс TObject имеет
предопределенный
обработчик
событий:
procedurе
DefaultHandler(var
Message); virtual;
Класс TObject имеет еще несколько методов, которые в основном
применяются для взаимодействия объекта со средой разработки. В целом
класс TObject может служить для создания на его основе некоторых простых
классов для использования в приложениях.
Класс TPersistent происходит непосредственно от класса TObject. Он
обеспечивает своих потомков возможностью взаимодействовать с другими
объектами и процессами на уровне данных. Его методы позволяют
передавать данные в потоки, а также обеспечивают взаимодействие объекта с
Инспектором объектов. "Persistent" в переводе с английского означает
"устойчивый", "постоянный". Что же такого постоянного в одноименном
классе? Ответ таков: виртуальный метод procedure Assign (Source:
TPersistent);
Этот важнейший метод осуществляет копирование содержимого одного
объекта (source) в другой (self, т.е. в объект, вызвавший метод Assign). При
этом объект-получатель остается самим собой, чего нельзя достигнуть,
используя простое присваивание переменных объектного типа:
FirstObject:= SecondObject;
24
Ведь в этом случае указатель на одну область адресного пространства,
содержащую экземпляр класса (объект), замещается указателем на другую
область адресного пространства, содержащую другой объект. Метод Assign
позволяет продублировать объект — присвоить одному объекту значения
всех свойств другого. При этом объекты не обязательно должны быть одного
и того же класса; более того, они не обязательно должны находиться в
отношениях "родитель-потомок".
Класс
TPersistent
никогда
не
используется
напрямую,
от
него
порождаются потомки, которые должны уметь передавать другим объектам
значения своих свойств, но не являться при этом компонентами.
Класс TComponent
Класс TComponent является предком всех компонентов VCL. Он
используется в качестве основы для создания невизуальных компонентов и
реализует основные механизмы, которые обеспечивают функционирование
любого компонента. Механизмы, реализованные в классе TComponent,
обеспечивают взаимодействие компонента со средой разработки, главным
образом с Палитрой компонентов и Инспектором объектов. Благодаря
возможностям этого класса, компоненты начинают работать на форме
проекта уже на этапе разработки. В нем появляются первые свойства,
которые отображаются в Инспекторе объектов.
Свойство (метод)
Описание
свойство содержит имя экземпляра
property Name: TComponentName;
компонента, которое используется для
идентификации
приложении
компонента
в
25
является вспомогательным и не влияет
на работу компонента. В нем можно
хранить числовое значение, например
property Tag: Longint;
для более удобной идентификации
компонентов
Для компонентов существует своя иерархия, поэтому в классе введен
механизм учета и управления компонентами, для которых данный компонент
является владельцем. Свойства и методы, которые отвечают за управление,
приведены в таблице ниже.
Свойство (метод)
Описание
Содержит индексированный список
Property
Components
[Index: указателей
всех
компонентов,
для
которых данный компонент является
Integer]: TComponent ;
владельцем (owner)
Property
ComponentCount
Integer;
property Owner: TComponent;
property ComponentIndex: Integer;
Procedure
Указывается,
какой
компонент
является владельцем данного
Индекс данного компонента в списке
владельца
список
RemoveComponent Удаляет компонент AComponent из
(AComponent : TComponent);
Procedure
Число подчиненных компонентов
InsertComponent Вставляет компонент AComponent в
(AComponent: TComponent) ;
Procedure
:
списка
FindComponent Осуществляет поиск компонента по
(AName: string): TComponent;
имени AName
26
procedure DestroyComponents;
Предназначен для уничтожения всех
компонентов, подчиненных данному
Очень важное свойство property ComponentState: TComponentState; дает
представление о текущем состоянии
компонента. Состояние может
измениться в результате получения компонентом некоторого сообщения,
действий разработчика, выполнения акции и т. д. Это свойство активно
используется средой разработки.
Определение принадлежности к классу и приведение типов объектов
Оператор is
Чтобы определить ссылка на объект какого именно типа находится в той
или
иной
переменной,
используется
оператор
is,
проверяющий
принадлежность объекта к заданному классу. Оператор is возвращает
логическое значение (True или False) и используется в следующем виде:
<Ссылка на объект> is <Название класса>
Оператор as
Для указания компилятору о том, что объект следует рассматривать как
экземпляр какого-либо конкретного класса, предусмотрен оператор as,
используемый следующим образом:
<Ссылка на объект> as <Название класса>
В результате такого указания Delphi пытается обращаться к объекту, на
который указывает ссылка, как к экземпляру заданного класса.
Задание Ответьте на вопросы:
1) Зарисуйте структуру 5 базовых классов.
2) Какие функции реализует класс TObject?
3) Заполните таблицу: Методы класса TObject.
метод
Действие метода
…..
….
4) Опишите действие виртуального метода
27
5) procedure Assign (Source: TPersistent);
6) Для чего используют класс TComponent?
7) Для чего используют оператор is?
8) Для чего используют оператор as?
Задание 1: Все установленные на форме компоненты TCheckBox
установить в положение checked.
Ход решения:
Установите на форме несколько (5) компонентов CheckBox и кнопку. В
обработчик события нажатия кнопки добавьте следующий код:
Задание 2: Составить программу, которая будет при установке
флажка в компоненте CheckBox делать недоступными все кнопки формы.
28
Урок 3. Базовые классы элементов управления
Напомним, иерархия базовых классов имеет следующий вид:
Рисунок 1
Визуальные и невизуальные компоненты
Класс TComponent обеспечивает взаимодействие компонентов между
собой и с визуальным построителем, но не предоставляет каких-либо
возможностей
визуального
для
взаимодействия
отображения
компонентов
компонентов
на
с
экране.
пользователем
Таким
и
образом,
TComponent предназначен не для прямого использования в программе, а
исключительно для целей построения других компонентов на его основе с
помощью стандартных механизмов наследования классов.
Компоненты:
Невизуальные
компоненты
не
Визуальные
компоненты,
имеющие называемые
представления
Диалоговые
компоненты, которые не
также имеют
визуального
на элементами управления, представления, но могут его
29
экране,
и
не имеющие
визуальное приобретать
взаимодействующие с представление
пользователем
и временного взаимодействия
возможность
взаимодействия
для
с пользователем
с
пользователем
Невизуальные компоненты
Невизуальные компоненты наследуются напрямую от класса TComponent
и поддерживают все его возможности взаимодействия со средой разработки,
например, сохранение свойств и связей с событиями в файлы формы и их
восстановление при последующем открытии проекта.
Невизуальные компоненты не имеют представления на экране во время
выполнения программы, в процессе разработки отображаются на формах в
виде иконок, сопоставленных им в Палитре компонентов, и предназначены
для добавления в программу поддержки некоторой технологии. В качестве
примера можно привести наборы компонентов для работы с базами данных с
использованием механизмов доступа BDE или ADO, или набор компонентов,
обеспечивающих взаимодействие программных продуктов через сети.
Базовый класс визуальных компонентов - TControl
Группа визуальных компонентов (элементов управления) строится на
основе класса TControl, описывающим свойства, методы и события,
присущие всем элементам управления, такие как:

расположение на экране;

правила выравнивания относительно других элементов управления;

курсор мыши, отображаемый при наведении мыши на элемент
управления;
30

шрифт, используемый для вывода надписей на компоненте;

цвет фона;

подсказка, выводимая операционной системой при попадании элемента
управления в фокус.
Общие свойства визуальных компонентов
Местоположение и размер визуального компонента
Для определения местоположения и размеров визуального компонента
используются следующие свойства:
Рисунок 2
Значения свойств задаются в пикселах.
Система координат рабочей области: начало отсчета находится в левом
верхнем углу. Оси направлены вправо и вниз. Под рабочей областью
понимается та часть площади владельца (формы, панели), которая
предназначена для размещения дочерних элементов. Эти свойства можно
использовать как на этапе разработки, так и во время выполнения.
Выравнивание элемента управления
Для выравнивания компонента в рабочей области его владельца (обычно
это форма) применяется свойство Align.
31
Может принимать следующие значения: alNone, alTop, alBottom, alLeft,
alRight, alClient. При значении alNone выравнивание отсутствует. При
следующих
четырех
значениях
выравнивание
осуществляется
по
соответствующей стороне. Значение alclient приводит к тому, что элемент
управления изменяет свои размеры до размеров рабочей области владельца.
Свойство
Anchors
(«Якорь»)
обеспечивает
фиксацию
элемента
управления по сторонам владельца. Сложное свойство, которое содержит
следующие подсвойства
akTop – фиксация по верху,
akLeft – фиксация по левой стороне,
akRight – фиксация по правому краю,
akBottom – фиксация по нижнему краю.
Комбинируя якоря для сторон, можно добиться различных вариантов
поведения компонента при изменении размеров владельца. Если по
вертикали или горизонтали якорь не установлен вообще, то при изменении
размеров владельца компонент остается на том же месте с учетом
изменившегося размера.
Если по вертикали или горизонтали установлены оба якоря, то при
изменении размеров владельца размер элемента управления изменяется
таким
образом,
чтобы
расстояния
до
сторон
владельца
остались
неизменными.
Свойство AutoSize обеспечивает изменение размеров компонента в
соответствии с размерами его содержимого (текста, изображения, списка,
иерархического дерева и т. д.).
Внешний вид элемента управления
Для определения цвета компонента используется свойство Color. При
нахождении указателя мыши над компонентом его изображение может
32
изменяться в соответствии со значением свойства Cursor. Для текста
компонента шрифт обычно задается свойством Font. Сам текст задается
свойством Text. Свойство Hint содержит текст ярлыка — однострочной
подсказки, которая появляется в маленькой рамке при остановке мыши на
элементе
управления.
Если
свойство ShowHint=true,
то
подсказка
показывается.
Если свойство ShowHint=False, то подсказка не отображается.
Рисунок 3.
У кнопки Hint=’Подсказка’, ShowHint=True;
Видимость компонента.
Элемент управления можно сделать видимым или невидимым. Для этого
применяется свойство Visible.
Visible=True – компонент виден,
Visible=false – компонент не виден.
Доступность элемента управления
Определяется свойством Enabled.
Если Enabled=True, то компонент доступен (полностью работоспособен).
Если Enabled=False, то компонент не доступен (неактивен и отображается
серым цветом).
33
Свойство визуальной принадлежности
Одно из самых важных свойств элементов управления — это свойство
визуальной принадлежности Parent, описанное в классе TControl, и
определяющее внутри какого компонента визуально располагается данный
элемент управления. Данное свойство имеет тип TWinControl, так как любой
элемент управления может располагаться только в Windows-окне.
Класс TWinControl
Класс
TWinControl
обеспечивает
создание
оконных
элементов
управления.
Главное отличие оконного элемента управления от любых других —
наличие дескриптора окна hwnd. Дескриптор окна — это специальный
идентификатор, который операционная система присваивает всем объектам,
которые должны обладать свойствами окна. Оконный элемент управления
умеет:

получать и передавать фокус управления во время выполнения
приложения;

воспринимать управляющие воздействия от мыши и клавиатуры;

размещать на себе другие элементы управления.
Оконными элементами управления являются не только формы, но и
практически все стандартные элементы управления Windows.
Фокус
Для передачи фокуса между элементами управления на одной форме
часто используется клавиша <Таb>. Порядок перемещения фокуса между
элементами определяется свойством TabOrder. В первую очередь фокус
передается компоненту с минимальным значением свойства. Далее — по
возрастанию значения. При переносе компонента на форму это значение
34
задается автоматически в соответствии с числом компонентов на форме.
Если свойство TabStop=False, то компонент не будет откликаться на
клавишу <Таb>. Для передачи фокуса прямо элементу управления
применяется метод SetFocus. Чтобы узнать, имеет ли элемент управления
фокус, в настоящее время используется метод Focused.
Внешний вид
Все оконные элементы имеют рамку по контуру (впрочем, она может быть
не видна). Ее параметры задаются группой свойств:

BevelEdges - задает, какие стороны входят в рамку;

Bevellnner, BevelOuter - задают внешний вид рамки;

BevelKind - определяет стиль рамки;

BevelWidth - задает размер рамки.
Внешний вид оконного элемента определяется свойством Ctl3D. Если
Ctrl3D=True, то элемент управления имеет трехмерный вид. Если
Ctrl3D=False, то элемент выглядит плоским.
Рисунок 4
у Edit1 свойство Ctrl3D=False, у Edit2 свойство Ctrl3D=True
Оконный элемент может содержать другие компоненты. Для управления
ими применяется индексированный список указателей, представляющих
свойство Controls. Общее число дочерних элементов управления содержится
в свойстве ControlCount.
35
Класс TGraphicControl
Класс TGraphicControl используется для создания неоконных (не
получающих фокус) элементов управления. Так как непосредственным
предком класса является класс TControl, то потомки TGraphicControl умеют
реагировать на управляющие воздействия мышью.
Наглядный пример элемента управления, которому не нужно получать
фокус, — это компонент TLabel, предназначенный для отображения текста,
или компонент TImage, предназначенный для визуализации изображений.
Для визуализации элементов управления на основе этого класса используется
канва, инкапсулированная в классе TCanvas.
Вопросы Ответьте на вопросы
1) Какие компоненты называют визуальными?
2) Какие компоненты называют невизуальными?
3) Какие компоненты называют диалоговыми?
4) Какие свойства, методы и события, присущие всем элементам
управления?
5) Какие
свойства
определяют
местоположения
и
размеров
визуального компонента?
6) Для чего используют свойство «Якорь»?
7) Какие свойства можно использовать для управления внешним
видом элемента?
8) Что определяет свойство Parent?
9) Что называют дескриптором окна?
10)
Опишите принцып работы фокуса ввода.
11)
Какие компоненты не получают фокус ввода?
36
Задание 1. Установить на форму две панели (на странице Standart)
panel1 и panel2 и осуществить выравнивание первой панели по верху формы,
а второй панели на всё оставшееся место формы. Использовать свойство
Align.
Задание 2: Посмотреть, как работает «Якорь».
Ход решения:
Задайте размеры формы 250х250. Установите компоненты Memo и кнопку
(рис.5).
Рисунок 5
Установите для кнопки якорь по правой и нижней стороне. Для этого в
подсвойствах свойства Anchors установите следующие значения:
akTop – false, akLeft – false, akRight – true, akBottom – true.
Запустите программу и увеличьте размеры формы.
Как поведет себя кнопка? А Memo?
Теперь для Memo настройте якорь по всем четырем сторонам. Все
подсвойства свойства Anchors установите в True.
37
Запустите приложение и снова увеличьте размер формы.
Как ведет себя Memo?
Задание 3: Установить на форму кнопку и сделать для нее
всплывающую подсказку «Нажми меня».
Задание 4. Установите на форму три кнопки, и сделать так, чтобы
при запуске была одна кнопка видима и доступна, вторая невидима, а третья
видима, но не доступна для пользователя.
Задание 5: создайте форму, показанную на рисунке 6, комбинируя
свойства BevelEdges, Bevellnner, BevelOuter, BevelKind, BevelWidth.
Рисунок 6
38
Урок 4. Свойства компонентов. События мыши и клавиатуры
Обращение к свойству объекта в программе
В программе к свойству объекта можно обратиться так:
<имя объекта>.<имя свойства>
Например: Label1.Caption.
Иногда свойство объекта является в свою очередь объектом. Тогда в
обращении к этому свойству указывается через точки вся цепочка
предшествующих объектов.
Например, метки имеют свойство Font — шрифт, которое в свою очередь
является объектом. У этого объекта имеется множество свойств, в частности,
свойство Color — цвет шрифта. Чтобы сослаться на цвет шрифта метки
Label1, надо написать Label1.Font.Color.
Аналогично для доступа к методам объекта.
<имя объекта>.<имя метода>
Например: Label1.Free.
Оператор With
Оператор with используется для сокращения записи при обращении к
полям записи или к свойствам и методам объекта. В этих случаях
применение with позволяет избежать повторных ссылок на объект в
последующих операторах. Например, группу операторов:
Form1.Label1.left:=Form1.Label1.left+10;
Form1.Label1.font.color:=clRed;
с помощью with можно записать короче:
with Form1.Label1 do
begin
39
left:=left+10;
font.color:=clRed;
end;
События
Приложения Delphi используют управляемые событиями методы для
организации взаимодействия между программой и пользователем. Большая
часть кода, которую Вы будете писать в Delphi, будет инициироваться
событиями. В принципе событием может быть изменение любой величины.
Происхождение события заставляет работать определенный объект, при этом
объект получает заранее определенные параметры для своей настройки на
работу.
Процедура, инициируемая событием, называется обработчиком события.
События делятся на три основные категории:

события мыши,

события клавиатуры и

системные события.
Все действия пользователя при взаимодействии с приложением сводятся к
перемещению мыши, нажатию кнопок мыши и нажатию клавиш клавиатуры.
Рассмотрим обработку в приложении событий, связанных с этими
манипуляциями пользователя.
События мыши
Событие onClick - щелчок мыши на компоненте и некоторые другие
действия пользователя
40
События OnMouseDown, OnMouseMove, OnMouseUp
Метод
OnMouseDown
Описание
Нажатие клавиши мыши над компонентом. Возможно
распознавание нажатой кнопки и координат курсора мыши.
Перемещении курсора мыши над компонентом. Возможно
распознавание нажатой кнопки и координат курсора мыши.
Оно происходит постоянно в процессе перемещения
OnMouseMove курсора мыши и даже просто при его дрожании, неизбежном,
если пользователь не снимает руки с мыши. Это надо
учитывать и пользоваться этим событием очень осторожно,
поскольку оно, в отличие от других, происходит многократно.
Отпускание
OnMouseUp
ранее
нажатой
кнопки
мыши
над
компонентом. Возможно распознавание нажатой кнопки и
координат курсора мыши
Рассмотрим на примере событие OnMouseDown.
Источник событий – параметр Sender
Во все обработчики событий, связанных с манипуляциями мыши
передается параметр Sender типа TObject. Он содержит указатель на
компонент, в котором произошло событие. Он используется, если пишется
обработчик события для одного конкретного компонента. Однако часто один
обработчик применяется для нескольких компонентов.
41
Распознаем, какая кнопка мыши нажата – параметр Button
Параметр Button типа TMouseButton определяет нажатую в этот момент
кнопку мыши. Может принимать следующие значения:

mbLeft соответствует нажатию левой кнопки мыши

mbRight — правой,

mbMiddle — средней.
Например, если вы хотите, чтобы обработчик реагировал на нажатие
только левой кнопки, вы можете его первым оператором написать:
if (Button <> mbLeft) then exit;
Тогда, если значение Button не равно mbLeft, т.е. нажата не левая кнопка,
выполнение обработчика прервется.
Распознаем, какая вспомогательная клавиша была нажата
–
параметр Shift
Параметр Shift может принимать следующие значения:
ssShift - нажата клавиш Shift,
ssAlt- нажата клавиш Alt,
ssCtrl- нажата клавиш Ctrl
ssLeft- нажата левая кнопка мыши
ssRight- нажата правая кнопка мыши
ssMiddle- нажата средняя кнопка мыши
Параметр Button соответствует кнопке, нажимаемой в данный момент, а
параметр Shift содержит информацию о том, какие кнопки были нажаты,
включая и те, которые были нажаты ранее. Поскольку Shift является
множеством, проверять наличие в нем тех или иных элементов надо
операцией in.
Пример: реагируем на событие, заключающееся в нажатии левой кнопки
мыши при нажатой клавише Alt:
if (Button = mbLeft) and (ssAlt in Shift) then ...
42
Аналогичные параметры Button и Shift передаются и в обработчик
события OnMouseUp. Отличие только в том, что параметр Button
соответствует не нажимаемой в данный момент, а отпускаемой кнопке.
Параметр Shift передается также в обработчик события OnMouseMove, так
что и в этом обработчике можно определить, какие клавиши и кнопки
нажаты.
Определяем координаты курсора – параметры X и Y.
Во все события, связанные с мышью, передаются также координаты
курсора X и Y. Эти параметры определяют координаты курсора в клиентской
области компонента. Благодаря этому можно обеспечить различную реакцию
в зависимости оттого, в какой части клиентской области расположен курсор.
Событие OnEnter – возникает в момент получения элементом фокуса в
результате
манипуляции
мышью,
нажатия
клавиши
табуляции
или
программной передачи фокуса. Событие OnExit – возникает в момент потери
элементом фокуса в результате манипуляции мышью, нажатия клавиши
табуляции или программной передачи фокуса.
События клавиатуры
Обработку клавиатуры можно выполнить, используя комбицацию трех
событий.
Событие OnKeyDown происходит при нажатии любой клавиши, включая
функциональные и специальные:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift:
TShiftState);
Например, если мы хотим по нажатию на клавишу Esc закрывать форму,
в обработчик события onKeyDown добавить следующий оператор:
if key=VK_ESCAPE then Close;
43
Здесь метод Close закрывает форму, key – параметр, который определяет
нажатую клавишу, VK_ESCAPE - символическое имя клавишы Esc.
Событие OnKeyPress возникает при нажатии клавиши, генерирующей
символы ASCII, включая управляющие клавиши:
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
Событие OnKeyUp происходит при освобождении любой клавиши:
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
Shift:
TShiftState);
Каждый из обработчиков событий получает, по крайней мере, один
параметр, называемый Key, который представляет нажатую клавишу. В
обработчиках событий OnKeyDown и OnKeyUp параметр Key является
беззнаковым значением типа Word, которое представляет код виртуальной
клавиши Windows. В обработчике события OnKeyPress параметр Key — это
значение типа Char, представляющее символ ASCII. Несмотря на то, что обе
переменные называются Key, они представляют различную информацию.
Все ASCII-символы имеют соответствующие коды виртуальных клавиш, но
многие виртуальные клавиши не имеют ASCII-эквивалента, например
клавиша F1.
Вопросы Ответьте на вопросы:
1)
Как обратится к свойствам объекта или методам объекта?
2)
Для чего используют оператор with?
3)
Что называют обработчиком события?
4)
На какие категории делятся события?
5)
Какие обработчики событий позволяют обрабатывать события
клавиатуры?
6)
Что представляет собой параметр Key?
7)
К каким типам может принадлежать параметр Key ?
44
8)
Какой из обработчиков событий позволяет определить нажатие
функциональной клавиши?
9)
Когда происходит событие onClick?
10) Когда происходит событие onDblClick?
11) В какой момент времени выполняются события onMouseUp,
onMouseDown, onMouseMove?
12) Какие
параметры
передаются
в
обработчике
события
onMouseDown?
13) Для чего используется каждый из параметров?
Задание 1. Напишите приложение, которое при щелчке левой
кнопкой мыши по форме перекрашивает ее в красный цвет.
Ход работы:
Создайте обработчик события OnClick: для этого в объектном инспекторе
перейдите на страницу Events, найдите событие onClick и выполните
двойной щелчок мышью в правой колонке, напротив этого события. На
переднем плане появится окно редактора с помещенной в нужное место
модуля заготовкой обработчика события OnClick. Для изменения цвета
формы в обработчике события OnClick напишите:
Form1.Color:=clRed;
Задание 2. Напишите приложение, в котором при нажатии на
левую кнопку мыши происходит смена цвета с зеленого на красный, и,
наоборот, с красного — на зеленый.
Ход работы:
В соответствии с условием задачи в обработчике события OnClick формы
необходимо проанализировать свойство Color формы: если его значение
45
соответствует красному, то изменить его на зеленый (clGreen), иначе
присвоить значение красный. На языке Object Pascal это записывается так:
if Form1.Color=clRed
then Form1.Color:=clGreen
else Form1.Color:=clRed;
Событие OnDblClick - двойной щелчок мыши на компоненте
Задание 3. Напишите приложение, в котором при двойном щелчке
левой кнопкой мыши изменяется вид курсора.
Ход работы:
Каждое значение свойства Cursor имеет свой числовой эквивалент в
пределах от -21 (crHandPoint) до 0 (crDefault). При каждом двойном щелчке
левой кнопкой мыши значение свойства Cursor будем увеличивать на
единицу, при достижении значения 0 — восстановим значение -21. Введите в
обработчик события формы OnDblClick следующий оператор:
if Cursor=0 then Cursor:=-21 else Cursor:=Cursor+1;
Задание 4: создать несколько кнопок, у которых будет один
обработчик события и который будет уметь работать с разными типами
кнопок.
Ход работы:
Установите на форму несколько разных кнопок TBitBtn, TSpeedButton (на
странице Additional в палитре инструментов). Выделите все кнопки
TSpeedButton и установите свойство GroupIndex=1.
Создайте следующий обработчик для кнопки BitBtn1.
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if Sender is TBitBtn then TBitBtn(Sender).Enabled := False;
if Sender is TSpeedButton then TSpeedButton(Sender).Down := True;
46
end;
Всем остальным кнопкам присвойте этот обработчик с помощью Object
Inspector. Для этого выделите все кнопки, перейдите в окно Object Inspector и
на закладке Events найдите событие onClick. Щелкните в колонке справа от
события и из списка выберите событие Bitbtn1Click (рис.1)
Рисунок 1
Задание 5.
При перемещении курсора по форме при нажатой клавише Shift выдавать
в заголовок формы координаты курсора.
Задание 6. Напишите приложение, позволяющее рисовать отрезок
на форме.
Ход работы:
Чтобы нарисовать на форме пунктирную линию красного цвета от точки с
координатами (10,10) до точки (300,300), создайте обработчик события
формы onClick и введите следующие операторы:
with Canvas do begin
Pen.Color:=ClRed; //цвет линии
Pen.Style:=PsDash; //стиль линии
47
MoveTo(10,10); //переместить курсор в точку (10,10)
LineTo(300,300); //нарисовать линию из точки, где находится курсор в
точку (300,300)
end;
Задание 7. Напишите приложение, которое при нажатии мыши
устанавливает курсор в точку, а при отпускании кнопки мыши в другом
месте формы рисует отрезок от первой точки до второй. Использовать
события MouseDown и MouseUp, для координат использовать параметры x,y.
48
Урок 5. Обработка событий. Динамическое изменение свойств
Задание 1. Поместить на форму два поля ввода и кнопку
"Переслать". При нажатии на кнопку текст из первого поля ввода
переписывается во второе, то есть исчезает в первом поле и появляется во
втором.
Ход работы: установите на форму два Edit и одну кнопку. В обработчик
события нажатия кнопки onClick поместите следующий код:
Задание 2. Создайте приложение, позволяющее изображать кривые
линии при нажатой левой кнопке мыши.
Ход работы:
Создайте обработчик события OnMouseMove и введите следующие
операторы:
Задание 3.
Напишите
приложение,
которое
изображает
прямоугольники (эллипсы)
Подсказка:
В классе TCanvas определен метод Rectangle(x1,y1,x2,y2), в котором
параметры задают координаты противоположных вершин прямоугольника
(т.е. принадлежащих одной из его диагоналей). Нажатие кнопки мыши
(событие OnMouseDown) фиксирует начало рисования прямоугольника и
49
соответственно определяет координаты первой точки, а освобождение
кнопки (событие ОnMouseUp) — окончание рисования прямоугольника и
соответственно определяет координаты второй точки.
Задание 4. Напишите программу, которая при нажатии на клавиши
управления курсором перемещает форму в соответствующем направлении;
при нажатии комбинации клавиши <Shift> и клавиши управления курсором
— изменяет размеры формы.
Задание 5. Напишите приложения для рисования эллипсов с
закрашенной внутренней областью.
Задание 6. Напишите приложения для рисования разноцветных
линий.
50
Урок 6. Компоненты ввода-вывода и редактирования.
Font — шрифт отображения текста в компонентах
Во всех компонентах ввода и отображения текстовой и цифровой
информации шрифт текста, его размер, стиль (жирный, курсив и т.п.)
определяются свойством Font. Это свойство в свою очередь является
объектом
типа
который
TFont,
имеет
множество
подсвойств,
устанавливаемых в процессе проектирования или программно во время
выполнения приложения.
Основные свойства шрифта следующие:
свойство
. Описание
Определяет набор символов шрифта. Каждый вид шрифта,
определяемый его именем (свойство Name), поддерживает
один
или
более
поддерживающих
наборов
несколько
символов.
наборов
Для
шрифтов,
символов,
важно
правильно задать Charset. В Delphi предопределено много
Charset
констант, соответствующих стандартным наборам символов.
Отметим только одно значение — 204, обозначаемое также
константой RUSSIAN_CHARSET, которое соответствует
символам кириллицы. По умолчанию в объектах типа TFont
задается
значение
Charset,
равное
1
или
DEFAULT_CHARSET
Color
Определяет цвет текста.
Height
Характеризует высоту шрифта в пикселях.
Name
Вид (имя) шрифта.
Pitch
Определяет
способ
установки
ширины
символов.
51
Возможные значения:
fpDefault -
ширина
устанавливается
равной
по
умолчанию, т.е. описанной в шрифте заданного вида Name.
fpFixed — установка одинаковой ширины всех символов
fpVariable — установка различной ширины символов.
Задание значения отличного от fpDefault заставляет
Windows искать наилучший способ удовлетворить всем
заданным характеристикам шрифта.
Size
Размер шрифта в кеглях (пунктах).
Стиль шрифта:
полужирный — fsBold,
курсив — fsItalic,
Style
подчеркнутый — fsUnderline,
перечеркнутый — fsStrikeout.
Label1.Font.Style:=[];
Label1.Font.Style:=[fsBold];
{Обычный стиль}
{Полужирный}
Label1.Font.Style:=[fsBold, fsItalic]; {Полужирный курсив}
Значения свойств объекта Font можно задавать все сразу методом Assign,
который записывает значения всех свойств одного объекта в другой.
Отображение текста в надписях компонентов Label, StaticText
Тексты, отображаемые в компонентах, определяются значением их
свойства Сaption. Его можно устанавливать в процессе проектирования или
задавать и изменять программно во время выполнения приложения.
Например:
Label1.Caption:='Новый текст';
52
Во всех компонентах цвет фона определяется свойством Color, а цвет
надписи — подсвойством Color свойства Font. Например, можно задать цвет
фона равным clWhite — белый. Компонент StaticText имеет свойство
BorderStyle, определяющее рамку текста — бордюр. Размер определяется
свойством AutoSize. Если AutoSize=true, то вертикальный и горизонтальный
размеры компонента определяются размером надписи. Если AutoSize=false,
то выравнивание текста внутри компонента определяется свойством
Alignment, которое позволяет выравнивать текст по левому краю, правому
краю или центру клиентской области метки.
Перенос текста в Label по строкам
WordWrap=true - допустимость
переноса
слов
длинной
надписи,
превышающей длину компонента, на новую строчку. При этом свойство
AutoSize = false (чтобы размер компонента не определялся размером
надписи) и сделать высоту компонента такой, чтобы в нем могло
поместиться несколько строк. В метке StaticText перенос длинного текста
осуществляется автоматически, если AutoSize=false и размер компонента
достаточен для размещения нескольких строк.
Окна редактирования Edit и MaskEdit
Внешнее оформление окон редактирования определяется свойством
BorderStyle. Вводимый и выводимый текст содержится в свойстве Text.
Выравнивание текста невозможно. Перенос строк тоже невозможен. Текст,
не помещающийся по длине в окно, просто сдвигается, и пользователь может
перемещаться по нему с помощью курсора.
Свойство AutoSelect определяет, будет ли автоматически выделяться весь
текст при передаче фокуса в окно редактирования. Его имеет смысл задавать
равным true в случаях, когда при переключении в данное окно пользователь
будет скорее заменять текущий текст, чем исправлять его.
53
Имеются также свойства только времени выполнения SelLength, SelStart,
SelText, определяющие соответственно длину выделенного текста, позицию
перед первым символом выделенного текста и сам выделенный текст.
Например, если в окне имеется текст «выделение текста» и в нем
пользователь выделил слово «текста», то SelLength = 6, SelStart = 10 и SelText
= 'текста'. Если выделенного текста нет, то свойство SelStart просто
определяет текущее положение курсора.
Окна редактирования можно использовать и просто как компоненты
отображения текста. Для этого надо установить в true их свойств ReadOnly.
Целесообразно установить AutoSelect в false.
Свойство MaxLength определяет максимальную длину вводимого текста.
Если MaxLength=0, то длина текста не ограничена. В противном случае
значение MaxLength указывает максимальное число символов, которое
может ввести пользователь.
Свойство Modified, доступное только во время выполнения, показывает,
проводилось ли редактирование текста в окне. Если вы хотите использовать
это свойство, то в момент начала работы пользователя с текстом Modified
надо установить в false. Тогда при последующем обращения к этому
свойству можно по его значению (true или false) установить, было или не
было произведено редактирование.
Окно ввода пароля
Свойство PasswordChar позволяет превращать окно редактирования в
окно ввода пароля. По умолчанию значение PasswordChar равно #0 —
нулевому символу. В этом случае это обычное окно редактирования. Но если
в свойстве указать иной символ (например, символ звездочки «*»), то при
вводе пользователем текста в окне будут появляться именно эти символы, а
не те, которые вводит пользователь. Тем самым обеспечивается секретность
ввода пароля.
54
Компонент MaskEdit (на стр. Additional)
Он отличается от Edit тем, что в нем можно задать строку маски в
свойстве EditMask. Маска состоит из трех разделов, между которыми
ставится точка с запятой:
1. записываются специальным образом символы (см. таблицу),
которые можно вводить в каждой позиции, и символы, добавляемые
самой маской;
2.
записывается 1 или 0 в зависимости от того, надо или нет,
чтобы символы, добавляемые маской, включались в свойство Text
компонента;
3.
указывается символ, используемый для обозначения позиций,
в которых еще не осуществлен ввод.
Прочитать результат ввода можно или в свойстве Text, которое в
зависимости от вида второго раздела маски включает или не включает в себя
символы маски, или в свойстве EditText, содержащем введенный текст
вместе с символами маски.
Для построения маски используются специальные символы:
! Поле заполняется слева направо
0 Цифра (0-9) или знак (+/-) обязательны
__ Автоматически вставляет пробел в указанной позиции
> Все символы справа от указанной позиции переводятся в верхний
регистр
< Все символы слева от указанной позиции переводятся в нижний
регистр
,:;/-() Разделители
L Буква обязательна
Примечание. Другие символы, используемые для создания маски, можно
посмотреть в справочной системе Delphi.
55
Вводить маску можно непосредственно в свойство EditMask. Но удобнее
пользоваться специальным редактором масок, вызываемым при нажатии
кнопки с многоточием в строке свойства EditMask в Инспекторе Объектов.
Рассмотрим примеры масок. Маска для ввода номера телефона имеет вид:
!\(999\) 000-00-00;0;_
В этой маске символ 9 означает, что в соответствующей позиции может
быть только цифра. Символ 0 означает, что в данной позиции должна быть
цифра. Символ подчеркивания в конце маски будет заполнять пустые
позиции. Таким образом, пользователю для ввода в окне будет отображен
шаблон:
(___)___-__-__
Поскольку второй раздел маски равен 0, то при чтении введенных
пользователем значений свойства EditText и Text будут различаться.
Свойство EditText (из примера на рисунке ниже) будет равно (095) 123-45-67,
а свойство Text будет равно 0951234567. Если второй раздел маски сделать
равным 1, то значения обоих свойств будут равны (095) 123-45-67.
Рассмотрим еще пример. Если с помощью EditMask надо ввести,
например, целое число без знака, состоящее не более, чем из двух цифр,
можно задать маску 99;0; . Если число обязательно должно быть двузначным,
то маска должна иметь вид 00;0; .
Многострочные окна редактирования Memo и RichEdit
Компоненты
Memo
и
RichEdit
являются окнами
редактирования
многострочного текста.
В компоненте Memo формат (шрифт, его атрибуты, выравнивание)
одинаков для всего текста и определяется свойством Font.
Компонент RichEdit работает с текстом в обогащенном формате RTF. В
этом компоненте разные фрагменты текста можно форматировать по
разному.
56
Компонент RichEdit (стр.Win32)
Свойство SelAttributes
Формат вновь вводимого фрагмента текста.
RichЕdit1.SelAttributes.Color (цвет),
RichЕdit1.SelAttributes.Name (имя шрифта),
RichЕdit1.SelAttributes.Size (размер),
RichЕdit1.SelAttributes.Style (стиль) и ряд других.
Свойство DefAttributes
В компоненте имеется также свойство DefAttributes, содержащее
атрибуты по умолчанию. Эти атрибуты действуют до того момента, когда
изменяются атрибуты в свойстве SelAttributes.
Но значения атрибутов в DefAttributes сохраняются и в любой момент эти
значения могут быть методом Assign присвоены атрибутам свойства
SelAttributes, чтобы вернуться к прежнему стилю.
Свойство DefAttributes доступно только во время выполнения. Поэтому
его атрибуты при необходимости можно задавать, например, в обработчике
события OnCreate.
Свойство Paragraph
Отвечает за выравнивание, отступы и т.д. в пределах текущего абзаца.
свойство
Описание
выравнивание текущего абзаца текста.
Alignment
RichЕdit1.Paragraph.Alignment:=taLeftJustify (по
краю),
левому
57
RichЕdit1.Paragraph.Alignment:=taCenter (по центру)
RichЕdit1.Paragraph.Alignment:=taRightJustify (по правому
краю).
FirstIndent
Число пикселей отступа красной строки.
Управляет вставкой маркеров, как в списках.
RichEdit1.Paragraph. Numbering:=nsNone; — отсутствие
Numbering
маркеров,
RichEdit1.Paragraph.
Numbering:=nsBullet; —
маркеры
ставятся.
LeftIndent
Отступ в пикселях от левого поля.
RightIndent
Отступ в пикселях от правого поля.
Значения подсвойств свойства Paragraph можно задавать только в
процессе выполнения приложения, например, в событии создания формы или
при нажатии какой-нибудь кнопки. Значения подсвойств свойства Paragraph
относятся к тому абзацу, в котором находится курсор.
Общие свойства окон редактирования Memo и RichEdit.
Свойство ScrollBars определяет наличие полос прокрутка текста в окне.
По умолчанию ScrollBars = ssNone, что означает их отсутствие.
Пользователь может в этом случае перемещаться по тексту только с
помощью курсора. Можно задать свойству ScrollBars значения ssHorizontal,
ssVertical или ssBoth, что будет соответственно означать наличие
горизонтальной, вертикальной или обеих полос прокрутки.
Основное свойство окон Memo и RichEdit — Lines, содержащее текст
окна в виде списка строк и имеющее тип TStrings. Начальное значение текста
можно установить в процессе проектирования, нажав кнопку с многоточием
около свойства Lines в окне Инспектора Объектов.
58
Во время выполнения приложения вы можете заносить текст в окно
редактирования с помощью методов свойства Lines типа TStrings.
Весь текст, представленный одной строкой типа String, внутри которой
используются разделители типа символов возврата каретки и перевода
строки, содержится в свойстве Text.
Доступ к отдельной строке текста вы можете получить с помощью
свойства Strings[Index: Integer]. Индексы начинаются с 0. Так что
Memo1.Lines.Strings[0] — это текст первой строки.
Свойство только для чтения Count указывает число строк в тексте.
Для очистки текста в окне надо выполнить процедуру Clear. Этот метод
относится к самому окну, а не к его свойству Lines.
Для занесения новой строки в конец текста окна редактирования можно
воспользоваться методами Add или Append свойства Lines. Для загрузки
текста из файла применяется метод LoadFromFile.
Сохранение текста в файле и загрузка из файла
Сохранение текста в файле может осуществляться командой
Memo1.Lines.SaveToFile('text.txt');
Загрузка в окно Memo1 текста из файла может осуществляться командой
Memo1.Lines.LoadFromFile ('text.txt');
Свойство SelStart компонентов Memo и RichEdit указывает позицию
курсора в тексте или начало выделенного пользователем текста. Свойство
CaretPos указывает на запись, поле X которой содержит индекс символа в
строке, перед которым расположен курсор. Поле Y — индекс строки, в
которой находится курсор. Учитывая, что индексы начинаются с 0, значения
Memo1.CaretPos.Y+1и Memо1.CaretPos.X+1 определяют соответственно
номер строки и символа в ней, перед которым расположен курсор. В
редакторе на рисунке именно эти значения (только не для Memo, а для
59
RichEdit) использованы, чтобы отображать в строке состояния позицию
курсора.
Вопросы Ответьте на вопросы:
1) Каким компонентам присуще свойство Font?
2) Перечислите основные свойства шрифта?
3) С помощью каких свойств можно изменять отображение текста в
надписях?
4) Можно ли в окне редактирования выровнять текст?
5) Какие
свойства
времени
выполнения
для
компонентов
редактирования? Опишить работу каждого.
6) Как использовать окно редактирования для отображения текста?
7) Какое свойство окна ввода превращает в окно ввода пароля?
8) Опишите составляющие маски.
9) Какие символы используют для построения маски?
10)
Для
чего
используется
свойство.SelAttributes
компонента
RichЕdit?
11)
Как в компоненте RichЕdit организовать красную строку?
12)
Как получить доступ к отдельной строке текста?
13)
Какая команда осуществлят сохранение текста Memo в файле?
14)
Загрузка в окно Memo текста из файла осуществляться
командой?
60
Задание 1. Рассмотреть свойства компонента Label, создав
следующию форму.
Рис. 1.
Задание 2. Создайте следующую форму, используя компоненты
Edit и EditMask.
Поле Edit - для ввода пароля. При вводе текста, он должен заменяться на
звездочки.
Для ввода телефона и даты использовать компонент MaskEdit.
Рис. 2
Задание 3: на форме расположить компоненты Memo1,
FontDialog1 (стр.Dialogs)— диалог выбора шрифта и кнопку. По нажатию на
кнопку выводить окно настройки шрифта.
61
Ход работы:
В обработчик события OnClick кнопки вставьте оператор:
if (FontDialog1.Execute) then Memo1.Font.Assign(FontDialog1.Font);
Если пользователь сменил атрибуты в диалоговом окне выбора шрифта,
то метод FontDialog1.Execute возвращает true и атрибуты шрифта компонента
Memo1 устанавливаются равными выбранным пользователем.
Задание 4. Установите на форму компоненты RichEdit, FontDialog
и кнопку Button, которая позволит пользователю менять атрибуты текста. В
обработчик щелчка кнопки введите код:
Объекты SelAttributes и Font совместимы по типу. Поэтому можно
присвоить сразу все свойства одного объекта другому:
if FontDialog1.Execute then RichEdit1.SelAttributes.Assign(FontDialog1.Font);
RichEdit1.SetFocus;
Запустите приложение и увидите, что вы можете менять атрибуты текста,
выполняя отдельные фрагменты различными шрифтами, размерами, цветами,
стилями. Устанавливаемые атрибуты влияют на выделенный текст или, если
ничего не выделено, то на атрибуты нового текста, вводимого начиная с
текущей позиции курсора (позиция курсора определяется свойством SelStart).
Задание 5. По нажатию на кнопку в окно RichEdit должен
выводиться текст (рис.3), оформленный таким образом.
Рис. 3
62
Урок 7 Компоненты для работы со списками
Компоненты ListBox и ComboBox отображают списки строк.
ListBox
Только отображает данные и позволяет пользователю выбрать из них то,
что ему надо.
ListBox отображает список в раскрытом виде и автоматически добавляет в
список полосы прокрутки, если все строки не помещаются в окне
компонента.
Множественный выбор в компоненте ListBox
В компоненте ListBox имеется свойство MultiSelect, разрешающее
пользователю множественный выбор в списке (на рис. это свойство
установлено в true в среднем верхнем списке).
Если MultiSelect=false, то пользователь может выбрать только один
элемент списка.
63
Свойство ItemIndex - индекс выбранной строки. Если ни одна строка не
выбрана, то ItemIndex = -1. По умолчанию ItemIndex = -1. Это означает, что
ни один элемент списка не выбран.
Если
допускается
множественный
выбор,
то
значение
ItemIndex
соответствует тому элементу списка, который находится в фокусе. При
множественном выборе проверить, выбран ли данный элемент, можно
проверив свойство: Selected[Index:Integer] типа Boolean.
Если ExtendedSelect=true, то пользователь может выделить интервал
элементов, выделив один из них, затем нажав клавишу Shift и переведя
курсор к другому элементу. Выделить не прилегающие друг к другу
элементы пользователь может, если будет удерживать во время выбора
нажатой клавишу Ctrl.
Если же ExtendedSelect=false, то клавиши Shift и Ctrl при выборе не
работают.
Свойство Columns определяет число столбцов, в которых будет
отображаться список, если он не помещается целиком в окне компонента
ListBox.
ComboBox
не только отображает данные, но и позволяет их редактировать.
ComboBox позволяет отображать список, как в развернутом виде, так и в
виде выпадающего списка, что обычно удобнее, так как экономит площадь
окна приложения.
Стиль изображения этого компонента определяется свойством Style,
которое может принимать следующие значения:
64

csDropDown
-
выпадающий
список
с
окном
редактирования,
позволяющим пользователю вводить или редактировать текст.

csSimple - развернутый список с окном редактирования, позволяющим
пользователю вводить или редактировать текст.

csDropDownList
-
выпадающий
список,
не
содержащий
окна
редактирования.
Выбор пользователя или введенный им текст можно определить по
значению свойства Text. Если же надо определить индекс выбранного
пользователем элемента списка, то можно воспользоваться свойством
ItemIndex. Если в окне проводилось редактирование данных, то ItemIndex =
-1. По этому признаку можно определить, что редактирование проводилось.
Общие свойства
Основное свойство обоих компонентов, содержащее список строк, —
Items, имеющее тип TStrings. Заполнить его во время проектирования
можно, нажав кнопку с многоточием около этого свойства в окне Инспектора
Объектов. Во время выполнения работать с этим свойством можно,
пользуясь свойствами и методами класса TStrings — Clear, Add и другими.
65
Сортировка списка Свойство Sorted позволяет упорядочить список по
алфавиту. При Sorted=true новые строки в список добавляются не в конец, а
по алфавиту. Свойство Style, установленное в lbStandard (значение по
умолчанию) соответствует списку строк. Другие значения Style позволяют
отображать в списке не только текст, но и изображения.
Список с индикаторами CheckListBox.
Выглядит он так же, как ListBox, но около каждой строки имеется
индикатор, который пользователь может переключать. Индикаторы можно
переключать и программно, если список используется для вывода данных и
необходимо в нем отметить какую-то характеристику каждого объекта,
например, наличие товара данного наименования на складе.
Все свойства, характеризующие компонент CheckListBox как список,
аналогичны
ListBox,
за
исключением
свойств,
определяющих
множественный выбор. Эти свойства компоненту CheckListBox не нужны,
поскольку в нем множественный выбор можно осуществлять установкой
индикаторов.
Состояния индикаторов определяют два свойства: State и Checked. Оба
эти свойства можно рассматривать как индексированные массивы, каждый
элемент которого соответствует индексу строки. Эти свойства можно
устанавливать программно или читать, определяя установки пользователя.
Например, операторы
CheckListBox1.Checked[1]:= true;
CheckListBox1.State[2]:= cbGrayed;
устанавливают индикатор второй строки списка CheckListBox1 в
состояние выбранного, а индикатор третьей строки — в промежуточное
состояние (вспомним, что индексы начинаются с 0). Оператор
for i:=0 to CheckListBox1.Items.Count - 1 do
if CheckListBox1.Checked[i] then ...
66
проверяет состояние всех индикаторов списка, и для выбранных
пользователем строк осуществляет какие-то действия (в приведенном
операторе на месте этих действий просто поставлено многоточие).
В компоненте CheckListBox имеется также событие OnClickCheck,
возникающее при каждом изменении пользователем состояния индикатора.
Его можно использовать для обработки результатов изменения.
Вопросы: Ответьте на вопросы
1) Как осуществить множественный выбор в ListBox?
2) Какое свойство определяет индекс выбранной строки в ListBox?
3) Чем отличаются компоненты ListBox и ComboBox
4) Какие вожможны варианты изображения в ComboBox?
5) Охарактеризуйте компонент CheckListBox.
6) Что представляют собой свойства State и Checked компонента
CheckListBox?
Задание 1. Рассмотреть свойства компонентов ListBox, ComboBox
и CheckListBox, создав следующую форму.
67
Задание 2. Установить на форму компоненты ListBox и ComboBox,
два компонента Edit и кнопку. По нажатию на кнопку текст из первого Edit
добавляется в список ListBox, а текст из второго Edit добавляется в список
ComboBox.
Задание 3. В предыдущем задании сделать так, чтобы текст,
введенный в ComboBox по нажатию на кнопку, добавлялся в список ListBox.
Задание 4. Список группы. Составить программу, которая по
нажатию на кнопку «Добавить в список» добавляет в список ListBox
фамилию и имя, указанные в соответствующих Edit. Нажатие на кнопку
«Удалить из списка» должно удалять из ListBox.
Ход работы:
Расположите компоненты на форме (рис.1).
Рисунок 1.
В обработчик кнопки «Добавить в список» занесите следующий код:
ListBox1.Items.Add(Edit1.Text+' '+Edit2.Text);
Edit1.SetFocus;
68
В обработчик кнопки «Удалить из списка»:
ListBox1.Items.Delete(ListBox1.ItemIndex);
В обработчик кнопки «Очистить список»:
ListBox1.Items.Clear;
Запустите программу и создайте список из нескольких человек. Проверьте
кнопки «Удаление из списка», «Очистить список».
Задание 5. Справочник цветов. Создать программу, которая
позволяет из списка ListBox выбирать название цвета. В результате выбора
на экране должно появляться название цвета в формате RGB. Примерный вид
запущенного приложения показан на рисунке 2.
Рисунок 2.
Название цвета
Формат RGB
черный
000000
белый
FFFFFF
красный
FF0000
зеленый
00FF00
бирюзовый
00FFFF
69
синий
0000FF
фиолетовый
FF00FF
желтый
FFFF00
коричневый
996633
оранжевый
FF8000
лиловый
8000FF
серый
А0А0А0
Задание
6.
Выбор
подарка.
После
запуска
программы
пользователь может сформировать список подарков для друзей. Выбирать
подарки можно из списка «Подарки», после выбора подарка он отображается
во втором списке «Выбранные подарки». С помощью кнопки «Добавить»
можно добавить название подарка, которого нет в списке «Подарки», а с
помощью кнопки «Удалить» - удалить выделенный подарок из списка
«Выбранные подарки». Для отображения списков использовать компоненты
ListBox. Добавить возможность сохранения списков в текстовый файл и
предусмотреть загрузку из него, для чего использовать методы
ComboBox1.Items.SaveToFile(‘1.txt’)
ComboBox1.Items.LoadFromFile(‘1.txt’).
и
70
Урок 8. Работа с таблицами
Класс TDrawGrid
Компонент DrawGrid предназначен для создания таблицы, в ячейках
которой
расположены
данные.
Компонент
обеспечивает
двумерное
представление данных, упорядоченных по строкам и столбцам.
Таблица
делится
на две
части
—
фиксированную
и
рабочую.
Фиксированная часть служит для показа заголовков столбцов/строк и для
ручного управления их размерами. Обычно фиксированная часть занимает
крайний левый столбец и самый верхний ряд таблицы. Она может содержать
произвольное количество столбцов и рядов, причем эти величины можно
изменять как в процессе разработки, так и программно. Рабочая часть
состоит из ячеек, в которых находятся данные. Если рабочая часть не
помещается целиком в пределах окна компонента, то у компонента
автоматически появляются полосы прокрутки. При прокрутке рабочей
области фиксированная часть не исчезает, но меняется ее содержимое —
заголовки строк и рядов. Заносить данные в ячейки таблицы можно только в
ходе работы программы.
Свойства компонента DrawGrid
У компонента есть множество свойств, некоторые из них доступны уже в
процессе разработки программы, остальные — только в ходе ее выполнения.
Рассмотрим основные свойства, доступные во время разработки.
Свойство
ColCount
Описание
количество
столбцов
фиксированной части;
таблицы,
включая
столбцы
71
RowCount
количество строк таблицы.
FixedCols
определяет количество столбцов фиксированной зоны;
FixedRows
определяет количество строк фиксированной зоны;
DefaultRowHeight
содержит значение высоты строки по умолчанию;
DefaultColWidth
определяет ширину столбца по умолчанию;
FixedColor
устанавливает цвет фиксированной зоны;
при
значении,
автоматическая
таблицы
DefaultDrawing
равном
прорисовка
(фиксированной
True,
происходит
служебных
элементов
зоны,
фона
и
прямоугольника сфокусированной ячейки и т. д.). Если
свойство установлено в False, то прорисовки этих
элементов необходимо определять в обработчике
события OnDrawCell;
Дополнительно к перечисленным в таблице свойствам необходимо
обратить особое внимание на свойство Options, определяющее некоторые
особенности
поведения
компонента
DrawGrid.
Свойство
Options
определяется следующим образом:
Свойство Options является множеством, определяющим многие свойства
таблицы:
наличие разделительных вертикальных и горизонтальных линий в
фиксированных (goFixedVertLine и goFixedHorzLine) и не фиксированных
(goVertLine и goHorzLine) ячейках, возможность для пользователя изменять с
помощью мыши размеры столбцов и строк (goColSizing и goRowSizing),
перемещать столбцы и строки (goColMoving и goRowMoving) и многое
другое.
Если таблицу необходимо редактировать, то в свойстве Options
необходимо подсвойство goEditing установить равным True.
72
Свойство Col и Row определяет номер столбца и строки выделенной
ячейки. Нумерация и строк и столбцов начинается с нуля, включая строки и
столбцы фиксированной зоны. Номер самого левого столбца, видимого в
прокручиваемой зоне ячеек, содержится в LeftCol, а номер самого верхнего
ряда — в свойстве TopRow.
Свойство
Selection
позволяет
определить
координаты
текущего
выделения. Описывается свойство следующим образом:
Type TGridCoord = record
X: Longint;
Y: Longint;
end;
TGridRect = record
case Integer of
0: (Left, Top, Right, Bottom: Longint);
1: (TopLeft, BottomRight: TGridCoord);
end;
property Selection: TGridRect;
Свойство Selection определяет группу выделенных ячеек в координатах
левая верхняя и правая нижняя ячейки. После выделения сфокусированной
окажется правая нижняя ячейка.
Методы компонента DrawGrid
Экранные координаты прямоугольника ячейки можно получить по
номерам столбца ACol и ряда ARow с помощью метода CellRect:
function CellRect(ACol, ARow: Longint): TRect;
где тип TRect — это
type TRect = record
case Integer of
0: (Left, Top, Right, Bottom: Integer);
73
1: (TopLeft, BottomRight: TPoint) ;
end;
TPoint = record
X: Longint;
Y: Longint;
end;
Получить номер столбца ACol и номер строки ARow по экранным
координатам (X.Y) точки можно с помощью метода MouseToCell(X, Y:
Integer; var ACol, ARow: Longint);
События компонента DrawGrid
Событие
Описание
возникает при перемещении столбца.
procedure
OnColumnMoved
TForm1.DrawGrid1ColumnMoved(Sender:
TObject; FromIndex, ToIndex: Integer);
Параметр FromIndex содержит «старый» индекс
столбца, а ToIndex — «новый» индекс перемещаемого
столбца.
OnRowMoved
OnTopLeftChanged
возникает при перемещении строки (параметры
аналогичные OnColumnMoved).
происходит при изменении значения TopRow или
LeftCol в результате прокрутки рабочей зоны
возникает
при
попытке
выделить
ячейку
с
табличными координатами (ACol, ARow).
OnSelectCell
Событие описывается следующим образом:
procedure
TForm1.DrawGrid1SelectCell(Sender
TObject; ACol, ARow: Integer; var CanSelect: Boolean);
:
74
В обработчик этого события передаются целые
параметры ACol и ARow — столбец и строка
выделенной ячейки, и булевый параметр CanSelect —
допустимость
выбора.
Параметр
можно
CanSelect
использовать для запрета выделения ячейки, задав его
значение false. А параметры ACol и ARow могут
использоваться для какой-то реакции программы на
выделение пользователя. Например, оператор
ячейка
Label1.Caption:='Выбрана
'
+IntToStr(ARow)+':'+IntToStr(ACol);
выдаст в метку Label1 номер выбранной ячейки.
возникает по завершении редактирования ячейки с
OnSetEditText
координатами
(ACol,
обработчик
получает
ARow).
В
параметре
Value
ввода
или
результат
редактирования текста. Описывается событие так:
procedure
TForm1.DrawGrid1SetEditText
(Sender:
TObject; ACol, ARow: Integer; const Value: String);
возникают при редактировании текста в ячейке с
табличными координатами (ACol, ARow). В параметре
Value первого события обработчик должен вернуть
шаблон для редактора TEditMask. Параметр Value для
OnGetMaskEdit
и OnGetEditText
события OnGetEditText должен содержать текстовую
информацию
для
редактора
TEditMask.
Описание
событий выглядит следующим образом:
procedure
TForm1.DrawGrid1GetEditMask(Sender:
TObject; ACol, ARow: Integer; var Value: String);
procedure
TForm1.DrawGrid1GetEditText(Sender:
TObject; ACol, ARow: Integer; var Value: String);
75
Событие
происходит
в
случае
необходимости
перерисовки ячейки с номером столбца ACol и номером
строки ARow. Обработчик данного события полностью
берет на себя ответственность за размещение в каждой
ячейке
нужных
данных.
Описывается
следующим
образом:
procedure
OnDrawCell
TForm1.DrawGrid1DrawCell(Sender:
TObject; ACol, ARow: Integer; Rect: TRect; State:
TGridDrawState);
Параметр Rect определяет
прямоугольник
прорисовки. Параметр State — состояние ячейки
gdSelected — ячейка выделена,
gdFocused — ячейка сфокусирована,
gdFixed — ячейка принадлежит фиксированной зоне
таблицы. Для прорисовки используется свойство Canvas.
Класс TStringGrid
Компонент StringGrid (на странице Additional) предназначен для
создания таблиц, в ячейках которых располагаются произвольные текстовые
строки.
Класс TStringGrid является прямым потомком класса TDrawGrid, от
которого им унаследовано большинство свойств и методов. У данного класса
появляется лишь несколько новых свойств.
Свойство
Описание
Cells[ACol, ARow: Integer]:
Строка,
в
ячейке
с
индексами столбца и строки ACol и ARow.
string
Cols[Index:
содержащаяся
Integer]:
Список строк, содержащихся в столбце с
76
индексом Index.
TStrings
Rows[Index:
Список столбцов, содержащихся в строке
Integer]:
с индексом Index.
TStrings
Все эти свойства доступны во время выполнения. Задавать тексты можно
программно или по отдельным ячейкам, или сразу по столбцам и строкам с
помощью методов класса TStrings.
Вывод текста в ячейку
StringGrid1.Cells [1, 0]:=’Проверка’; (первая строка, второй столбец)
Вопросы:
1) На какие части делится таблица?
2) Какие подсвойста определяет свойство Options?
3) Какие методы присуще компоненту DrawGrid?
4) Какое событие возникает при завершении редактирования ячейки
DrawGrid?
5) Какое событие возникает при попытке выделить ячейки DrawGrid?
6) Какие новые свойства появляются у компонента StringGrid?
Задание 1. Установите на форму компонент DrawGrid (на странице
Additional).
Запустите программу и попробуйте ввести в таблицу какие-либо данные.
Получилось? Нет. А теперь установите в свойстве Options подсвойство
goEditing=true.
Теперь запустите программу и попробуйте ввести какие-либо данные в
ячейки таблицы.
77
Задание 2. Вывести в заголовок формы номера строки и столца
выделенной ячейки.
Решение: установите на форму компонент DrawGrid1 и создайте для него
обработчик события OnMouseDown. В него внесите следующие операторы:
Задание
3.
Создайте
приложение,
которое
позволяет
просматривать символы системных шрифтов.
Ход работы:
1. Установите на форму компоненты Panel1 (Align=alTop) и DrawGrid1
(Align=alClient). На панель установите компонент ComboBox1.
2. Настройте у компонента DrawGrid1 следующие свойства: RowCount=7,
ColCount=32,
FixedCols=0,
FixedRows=0,
DafaultColWidth=20,
DefaultRowHeight=20.
3. Измените размеры формы так, чтобы сетка не имела полос прокрутки, а
вокруг ячеек не было пустого пространства.
4. В результате получится форма, показанная на рисунке ниже.
78
5. Для того чтобы содержимое каждой ячейки перерисовывалось, создайте
обработчик
события
OnDrawCell
для
компонента
DrawGrid1.
Для
изображения символов шрифта воспользуемся свойством Canvas компонента
DrawGrid1. Непосредственно нам понадобится метод TextRect свойства
Canvas. Этот метод используется для вывода текстовой информации в
определенной ячейке. Обработчик события будет выглядеть так:
{параметры ячейки для вывода символов шрифта берутся из параметров
обработчика события, а символ шрифта для отображения в ячейке
определяется в зависимости от строки и столбца}
6. Сохраните проект. Убедитесь, что в ячейках таблицы отображаются
символы системного шрифта, установленного по умолчанию.
7. Для выбора шрифта воспользуемся компонентом ComboBox1. Для того
чтобы данный компонент содержал все экранные шрифты, надо при
создании формы занести их в список. Названия всех экранных шрифтов
можно узнать с помощью глобальной переменной Screen типа TScreen.
Данная переменная автоматически добавляется во все приложения Delphi.
Переменная Screen содержит информацию о текущем состоянии экрана
79
приложения: названия форм и модулей данных, которые используются
приложением; данные об активной форме и компонентах, используемых этой
формой; размер и разрешение используемого экрана; информацию о
доступных приложению курсорах и шрифтах. Информация о доступных
приложению шрифтах содержится в свойстве Font, принадлежащем
переменной Screen.
8. Создайте для формы обработчик события onCreate и внесите в него
операторы:
9. Сохраните и запустите проект. Компонент DrawGrid1 содержит
символы шрифта, установленного в ComboBox1.
Сколько шрифтов установлено на компьютере?
Что происходит при выборе другого шрифта?
10. Для того чтобы связать значение имени шрифта у DrawGrid1 и
ComboBox1, создадим еще один обработчик события:
11. Сохраните и запустите проект. Что происходит при изменении
шрифта?
80
Задание 4. Рассмотреть свойства компонента StringGrid и создать
следующую таблицу. По щелчку на любую ячейку номер ее строки и
столбца, а также содержимое ячейки должно отображаться в заголовке
формы.
Задание 5. Доработать программу с таблицей следующим образом:
по щелчку на любую ячейку номер ее строки и столбца должны
отображаться в Label1, а содержимое ячейки должно отображаться в Label2.
81
Урок 9. Кнопочные компоненты, переключатели
Кнопки Button (на стр.Standart) и BitBtn (на стр.Additional)
В надписях (Caption) кнопок можно предусматривать использование
клавиш ускоренного доступа, выделяя для этого один из символов надписи.
Перед символом, который должен соответствовать клавише ускоренного
доступа, ставится символ амперсанта «&». Этот символ не появляется в
надписи, а следующий за ним символ оказывается подчеркнутым. Тогда
пользователь может вместо щелчка на кнопке нажать в любой момент
клавишу Alt совместно с клавишей выделенного символа.
Свойство Cancel, если его установить в true, определяет, что нажатие
пользователем клавиши Esc будет эквивалентно нажатию на данную кнопку.
Свойство Default, если его установить в true, определяет, что нажатие
пользователем клавиши ввода Enter будет эквивалентно нажатию на данную
кнопку, даже если данная кнопка в этот момент не находится в фокусе.
Правда, если в момент нажатия Enter в фокусе находится другая кнопка, то
все-таки сработает именно кнопка в фокусе.
Особенности кнопки с пиктограммой BitBtn (на стр.Additional)
При нажатии кнопки с многоточием в строке свойства Glyph в
Инспекторе Объектов вызывается окно, нажав в нем кнопку Load, вы
перейдете в обычное окно открытия файла рисунка и можете выбрать файл
битовой матрицы .bmp, содержащий желаемое изображение.
Имеется возможность указать тип кнопки в свойстве Kind, при этом будет
меняться
картинка
и
надпись.
В
свойстве
Caption
настраиваются горячие кнопки и соответствующие действия.
Расположение изображения и надписи на кнопке
автоматически
82
Свойство Описание
Если = -1 (значение по умолчанию), то изображение и надпись
размещаются в центре кнопки. Если же Margin > 0, то в
Margin
зависимости
от
значения
Layout
изображение
и
надпись
смещаются к той или иной кромке кнопки, отступая от нее на
число пикселей, заданное значением Margin.
Положение изображения по отношению к надписи. blGlyphLeft
Layout
(слева, по умолчанию), blGlyphRight (справа), blGlyphТор (вверху),
blGlyphBottom (внизу)
задает число пикселей, разделяющих изображение и надпись на
поверхности кнопки. По умолчанию Spacing = 4. Если задать
Spacing
Spacing = 0, изображение и надпись будут размещены вплотную
друг к другу. Если задать Spacing = -1, то текст появится
посередине между изображением и краем кнопки.
Кнопка с фиксацией SpeedButton
Кнопки SpeedButton имеют возможность отображения пиктограмм и
могут использоваться как обычные управляющие кнопки или как кнопки с
фиксацией нажатого состояния. Обычно они используются в качестве кнопок
в инструментальных панелях, в которых требуется фиксация нажатого
состояния.
Свойство AllowAllUp - разрешение отжатого состояния всех кнопок
группы.
Если свойство Down=true, то исходное состояние кнопки — нажатое.
Если GroupIndex=0, то кнопка ведет себя так же, как Button и BitBtn. При
нажатии пользователем кнопки она погружается, а при отпускании
возвращается в нормальное состояние. В этом случае свойства AllowAllUp и
83
Down
не
влияют
на
поведение
кнопки.
Если
Grouplndex>0
и
AllowAllUp=true, то кнопка при щелчке пользователя на ней погружается и
остается в нажатом состоянии. При повторном щелчке пользователя на
кнопке она освобождается и переходит в нормальное состояние. Если у
группы кнопок GroupIndex имеет одинаковое ненулевое значение, то они
образуют группу взаимосвязанных кнопок, из которых нажатой может быть
только одна. Если AllowAllUp=true, то при щелчке по нажатой кнопке она
освободится (т.е. все кнопки группы будут отжаты). Если AllowAllUp=false,
то щелчок на нажатой кнопке не приведет к изменению вида кнопки.
Состояние кнопки во время выполнения можно определить по значению
свойства Down: если значение равно true, то кнопка нажата. Во время
события OnClick значение Down уже равно тому состоянию, которое примет
кнопка в результате щелчка на ней.
Индикаторы с флажком CheckBox (на стр.Standart)
Используются в приложениях для того, чтобы пользователь мог включать
и выключать какие-то опции, или для индикации состояния.
При каждом щелчке пользователя на индикаторе его состояние
изменяется, при этом изменяется значение свойства State:
Внешний
вид
Значение
Описание
cbChecked
Выделение (появление черной галочки)
Промежуточное (серое окно индикатора
cbGrayed
и серая галочка).
Обычно используется, если индикатор
применяется для отображения какой-то
84
характеристики объекта.
Например, индикатор показывает, какой
регистр
использовался
при
написании
фрагмента текста. Если весь текст написан
в верхнем регистре –
индикатор
может
принимать
выделенное состояние,
если в нижнем — не выделенное, а
если использовались оба регистра —
промежуточное.
cbUnchecked
Не
выделенное
(пустое
окно
индикатора)
Если свойство AllowGrayed=true, то допускаются три возможных
состояния.
Если свойство AllowGrayed=false, то допускается только два состояния:
выделенное и не выделенное. Проверять состояние индикатора можно по
значению свойства Checked. Если Checked=true, то индикатор выбран, т.е.
State = cbChecked. Если Checked=false, то State=cbUnchecked или
cbGrayed.
Радиокнопка RadioButton.
Свойство
Описание
Caption
надпись, появляющуюся около кнопки.
с какой стороны от кнопки появится надпись:
Alignment
taLeftJustify — слева,
taRightJustify —
справа
(это
значение
принято
по
85
умолчанию).
определяет, выбрана ли данная кнопка пользователем, или
нет. Поскольку в начале выполнения приложения обычно
Checked
надо, чтобы одна из кнопок группы была выбрана по
умолчанию, ее свойство Checked надо установить в true в
процессе проектирования.
Компонент
RadioGroup
(на
стр.Standart)
-
панель
группы
радиокнопок.
Это панель, которая может содержать регулярно расположенные
столбцами и строками радиокнопки.
Свойство
Описание
Columns
Количество столбцов радиокнопок (не более 17).
Индекс
выбранной
пользователем).
кнопки
Индексы
(какая
начинаются
кнопка
с
выбрана
0.
По
умолчанию ItemIndex = -1, что означает отсутствие выбранной
ItemIndex
кнопки.
Определить, какая радиокнопка выбрана в RadioGroup, можно так:
case RadioGroup1.ItemIndex of
0: ShowMessage('Выбран первый элемент');
1: ShowMessage('Выбран второй элемент');
2: ShowMessage('Выбран третий элемент');
end;
Возможность нерегулярного расположения кнопок дают компоненты
RadioButton, сгруппированные панелью GroupBox.
Узнать значение выделенного элемента можно следующим образом
(выводим значение в Label):
86
Label1.Caption:=RadioGroup1.Items[RadioGroup1.ItemIndex];
Панель GroupBox
Выглядит на форме так же, как RadioGroup, и надпись в ее верхнем левом
углу также определяется свойством Caption. Назначение панели — служить
контейнером для других управляющих элементов, в частности, для
радиокнопок RadioButton
Вопросы:
1) Как предусматривать использование клавиш ускоренного доступа?
2) Как установить желаемое изображение на кнопку?
3) Для чего обычно используются кнопки SpeedButton?
4) Для чего в приложениях используются индикаторы с флажком?
5) Назначение панели RadioGroup?
Задание 1. Установите на форму кнопку, свойство Caption =
&Выполнить. На кнопке эта надпись будет иметь вид «Выполнить». В
обработчике события нажатия кнопки впишите следующий текст:
ShowMessage(‘Нажали кнопку’);
Запустите программу и нажмите клавиши Alt-В.
Задание 2. Установите на форму кнопку, назовите ее «Выход». В
обработчике события onClick напишите код:
Form1.close;
Свойство Cancel установите = True. Запустите программу и нажмите
клавишу Esc.
Как поведет себя программа?
87
Задание 3: установите на форму 5 кнопок BitBtn и настройте
изображения на кнопках следующим образом:
Задание 4. Установите на форме три кнопки SpeedButton. Дайте им
соответствующие названия, настройте свойство Font так, чтобы текст на
кнопках выглядел как на рисунке. Установите свойство GroupIndex=1 для
всех трех кнопок. У первой кнопки установите свойство Down=True.
Запустите программу и посмотрите, как ведут себя кнопки.
Задание 5. Измените свойства кнопок так, чтобы кнопки
нажимались и оставались нажатыми до тех пор, пока на них не нажмут
второй раз, независимо друг от друга.
Задание 6. Установить на форму CheckBox и настроить его
свойства таким образом, чтобы индикатор проходил через три состояния по
щелчку пользователя.
88
Задание 7. Установите на форму компоненты, показанные на
рисунке, и настройте их внешний вид, используя свойства, изученные выше.
89
Урок 10. Работа с кнопками и переключателями
Задание 1. Установите на форме две кнопки BitBtn, три CheckBox,
один Memo (рис.1). По нажатию на кнопку OK должны меняться настройки
шрифта в поле Memo в соответствии с установленными флажками CheckBox.
По нажатию на кнопку Close форма должна закрываться.
Подсказка: установка полужирного начертания в компоненте Memo
выполняется следующим оператором:
memo1.Font.Style:=memo1.Font.Style+[fsBold];
Отключение полужирного начертания:
memo1.Font.Style:=memo1.Font.Style-[fsBold];
Рис. 1.
Задание 2. Создайте программу, подсчитывающую стоимость
заказа (рис.2). Результат подсчета должен выводиться на Panel.
Подсказка: в обработчике события onClick компонента CheckListBox
необходимо проверять все строки. Если строка выделена (стоит галочка), то
90
нужно к общей стоимости прибавлять соответствующую сумму из ListBox.
Для пробега по строкам использовать цикл For.
Рис. 2
Задание 3. Разместите на форме компоненты, как показано на
рисунке 3 и установите их необходимые свойства в инспекторе объектов.
Компонент
SpinEdit
Вы
найдете
на
странице
Samples.
Компонент
ColorDialogs находится на странице Dialogs. Компонент Shape на странице
Additional.
91
Рис. 3
Самостоятельно создайте обработчики событий для радиогрупп.
Подсказка: Программно изменить фигуру компонента Shape можно так:
Shape1.Shape:=stCircle;//окружность
Shape
Фигура
stEllipse
Эллипс
stSquare;
Квадрат
stRectangle;
Прямоугольник
stRoundRect;
Скругленный прямоугольник
Программно изменить вид штриховки компонента Shape:
Shape1.Brush.Style:=bsSolid; //сплошная заливка
Brush.Style
Стиль заливки
bsCross
Клеточки
bsDiagCross
Сеточка
Создайте обработчик события onChange для компонента SpinEdit. Внесите
в него следующий код:
Shape1.Pen.Width:=SpinEdit1.Value;
Создайте обработчик события OnClick для кнопки «Выбор цвета»:
if ColorDialog1.Execute then Shape1.Brush.Color:= ColorDialog1.Color;
Создайте обработчик события onClick для CheckBox:
Button1.Enabled:=CheckBox1.Checked;
92
Примерный внешний вид окна программы во время ее работы приведен на
рисунке ниже.
Проверьте работу программы, составьте комментарии и объясните
преподавателю, как она работает.
Рис.4
Вопросы:
1) Самостоятельно изучить компоненты TrackBar и ScrollBar.
2) Изучить свойства и события компонента.
Составте таблицы
Свойство
Описание
Метод
(события)
Описание
93
Задание 4. Создать программу, с помощью которой пользователь
мог бы увидеть в зависимости от значений насыщенности красного, зеленого
и синего результирующий цвет. Для изменения значения выбираемых цветов
использовать или TrackBar или ScrollBar (min=0, max=255). Для изменения
цвета
использовать
функцию
RGB,
например
panel1.Color:=TcolorRef(rgb(ScrollBar1.position,0,0));
следующим
образом:
94
Урок 11. Контейнеры
Панели общего назначения —Panel, Splitter, GroupBox, ScrollBox,
PageScroller
С помощью Panel компонуются различные элементы интерфейса,
функционально связанные друг с другом. Внешний вид панели Panel
определяется совокупностью параметров:
BevelInner — стиль внутренней части панели,
BevelOuter — стиль внешней части панели,
BevelWidth — ширина внешней части панели,
BorderStyle — стиль бордюра,
BorderWidth — ширина бордюра.
Компонент Splitter
Свойство MinSize компонента Splitter устанавливает минимальный
размер в пикселях обеих панелей, между которыми зажат разделитель.
Задание такого минимального размера необходимо, чтобы при перемещениях
границы панель не сжалась бы до нулевого размера или до такой величины,
при которой на ней исчезли бы какие-то необходимые для работы элементы
управления. Компонент Splitter имеет событие OnMoved, которое наступает
после конца перемещения границы. В обработчике этого события можно
предусмотреть, если необходимо, упорядочение размещения компонентов на
панелях, размеры которых изменились: переместить какие-то метки,
изменить размеры компонентов и т.д.
ScrollBox — панель с прокруткой (на стр.Additional)
95
Этот компонент предназначен для создания области, в которой могут
размещаться компоненты, занимающие площадь большую, чем сам
ScrollBox.
Свойство
AutoScroll
позволяет
задать
автоматическое
появление
необходимых полос прокрутки, если размер размещенных компонентов
превышает размер области по горизонтали, вертикали или в обоих
измерениях.
PageScroller (на стр.Win32)
Предназначен для прокрутки одного компонента, который может являться
контейнером и содержать в себе другие компоненты. Направление прокрутки
задается свойством Orientation, которое может иметь два значения:

soHorizontal –прокрутка в горизонтальном направлении;

soVertical – прокрутка в вертикальном направлении.
Компонент часто используется совместно с панелями инструментов,
которые обычно имют фиксированную ширину или высоту, т.е. не требуют
перемещения видимой области во всех направлениях.
МНОГОСТРАНИЧНЫЕ ПАНЕЛИ
Компонент PageControl (на стр.Win32).
Чтобы задавать и редактировать страницы этого компонента, надо
щелкнуть на нем правой кнопкой мыши. Во всплывшем меню вы можете
видеть команды:
New Page — создать новую страницу,
Next Page — переключиться на следующую страницу,
Previous Page — переключиться на предыдущую страницу.
Каждая создаваемая вами страница является объектом типа TTabSheet.
Это панель, на которой можно размещать любые компоненты, окна
96
редактирования и т.п. После того, как вы создадите несколько страниц,
выделите одну из них, щелкнув в ее середине, и посмотрите ее свойства в
Инспекторе Объектов.
Свойства страницы TabSheet
Name
Caption
PageIndex
ImageIndex
Имя, по которому можно ссылаться на страницу
Надпись,
которая
появляется
на
ярлычке
закладки
Индекс страницы, по которому можно ссылаться
на страницу
Индекс изображения, которое может появляться
на ярлычке закладки
Свойства компонента PageControl
Определяет стиль отображения компонента:
tsTabs — закладки,
tsButtons — кнопки,
Style
tsFlatButtons — плоские кнопки.
Определяет, будут ли закладки размещаться в
несколько рядов, если все они не помещаются в
MultiLine
один ряд
Определяет
место
закладок:
tpBottom — внизу,
tpLeft — слева,
TabPosition
tpRight — справа
расположения
ярлычков
97
tpTop — вверху компонента
Высота и ширина ярлычков закладок в пикселях.
Если значения этих параметров заданы равными 0,
TabHeight и TabWi то размеры ярлычков определяются автоматически
по размерам надписей на них
dth
Ссылка
содержит
на
компонент
список
ImageList,
изображений
на
который
ярлычках.
Свойства ImageIndex страниц содержат индексы,
соответствующие именно этому списку.
Images
Имя активной страницы
ActivePage
Основные события компонента:
происходит
непосредственно
перед
переключением на другую страницу после щелчка
пользователя на новой закладке. При этом в
OnChanging
обработчик события передается по ссылке параметр
AllowChange — разрешение переключения.
Если в обработчике задать AllowChange = false,
то переключение не произойдет.
происходит сразу после переключения
OnChange
Вопросы Ответьте на вопросы:
1) Для чего используют компонент Panel?
2) Для чего предназначен компонент ScrollBox?
3) Как
задать
автоматическое
компоненте ScrollBox?
появление
полос
прокрутки
в
98
4) Какой компонент предназначен для прокрутки одного компонента,
который может являться контейнером и содержать в себе другие
компоненты?
5) Как
выбрать
свойства
некоторой
страницы
компонента
PageControl?
6) Какие основные события присущи компоненту PageControl?
Задание 1. Создать форму, содержащую три панели, которые
располагаются так, как показано на рисунке ниже. При изменении
пользователем размеров окна панель Panel1 должна в любом случае занимать
всю нижнюю часть окна, не увеличиваясь в высоту. Панель Panel2 должна
занимать левую часть окна, изменяя при изменении размеров окна свою
высоту, но, не изменяя ширину. А панель Panel3 должна занимать всю
оставшуюся часть окна. Кроме того надо обеспечить пользователю
возможность изменять положение границы между панелями Panel2 и Panel3,
расширяя одну из этих панелей и соответственно сжимая другую.
Исходя из требований свойство Align надо установить у панели Panel1 в
alBottom, у панели Panel2 — в аlLeft, у панели Panel3 — в alClient. А между
Panel2 и Panel3 надо разместить Splitter — разделитель.
А)
Б)
Рис. 1.
99
Ход решения:
1. Разместите на форме панель Panel1 и задайте у нее Align = alBottom.
2. Разместите на форме панель Panel2 и задайте у нее Align = alLeft.
3. Разместите на форме разделитель Splitter и задайте у него Align = alLeft
(впрочем, это значение Align установлено по умолчанию). Разделитель
прижмется к правой стороне панели Panel2, которая уже выровнена в ту же
сторону. Разделитель всегда надо выравнивать только после выравнивания
соответствующей панели, так как иначе он прижмется просто к краю формы.
4. После этого можно разместить на форме панель Panel3 и задать у нее
Align = alClient. Разделитель окажется зажатым между Panel2 и Panel3.
5. Откомпилируйте приложение, запустите его на выполнение и
убедитесь, что, потянув курсором мыши за границу раздела между панелями,
вы можете перемещать эту границу (рис. Б).
Задание 2. Установить на форму компонент ScrollBox. На него
установить шесть компонентов CheckBox (рис.2). Уменьшить компонент
ScrollBox так, чтобы было видно только три компонента CheckBox.
Рис. 2
Задание 3. Установите в приложении компоненты PageControl и
TabControl (на стр.Win32). Создайте закладки в компоненте PageControl.
100
Для создания закладок у компонента TabControl необходимо в свойстве
Tabs компонента ввести столько строк, сколько требуется закладок (каждая
строка – заголовок закладки). Создайте несколько закладок в компоненте
TabControl.
Поставьте на первой странице каждого компонента по кнопке (рис.3).
Запустите приложение, пощелкайте по закладкам компонентов.
Ответьте на вопрос: в чем отличие этих двух компонентов?
Рис.3
Задание 4. Установите на форму компонент PageControl и
размножьте его в трех экземплярах на форме. Для каждого из четырех
компонентов PageControl выполните следующие настройки (рис.4).
101
Рис 4.
102
Урок 12. Инструментальные панели
Инструментальные панели - компонент ToolBar
Занесение компонентов на панель ToolBar можно осуществлять обычным
способом — переносом их из палитры компонентов. Но для занесения
кнопок имеется и более простой вариант.
Свойства кнопок ToolButton
Изображения для компонента ToolBar хранятся в компоненте ImageList.
Указание на этот компонент может задаваться такими свойствами
компонента ToolBar, как Images, DisabledImages (указывает на список
изображений кнопок в недоступном состоянии) и HotImages (указывает на
список изображений кнопок в моменты, когда над ними перемещается
курсор мыши). У кнопки необходимо указать индекс изображения в свойстве
ImageIndex.
Вид и поведение созданных кнопок определяется свойством Style.
Значения свойства:
Свойство
tbsButton
Описание
кнопка. И как кнопка этот объект очень похож на
кнопку SpeedButton.
кнопка, которая после щелчка пользователя остается в
нажатом состоянии. Повторный щелчок на кнопке
tbsCheck
возвращает ее в отжатое состояние. Поведение такой
кнопки определяется свойствами AllowAllUp и Down.
Если при этом в нескольких кнопках установлено
свойство Grouped=true, то эти кнопки образуют группу,
103
из которой только одна кнопка может находиться в
нажатом состоянии.
кнопка в виде выпадающего списка. Этот стиль удобен
для воспроизведения выпадающего меню. Если для
подобной кнопки задать в качестве свойства MenuItem
головной раздел меню, то в выпадающем списке
автоматически будут появляться разделы выпадающего
меню. На рисунке ниже стиль tbsDropDown имеет
четвертая
слева
DropDownMenu,
tbsDropDown
кнопка.
Можно
определяющее
задать
свойство
контекстное
меню
(компонент PopupMenu), которое будет отображаться в
выпадающем списке.
tbsSeparator
tbsDivider
разделитель, позволяющий отделить друг от друга
кнопки разных функциональных групп
Разделитель в виде вертикальной линии.
Свойство Wrap, установленное в true, приводит к тому, что после этой
кнопки ряд кнопок на панели прерывается, и следующие кнопки
размещаются в следующем ряду. Свойство кнопки Indeterminate задает ее
третье состояние — не нажатая и не отпущенная. Это свойство можно
устанавливать в true во время выполнения, если в данном режиме кнопка не
доступна.
104
Свойство Marked выделяет кнопку.
Свойства компонента ToolBar
ButtonHeight и ButtonWidth — высота и ширина кнопок в пикселях.
Wrapable — автоматический перенос кнопок в следующий ряд панели, если
они не помещаются в предыдущем.
BorderWidth — ширина бордюра,
EdgeInner и EdgeOuter — стиль изображения внутренней и внешней
части панели (утопленный или выступающий),
EdgeBorders — определяет изображение отдельных сторон панели
(левой, правой, верхней, нижней).
Перестраиваемые панели
Компонент CoolBar.
Он позволяет строить перестраиваемые панели, состоящие из полос
(bands). В полосы могут включаться инструментальные панели ToolBar и
любые другие оконные компоненты: окна редактирования, панели и т.п.
Каждый из этих компонентов автоматически снабжается средствами
перемещения его пользователем в пределах окна CoolBar.
Создание перестраиваемой полосы в CoolBar
1. Вызвать редактор полос
1 способ: из Инспектора Объектов кнопкой с многоточием около
свойства Bands,
105
2 способ: двойным щелчком на компоненте CoolBar,
3 способ: из контекстного меню, выбрав команду Bands Editor.
2. В окне этого редактора вы можете перемещаться по полосам,
добавлять
новые
полосы
(кнопка
AddNew)
или
уничтожать
существующие (кнопка Delete Selected).
3. При выделении полосы в объектном инспекторе отображаются ее
свойства.
Свойства полосы:
- Control определяет размещенный на полосе компонент.
-Break определяет, занимает ли полоса весь соответствующий
размер контейнера CoolBar, или обрывается.
-
Text
задает
текст,
который
может
появиться
в
начале
соответствующей полосы.
- ImageIndex — изображение в начале полосы (индекс картинки из
ImageList)
- MinHeight и MinWidth определяют минимальную высоту и
ширину полосы при перестроениях пользователем полос панели.
- FixedSize определяет, фиксирован ли размер данной полосы или он
может изменяться пользователем.
По умолчанию для всех полос FixedSize = false, т.е. все полосы
перестраиваются. Но при желании размеры некоторых полос можно
зафиксировать, задав для них FixedSize = true.
106
Вопросы:
1) В каком компоненте хранятся изображения для ToolBar?
2) Какие существуют варианты организации поведения кнопок на
панели ToolBar?
3) Как организовать кнопку в ToolBar в виде выпадающего списка?
4) Как разместить кнопки в несколько рядов в компоненте ToolBar?
5) Какой компонент позволяет строить перестраиваемые панели,
состоящие из полос?
6) Как создать перестраиваемые полосы CoolBar?
Задание 1. Установите на форму компонент ToolBar, щелкните по
нему правой кнопкой мыши и выберите из всплывшего меню команду New
Button. На панели появится очередная кнопка — объект типа TToolButton.
Создайте несколько таких кнопок.
Задание 2. Создать панель инструментов (рис.1). Кнопки со
стрелочками должны быть зависимыми переключателями – если нажата
одна, остальные должны быть отжаты. Поместите на форму CoolBar.
Перенесите на него два ToolBar и два Edit (рис.1).
Панели инструментов ToolBar настройте как на рисунке (по 4 кнопки с
заданными картинками).
107
Рис 1.
Пиктограммы для кнопок:
1. Установите на форму компонент ImageList (на стр.Win32)
2. Щелкните двойным щелчком по компоненту и в открывшемся окне
нажмите кнопку Add. В окне добавления файлов найдите папку C:/Program
Files/Common files/ Borland Shared/Images/Buttons.
3. В этой папке выберите подходящие файлы и нажмите кнопку Открыть.
4. В результате в компонент добавятся выбранные вами картинки.
5. Для того, чтобы пиктограммы появились на кнопках, необходимо
настроить свойство Images компонента ToolBar на компонент ImageList1.
6. Затем необходимо в каждой кнопке задать нужную картинку с
помощью свойства ImageIndex.
7. Запустите программу. Около каждого компонента появляется слева
полоска, за которую компонент можно перемещать. Взявшись за эту полоску,
попробуйте переместить полосу вместе с ее компонентом в тот ряд, где уже
имеется другой компонент. Тогда они расположатся в ряд один левее
другого.
Задание 3. Поместите на форму компонент ControlBar и
перенесите на него несколько компонентов, например, инструментальных
панелей ToolBar и окон редактирования Edit. Каждый компонент, попадая
на ControlBar,
получает
полосу
захвата,
свойственную
технологии
Drag&Doc. Установите у компонентов, размещенных на ControlBar,
108
свойство DragMode=dmAutomatic и DragKind=dkDock. Это означает
автоматическое выполнение операций Drag&Doc.
Рис 2.
Запустите
приложение
и
посмотрите
на
практике
возможности
перестроения панелей.
А если вы установите свойство AutoDrag в true, то вы сможете
вытаскивать
из
панели
самостоятельными окнами.
отдельные
компоненты,
и
они
становятся
109
Урок 13. Формы
Управление формами
С точки зрения пользователя форма — это окно, в котором он работает с
приложением. Каждой новой форме, вводимой в приложение, соответствует
свой модуль (unit), описывающий эту форму как класс и включающий, если
необходимо, какие-то дополнительные константы, переменные, функции и
процедуры. Рассмотрим некоторые свойства, методы и события, присущие
формам.
По умолчанию все формы создаются автоматически при запуске
приложения, и первая из введенных в приложение форм считается главной.
Главная форма

Ей передается управление в начале выполнения приложения.

закрытие
пользователем
главной
формы
означает
завершение
выполнения приложения.

Она может быть спроектирована невидимой, но если все остальные
формы закрыты, то главная форма становится в любом случае видимой
(иначе пользователь не смог бы продолжать работать с приложением и даже
не смог бы его завершить).
Главной в приложении может быть не та форма, которая была
спроектирована первой.
Не стоит также в общем случае все формы делать создаваемыми
автоматически. В приложении могут быть предусмотрены формы (например,
формы для установки различных опций), которые требуются далеко не в
каждом
сеансе
работы
с
приложением.
Было
бы
варварским
расточительством создавать на всякий случай такие формы автоматически
при каждом запуске приложения и занимать под них память.
110
В момент создания формы возникает событие OnCreate. Обработка этого
события широко используется для настройки каких-то компонентов формы,
создания списков и т.д.
В нужный момент форму можно сделать видимой методами Show или
ShowModal. Их можно применять только к невидимой в данный момент
форме. Если нет уверенности, что форма в данный момент видима, то
прежде, чем применять эти методы, следует проверить свойство Visible
формы. Например:
if (not Form2.Visible) then Form2.ShowModal;
При выполнении методов Show или ShowModal возникает событие
формы onShow. Это событие возникает до того момента, как форма
действительно станет видимой. Поэтому обработку события onShow можно
использовать для настройки каких-то компонентов открываемой формы.
Отличие от упомянутой ранее настройки компонентов в момент события
onCreate заключается в том, что событие onCreate наступает для каждой
формы только один раз в момент ее создания, а события onShow наступают
каждый раз, когда форма делается видимой. Так что при этом в настройке
можно использовать какую-то оперативную информацию, возникающую в
процессе выполнения приложения. Методом Hide форму в любой момент
можно сделать невидимой. В этот момент в ней возникает событие onHide.
Закрытие формы
Закрыть форму можно методом Close. При этом в закрывающейся форме
возникает последовательность событий, которые можно обрабатывать. Их
назначение — проверить возможность закрытия формы и указать, что
именно подразумевается под закрытием формы. Проверка возможности
закрытия формы необходима, например, для того, чтобы проанализировать,
сохранил ли пользователь документ, с которым он работал в данной форме и
который изменял. Если не сохранил, приложение должно спросить его о
111
необходимости сохранения и, в зависимости от ответа пользователя,
сохранить документ, закрыть приложение без сохранения или вообще
отменить закрытие. Рассмотрим последовательность событий, возникающих
при выполнении метода Close.
Первым возникает событие onCloseQuery. В его обработчик передается
булева переменная CanClose, определяющая, должно ли продолжаться
закрытие формы. По умолчанию CanClose равно true,что означает
продолжение закрытия. Но если из анализа текущего состояния приложения
или из ответа пользователя на запрос о закрытии формы следует, что
закрывать ее не надо, параметруCanClose должно быть присвоено значение
false. Тогда последующих событий, связанных с закрытием формы не будет.
Если обработчик события onCloseQuery отсутствует или если в его
обработчике сохранено значение true параметра CanClose, то следом
наступает событие OnClose. В обработчик этого события передается
переменная Action, которой можно задавать значения:

сaNone- не закрывать форму. Это позволяет и в обработчике данного
события еще отказаться от закрытия формы.

caHide -при этом значении закрыть форму будет означать сделать ее
невидимой. Для пользователя она исчезнет с экрана, однако вся хранящаяся в
форме информация сохранится.

caMinimize - при этом значении закрыть форму будет означать
свернуть ее до пиктограммы. Как и в предыдущем случае, вся информация в
форме будет сохранена.

сaFree - при этом значении закрыть форму будет означать
уничтожение формы и освобождение занимаемой ею памяти. Если эта форма
в дальнейшем потребуется еще раз, ее надо будет создавать методом
CreateForm.
112
Свойства формы
Свойство
Описание
Возможные значения:
bsSizeable (по
умолчанию)
-
обычное
окно
с
изменяемыми размерами, имеющее стандартную строку
заголовка.
bsDialog - диалоговое окно, которое не изменяет свои
размеры (нет кнопок свернуть и развернуть).
BorderStyle
bsSingle - форму, которая не может изменять размеры
во время работы.
bsSizeToolWin - окно может изменять размеры и не
имеет кнопок biMinimize, biMaximize HbiHelp.
bsToolWindow – аналогично bsSizeToolWin, но не
позволяет изменять размеры
bsNone - окно без рамки и заголовка
KeyPreview
=
False,
тогда
события
клавиатуры
пересылаются только тому управляющему элементу,
KeyPreview
который имеет фокус ввода.
KeyPreview
=
True,
тогда
событие
сначала
пересылается форме, а затем — управляющему элементу,
имеющему фокус ввода.
Определяет
размещение
формы
при
запуске
приложения.
Position
poDesigned - форма выводиться в месте, определенном
при разработке приложения.
poScreenCenter - форма выводится в центре экрана.
poDefault -
Windows
автоматически
установит
113
размеры и положение формы.
poDefaultPosOnly
- автоматически
определяет
расположение формы, но не ее размеры.
poDefaultSizeOnly - автоматически определяет размер,
но не расположение формы.
определяет состояние окна— свернутое, развернутое
WindowState
или нормальное.
Возможные
значения:
wsNormal,
wsMinimize,
wsMaximize
События формы:
Выполняется при изменении размера формы во время
OnResize
выполнения приложения. Обычно здесь помещается код
для изменения размера и положения на экране элементов
управления, не поддерживающих свойство Align.
Выполняется при получении формой фокуса ввода.
OnActivate
OnActivate вызывается только при переходе фокуса ввода
от одной формы к другой в пределах одного приложения.
Выполняется когда необходимо перерисовать форму.
OnPaint
Это может происходить, когда форма только что стала
видимой, при частичном удалении перекрывающих ее
элементов или увеличении размеров.
Выполняется
OnDestroy
перед
уничтожением
формы.
Используется для освобождения ресурсов, выделенных в
OnCreate.
Модальные формы
114
Открытие форм как модальных используется в большинстве диалоговых
окон. Модальная форма приостанавливает выполнение вызвавшей ее
процедуры до тех пор, пока пользователь не закроет эту форму. Модальная
форма не позволяет также пользователю переключить фокус курсором мыши
на другие формы данного приложения, пока форма не будет закрыта.
Модальной может быть сделана любая форма, если она делается видимой
методом ShowModal. Поведение модальной формы определяется ее
основным
свойством
ModalResult.
При
открытии
формы
методом
ShowModal сначала свойство ModalResult=0.
Как только при обработке каких-то событий на форме свойству
ModalResult будет присвоено положительное значение, модальная форма
закроется. А значение ее свойства ModalResult можно будет прочитать как
результат, возвращаемый методом ShowModal. Таким образом программа,
вызвавшая модальную форму, может узнать, что сделал пользователь,
работая с этой формой, например, на какой кнопке он щелкнул.
Численное
значение
Константа
Пояснение
ModalResult
0
1
mrNone
mrOk
или
idOK
закрытие модальной формы нажатием
кнопки ОК
закрытие модальной формы нажатием
2
mrCancel
кнопки Cancel или методом Close, или
или idCancel
нажатием кнопки системного меню в
полосе заголовка окна
6
mrYes или
idYes
закрытие модальной формы нажатием
кнопки Yes
115
7
mrNo
idNo
или
закрытие модальной формы нажатием
кнопки No
Требуемые значения ModalResult можно задавать в обработчиках
соответствующих событий в компонентах модальной формы. Однако при
использовании кнопок можно обойтись и без подобных обработчиков. Дело в
том, что кнопки типа TButton и TBitBtn имеют свойство ModalResult, по
умолчанию равное mrNone. Для кнопок, расположенных на модальной
форме, значение этого свойства можно изменить и тогда не потребуется
вводить каких-либо обработчиков событий при щелчке на них. В кнопках
BitBtn при свойстве Kind, не равном bkCustom, заложены по умолчанию
значения ModalResult, соответствующие назначению той или иной кнопки.
MDI-интерфейс (многодокументный интерфейс)
В приложении MDI имеется родительская (первичная) форма и ряд
дочерних форм (называемых также формами документов). Окна документов
могут создаваться самим пользователем в процессе выполнения приложения
с помощью команд типа Окно | Новое. Число дочерних окон заранее
неизвестно — пользователь может создать их столько, сколько ему
потребуется. Окна документов располагаются в клиентской области
родительской формы. Поэтому чаще всего целесообразно в родительской
форме ограничиваться только главным меню, инструментальными панелями
и, если необходимо, панелью состояния, оставляя все остальное место в окне
для окон дочерних форм. При этом обычно окно родительской формы в
исходном состоянии разворачивают на весь экран.
Рассмотрим теперь, как можно сделать обработчик команды, по которой
пользователь задает в родительском окне создание нового окна документов
— нового экземпляра дочерней формы. Этот обработчик может иметь вид:
var <имя> : <имя класса дочерней формы>;
116
begin
<имя>:=<имя класса дочерней формы>.Create(Application);
<операторы настройки, если они нужны>
<имя>.Show;
end;
Переменная, объявленная в этой процедуре, используется для создания
произвольного временного имени (указателя) вновь создаваемого объекта —
формы. Первый из выполняемых операторов процедуры создает этот объект.
Далее могут следовать какие-то операторы настройки нового дочернего окна.
Например, новому окну надо присвоить какой-то уникальный заголовок
(свойство Caption дочерней формы), чтобы пользователь мог отличать друг
от друга окна документов это безусловное требование к приложениям MDI
Windows. Последний оператор процедуры делает видимым вновь созданное
окно.
Управление дочерними окнами
В родительской форме имеется ряд свойств, позволяющих управлять
дочерними окнами. Все они доступны только для чтения и только во время
выполнения.
Свойство MDIChildCount определяет количество открытых дочерних
окон.
Свойство MDIChildren[i: integer] дает доступ к i-му окну (окна
индексируются в порядке их создания).
Вопросы:
1) Что представляет собой пользовательская форма?
2) Перечислите признаки главной формы.
3) Какое событие возникает в момент создания формы?
117
4) Какое событие можно использовать для настройки каких-то
компонентов открываемой формы?
5) В чем отличие событий onCreate и onShow?
6) Опишите
последовательность
событий,
возникающих
при
выполнении метода Close.
7) Для чего используют модальную форму?
8) Как сделать форму модальной?
9) Как закрыть модальную форму нажатием кнопки No?
10)
Что представляет собой приложение MDI?
11)
С помощью каких свойств можно управлять дочерними
формами?
Задание 1. Создайте новое приложение и установите RichEdit.
Создайте обработчик события формы onCloseQuery и внесите следующий
код:
if RichEdit1.Modified then
if MessageDlg('Документ не сохранен. Вы действительно хотите
завершить
работу?',
mtConfirmation,
[mbOk,mbNo],0)=mrNo
then
CanClose:=False;
Если пользователь в диалоговом окне с запросом о сохранении ответит
Нет, то CanClose будет равно false и окно не закроется. Причем этот
обработчик сработает при любой попытке пользователя закрыть приложение:
нажатии в нем кнопки или раздела меню Выход, нажатии кнопки системного
меню в полосе заголовка окна и т.п.
Задание 2. Создайте новое приложение. Установите у формы
свойство FormStyle = fsMDIForm (это будет родительская форма). Свойство
Caption='Родительская форма'.
118
Создайте новую форму (она будет дочерней), свойство FormStyle =
fsMDIChild. Свойство Caption=’Окно'. Свойство Name=FDoc.
Сохраните приложение и запустите на выполнение. Как ведет себя
дочерняя форма?
Поскольку дочерние окна будет создавать сам пользователь в процессе
выполнения приложения, дочернюю форму необходимо исключить из числа
создаваемых автоматически.
Задание 3. Откройте файл проекта командой Project- View Source.
Удалите строку
Application.CreateForm(TFDoc, FDoc);
Этим
вы
исключите
дочернюю
форму
из
числа
создаваемых
автоматически.
Задание 4. Установите на родительскую форму панель ToolBar, и
на
ней
создайте
кнопку
«Новое
окно»
(у
ToolBar
свойство
ShowCaptions=True).
Свяжите две формы, для этого выделите родительскую форму и
выполните команду File-Use Unit… в открывшемся окне выберите второй
модуль.
Создайте обработчик для кнопки «Новое окно», и добавьте в него
следующий код:
var NewF : TFDoc;
begin
NewF:=TFDoc.Create(Application);
NewF.Show;
end;
119
Запустите программу и нажмите на кнопку «Новое окно». Что
произошло? Объясните код программы.
Задание 5. Добавьте в обработчик, созданный вами ранее, перед
строчкой NewF.Show; следующую строку, для задания уникального имени
вновь созданного окна NewF:
NewF.Caption :='Окно ' + IntToStr(MDIChildCount);
Задание 6. Создайте в родительской форме кнопку «Свернуть все окна».
В обработчик нажатия введите код:
Var I: Integer;
begin
with Form1 do
for I:=MDIChildCount-1 downto 0 do MDIChildren[I].Close;
end;
Добавьте еще и кнопку «Восстановить все окна».
Var I: Integer;
begin
for I:=0 to MDIChildCount-1 do
MDIChildren[I].WindowState:=wsNormal;
end;
120
Урок14. Невизуальные компоненты
Невизуальные
компоненты
представляют
собой,
как
правило,
компоненты, с помощью которых осуществляется доступ к системным
ресурсам. Они отображаются только во время конструирования интерфейса,
но не видны во время работы приложения. Примером таких компонентов
служит компонент Timer. Кроме него к невизуальным компонентам относят
диалоговые компоненты и компоненты-меню.
Диалоговые компоненты
В Win32 диалоговым окном называется окно стандартного размера без
кнопок максимизации и минимизации. Диалоговые окна позволяют
управлять различными режимами работы программы и сообщать ей
необходимую информацию. Диалоговое окно может пересылать сообщения,
задавать вопросы и принимать ответы.
Выделяют два вида диалоговых окон — модальные и немодальные.
Модальные диалоговые окна сохраняют фокус ввода до закрытия окна.
Немодальные диалоговые окна позволяют переключаться в другие окна без
закрытия данного окна. Диалоговые компоненты расположены в панели
компонентов на странице Dialogs.
Основные правила использования диалоговых панелей
Работа со стандартными диалоговыми окнами осуществляется в три этапа.
1 этап:
на форму помещается соответствующий компонент и
осуществляется настройка его свойств
2 этап: осуществляется вызов стандартного для диалоговых компонентов
метода Execute, который отображает соответствующее диалоговое окно.
Вызов этого метода обычно располагается внутри обработчика какого-либо
события
121
Например, мы хотим, чтобы при нажатии на кнопку на экране появилось
диалоговое окно сохранения файла. Для этого в обработчик события нажатия
кнопки необходимо внести следующий оператор:
If SaveDialog1.Execute Then ...
Только после обращения к методу Execute на экране появляется
соответствующее диалоговое окно. Стандартное окно диалога является
модальным окном, поэтому сразу после обращения к Execute дальнейшее
выполнение программы приостанавливается до тех пор, пока пользователь не
закроет окно.
Метод Execute является логической функцией, которая возвращает
значение True, если результат диалога с пользователем был успешным.
Проанализировав результат выполнения метода Execute, программа может
выполнить третий этап.
3 этап: использование введенных с помощью диалогового окна данных
— имени файла, настроек принтера, выбранного шрифта и т. д.
Компоненты OpenDialog и SaveDialog
Компонент OpenDialog позволяет выбрать открываемый файл по
заданному шаблону.
Компонент SaveDialog используется для выбора имени файла, в котором
будет сохраняться информация.
Свойства компонентов:
Свойство
FileName
DefaultExt
Описание
содержит маршрут поиска и выбранный файл при
успешном завершении диалога.
определяет расширение файла по умолчанию: если при
задании имени файла пользователь не указал расширение, то
122
к имени файла будет добавлена разделительная точка и
значение этого свойства.
используется для выбора файлов, отображаемых в
диалоговом
окне.
Для
определения
фильтра
можно
воспользоваться редактором свойства. Свойство можно
устанавливать с помощью специального редактора или
Filter
программно
OpenDialog1.Filter:
='Текстовые
файлы|*.txt|
Файлы
Паскаля|*.pas;*.dpr|;
Символы «|» служат для разделения фильтров друг от
друга, а также для разделения описания фильтруемых
файлов от соответствующей маски выбора.
FilterIndex
указывает, какой из заданных шаблонов отображается в
списке. По умолчанию значение этого свойства равно 1;
задает название каталога, содержимое которого будет
InitialDir
отображаться при вызове диалогового окна. Если значение
этого свойства не задано, то отображается содержимое
текущего каталога;
Title
задает текст заголовка диалогового окна;
Компонент FontDialog
Компонент FontDialog используется для вызова стандартного диалогового
окна выбора шрифтов и их характеристик
Свойства:
Device позволяет указать тип устройства, для которого выбираются
шрифты: fdScreen — экран.
fdPrinter — принтер.
fdBoth — шрифты, поддерживаемые и экраном, и принтером.
123
MinFontSize, MaxFontSize - этими свойствами определяется диапазон
возможных значений размеров шрифтов. Значения этих свойств задаются в
пунктах (1 пункт равен 1/72 дюйма, что приблизительно равно 0.36 мм). Если
свойства содержат 0, то ограничения на размер шрифта отсутствуют.
Font содержит результат выбора шрифта.
Для того чтобы изменить шрифт компонента на значение, установленное в
диалоговом окне, необходимо определить обработчик сообщения OnApply
компонента FontDialog.
Компонент ColorDialog
Компонент ColorDialog используется для вызова диалогового окна
настройки цветов.
Color содержит выбранный цвет.
CustomColors содержит до 16 цветов, определенных пользователем.
Каждая строка имеет такой формат: ColorX=HHHHHH, где X — буква от А
до Р, определяющая номер цвета, НННННН — шестнадцатеричное
представление цвета в формате RGB.
Options задает значения опций, определяющих настройку окна:
Значение
cdFullOpen
cdPreventFullOpen
Описание (при установленном значении True)
показывать с развернутым окном выбора цвета
пользователя
запретить показ окна выбора цвета пользователем
cdShowHelp
включить в окно кнопку Справка
cdSolidColor
выбирать ближайший сплошной цвет
cdAnyColor
разрешить выбор несплошных цветов
124
Компоненты FindDialog и ReplaceDialog
Компонент FindDialog используется для отображения стандартного
диалогового окна, предназначенного для ввода искомой информации.
Компоненты имеют следующие основные свойства:
Свойство
Описание
Текст, заданный пользователем для поиска или замены.
FindText
Программно может быть установлен как начальное значение,
предлагаемое пользователю
ReplaceText
Только в компоненте ReplaceDialog — текст, который
должен заменять FindText
Сами по себе компоненты FindDialog и ReplaceDialog не осуществляют
ни поиска, ни замены. Они только обеспечивают интерфейс с пользователем.
А поиск и замену надо осуществлять программно. Для этого можно
пользоваться событием OnFind, происходящим, когда пользователь нажал в
диалоге кнопку Найти далее, и событием OnReplace, возникающим, если
пользователь нажал кнопку Заменить или Заменить все. В событии
OnReplace узнать, какую именно кнопку нажал пользователь, можно по
значениям флагов frReplace и frReplaceAll.
Компонент OpenPictureDialog
Компонент OpenPictureDialog является потомком класса TOpenDialog и
предназначен для выбора графических изображений с возможностью их
просмотра.
Компонент
OpenPictureDialog
поддерживает
изображения в следующих форматах (BMP, ICO, WMF, EMF).
Компонент SavePictureDialog
графические
125
Компонент SavePictureDialog является «потомком» класса TSaveDialog и
предназначен для сохранения графических изображений с возможностью их
предварительного просмотра в одном из форматов, поддерживаемых классом
TPicture.
Вопросы:
1) Для чего нужны невизуальные компоненты?
2) Какие компоненты относят к невизуальным?
3) Опишите действия модальных диалоговых окон.
4) Опишите основные правила использования диалоговых панелей.
5) Перечислите диалоговые компоненты и опишите их назначение.
(таблица)
Задание 1. Создайте приложение, которое использует компонент
ColorDialog для изменения цвета формы.
Ход работы.
Поместите на форму компоненты ColorDialog и Button (измените
значения свойства Caption на «Изменить цвет). Для кнопки создайте
обработчик события onСlick и внесите в него следующий код:
Запустите программу и нажмите на кнопку. На экране появится окно.
126
Задание 2. Измените в программе из задания 1 свойства
компонента ColorDialog1 так, чтобы на экран выводилось диалоговое окно в
следующем виде:
Задание 3. Организовать поиск текста в компоненте RichEdit.
Ход решения:
127
Установите компонент Memo1 и кнопку «Поиск».
Создайте следующий обработчик события нажатия кнопки «Поиск» и
объявите глобальную переменную SPos.
128
Создайте обработчик события onFind для компонента FindDialog.
Запустите программу. Введите несколько строчек текста (так, чтобы
встречались одинаковые слова). Затем выделите одно из повторяющихся
слов и нажмите кнопку Поиск.
Пояснение кода программы:
Поиск заданного фрагмента легко проводить, пользуясь функцией Object
Pascal Pos, которая определена в модуле System следующим образом:
Function Pos(Substr: string; S: string): Byte;где S — строка, в которой
ищется фрагмент текста, a Substr — искомый фрагмент. Функция
возвращает позицию первого символа первого вхождения искомого
фрагмента в строку. Если Substr в S не найден, возвращается 0.
Для организации поиска нам потребуется еще две функции: Сору и
AnsiLowerCase. Первая из них определена как:
Function Copy(S: string; Index, Count: Integer): string;
129
Она возвращает фрагмент строки S, начинающийся с позиции Index и
содержащий число символов, не превышающее Count.
Функция AnsiLowerCase, определенная как
function AnsiLowerCase(const S: string): string;
возвращает строку символов S, переведенную в нижний регистр
В программе вводится переменная SPos, сохраняющая позицию, начиная с
которой надо проводить поиск.
Процедура MFindClick вызывает диалог, процедура FindDialog1Find
обеспечивает поиск с учетом или без учета регистра в зависимости от
флага frMatchCase. После нахождения очередного вхождения искомого
текста этот текст выделяется в окне Memo1 и управление передается этому
окну редактирования. Затем при нажатии пользователем в диалоговом окне
кнопки Найти далее, поиск продолжается в оставшейся части текста. Если
искомый текст не найден, делается запрос пользователю о продолжении
диалога. Если пользователь не ответил на этот запрос положительно, то
диалог закрывается методом CloseDialog.
130
Урок 15. Главное и контекстное меню
Главное меню — компонент MainMenu
Это невизуальный компонент, т.е. место его размещения на форме в
процессе проектирования не имеет никакого значения для пользователя — он
все равно увидит не сам компонент, а только меню, сгенерированное им.
Дизайнер меню
Вызов дизайнера меню осуществляется двойным щелчком по компоненту
MainMenu.
Рис.1. Дизайнер меню.
Дизайнер меню работает в паре с окном свойств. Создание и удаление
пунктов осуществляется в дизайнере меню, а свойства отдельно взятого
пункта устанавливаются в окне свойств.
131
В компоненте MainMenu существует свойство AutoHotKeys. Если оно
установлено
в
значение
maAutomatic,
то
подбор
горячих
клавиш
выполняется автоматически.
Внимание! Не пытайтесь удалить пустой пункт, завершающий список
команд - у вас ничего не выйдет. Да это и не требуется, поскольку пустые
висячие пункты не отображаются в меню во время работы программы.
Для создания полноценного меню нужны средства вставки и удаления
пунктов, создания вложенных меню и прочие. Поэтому в дизайнере меню
для каждого отдельно взятого пункта предусмотрено контекстное меню с
необходимым набором команд (рисунок 2 и таблица).
Рис. 2. Контекстные команды в дизайнере меню
Команда
Описание
Insert
Вставляет новый пункт.
Delete
Удаляет выбранный пункт.
Create Submenu
Создает в позиции пункта подчиненное меню.
Создание пункта меню
132
Установить курсор в синюю рамку из точек, обозначающую место
расположения нового раздела. Далее в объектном инспекторе необходимо
задать заголовок меню (свойство Caption) и нажать клавишу Enter.
Вставка пункта меню
Если вы предварительно выделите какой-то раздел меню и выберите из
контекстного меню команду Insert, то рамка нового раздела вставится перед
выделенным ранее.
Создание подменю
Из
контекстного
меню
выполнить
команду
Create
Submenu,
позволяющую ввести подменю в выделенный раздел (см. подменю раздела
Опции на рисунке).
Перемещение пунктов меню
Захватите пункт меню щелчком левой кнопки мыши и, удерживая
нажатой кнопку мыши, отбуксируйте его к новой позиции. Таким образом,
можно переместить не только отдельный пункт, но и целое подчиненное
меню со всеми его пунктами и вложенными меню.
Пункты меню
Нетрудно догадаться, что пункты меню, как и все элементы интерфейса,
являются компонентами. Класс пункта меню называется TMenuItem, самые
характерные его свойства обозначены в таблице.
133
Свойство
Описание свойства
Caption
надпись раздела.
имя объекта, соответствующего разделу меню. Очень
Name
полезно давать этим объектам осмысленные имена, так как
иначе вы скоро запутаетесь в ничего не говорящих именах,
типа N21. Куда понятнее имена MFile, MOpen, MSave и т.п.
клавиши быстрого доступа к разделу меню — «горячие»
Shortcut
клавиши, с помощью которых пользователь, даже не заходя в
меню, может в любой момент вызвать выполнение процедуры,
связанной с данным разделом.
определяет, является ли данный раздел разделом по
Default
умолчанию своего подменю, т.е. разделом, выполняемым при
двойном щелчке пользователя на родительском разделе.
используется в длинных меню, чтобы разбить список
разделов на несколько столбцов. Возможные значение Break:
mbNone — отсутствие разбиения меню (это значение принято
по умолчанию),
mbBarBreak и mbBreak — в меню вводится новый столбец
разделов, отделенный от предыдущего полосой (mbBarBreak)
или пробелами (mbBreak). На рис 3. показан пример, в
Break
котором в разделе 1-3 установлено значение Break = mbBreak,
а в разделе 1-5 — Break = mbBarBreak
Рисунок 3. Меню из нескольких столбцов
134
установленное в true, указывает, что в разделе меню будет
отображаться маркер флажка, показывающий, что данный
раздел выбран. Правда, сам по себе этот маркер не изменяется
Checked
и в обработчик события OnClick такого раздела надо вставлять
оператор типа
MAutoSave.Checked := not MAutoSave.Checked;
(в приведенном операторе подразумевается, что раздел
меню назван MAutoSave).
Это свойство, установленное в true, определяет, что данный
раздел должен работать в режиме радиокнопки совместно с
другими разделами, имеющими то же значение свойства
GroupIndex. По умолчанию значение GroupIndex равно 0. Но
можно задать его большим нуля и тогда, если имеется
RadioItem
несколько разделов с одинаковым значением GroupIndex и
сRadioItem = true, то в них могут появляться маркеры
флажков, причем только в одном из них (на рис.свойство
RadioItem установлено в true в разделах Шаблон 1 и Шаблон
2, имеющих одинаковое значение GroupIndex).
Управлять
переключениемы
радиокнопок
придется
с
помощью программного кода.
Bitmap
Изображение из указанного вами файла в пункте меню
индекс изображения, хранящегося во внешнем компоненте
ImageList. Указание на этот компонент вы можете задать в
ImageIndex
свойстве Images компонента MainMenu. Индексы начинаются
с 0. Если вы укажете индекс -1 (значение по умолчанию),
изображения не будет.
135
По аналогии с остальными классами компонентов можно было бы
предположить, что в палитре компонентов существует компонент MenuItem.
Однако его там нет, поскольку пункты меню не существуют сами по себе, а
работают только в составе строки главного меню или окна контекстного
меню. Тем не менее, они во многом ведут себя как настоящие компоненты,
например, настраиваются в окне свойств и наряду с остальными
компонентами помещаются в исходный текст формы в виде отдельных
полей. Чтобы в этом убедиться, активизируйте редактор кода и найдите
определение класса формы. Оно будет таким, как на рисунке 4.
Рис. 4. Редактор кода.
Разделительные линии
136
Логически связанные между собой команды принято отделять от других
команд горизонтальной линией. Например, пункт Exit хорошо бы отделить
от остальных.
Комбинации клавиш
Некоторым пунктам меню назначают комбинации клавиш (shortcut),
чтобы выполнять команды, не открывая меню. Они ускоряют работу с
приложением и популярны среди опытных пользователей. Названия
комбинаций клавиш отображаются справа от текста соответствующих
пунктов. Например, во многих программах команде меню File / Open...
назначается комбинация клавиш Ctrl+O.
Контекстное всплывающее меню — компонент PopupMenu
Контекстное меню привязано к конкретным компонентам. Оно всплывает,
если во время, когда данный компонент в фокусе, пользователь щелкнет
правой кнопкой мыши. Поскольку в приложении может быть несколько
контекстных меню, то и компонентов PopupMenu может быть несколько.
Оконные компоненты: панели, окна редактирования, а также метки и др.
имеют свойство PopupMenu, которое по умолчанию пусто, но куда можно
поместить имя того компонента PopupMenu, с которым будет связан данный
компонент.
Формирование контекстного всплывающего меню производится с
помощью
Конструктора
Меню,
вызываемого
двойным
PopupMenu, точно так же, как это делалось для главного меню.
Вопросы:
щелчком
на
137
1) Где необходимо помещать главное меню при конструировании
формы?
2) Как конструируется главное меню?
3) Как создать подменю?
4) Как сделать разделительную горизонтальную и вертикальную
полосы между пунктами меню?
5) Как назначить комбинацию клавиш для пункта меню?
6) Для чего применяется контекстное меню?
7) Как создать контекстное меню?
Задание 1. Установите на форму компонент MainMenu. Вызовите
дизайнер меню. Щелкните по рамке с точками в дизайнере меню. Перейдите
в объектный инспектор и в свойстве Caption введите заголовок пункта меню
File.
Задание 2. Сейчас под пунктом File нужно создать подчиненное
меню со списком команд. Для этого просто щелкните в дизайнере меню на
пункте File. Под пунктом File появится пустая ячейка - заготовка первого
пункта выпадающего списка. Выберите этот пункт с помощью мыши и
138
задайте ему в свойстве Caption заголовок Open... . Вместо пустой ячейки
появится текст Open... и пустая ячейка переместится ниже. Действуя по
аналогии, добавьте еще три пункта: Save As... , Close и Exit.
Задание 3. Создать разделитель перед пунктом меню Exit. Для
этого щелкните правой кнопкой мыши по пункту Exit и в открывшемся меню
выберите Insert. В свойстве Caption укажите символ минуса (-).
Рис 5. Разделительная линия в меню
Задание 4. Выделите пункт Open в дизайнере меню, в объектном
инспекторе выберите в списке значений свойства ShortCut требуемую
комбинацию клавиш (рисунок).
139
Задание 5. Создайте пункты меню, показанные на рисунке 1.
Картинки для меню взять из папки C:/Program Files/Common Files/Borland
Shared/Images/Buttons
Задание 6. Создать программу с использованием главного и
контекстного меню (рис.6 и 7). При выборе из любого пункта меню
соответствующего названия рисунка, изображение на форме должно
изменяться. Картинки подобрать самостоятельно.
Для загрузки картинки используется следующий оператор:
Image1.Picture.LoadFromFile(ExpandFileName('имя_файла.bmp'));
140
Рис. 6. Меню
Рис. 7. Контекстное меню
141
Урок 16 Класс Exception. Стандартные классы исключений. Операторы
обработки исключений.
Исключительная ситуация как класс
Исключительная ситуация это такая ситуация, в результате которой
генерируется ошибка, и выполнение программы прерывается. Например,
деление на ноль - классический пример исключительной ситуации.
Как в такой ситуации действует человек? Если он пытается что-то
сделать, и это не получается - он идёт другим путём. Так же и компьютер,
следующий программе, умеющей обрабатывать исключительные ситуации.
Он
не
бросает
выполнение
программы,
не
виснет,
а
обходит
исключительную ситуацию, выполняя альтернативный вариант фрагмента, в
которой исключительная ситуация возникла.
Возникает вопрос, почему бы не поставить проверку, например, на
равенство нулю знаменателя при делении? Можно и поставить. Но во многих
случаях источник исключительной ситуации далеко не так очевиден, а на все
случаи жизни проверки не введёшь.
Итак, для контроля исключительных ситуаций программист должен
подготовить как основной вариант фрагмента, где возможна исключительная
ситуация, так и его вариант, в котором она заведомо невозможна, или
выводится информационное сообщение для пользователя.
Под
исключительной
ситуацией
мы
будем
понимать
некое
непредвиденное событие, способное повлиять на дальнейшее выполнение
программы.
При обработке такой ситуации Delphi, как обычно, работает с объектами.
С точки зрения компилятора Delphi исключительная ситуация - это объект.
Чем же различаются между собой исключительные ситуации? Как
отличить одну исключительную ситуацию от другой? Поскольку это
объекты,
они
отличаются
классом
(объектным
типом).
В
модуле
142
SYSUTILS.PAS описан объектный тип Exception. Он является предком для
всех других объектов — исключительных ситуаций.
Тип
Exception
порождает
многочисленные
дочерние
типы,
соответствующие часто встречающимся случаям ошибок ввода/вывода,
распределения памяти и т.п.
Исключительные
Тип
ситуации
искл.
ситуации
Условие возникновения
Недостаточно места в куче
EOutOfMemory
при
работе
с
памятью
EOutOfResources
(памяти)
Нехватка системных ресурсов
Недопустимый
EInvalidPointer
указатель
(обычно nil)
Попытка деления на ноль
EDivByZero
Число
целочисленной
выходит
математики
ERangeError
математики
(целое число)
с
плавающей точкой
или
за
выражение
допустимый
диапазон
EIntOverflow
Целочисленное переполнение
EInvalidOp
Неверная операция
EZeroDivide
Попытка деления на ноль
Переполнение с плавающей
EOverflow
EUnderflow
точкой
Исчезновение порядка
Неверный
аргумент
EInvalidArgument математических функций
143
Защитные конструкции
Для работы
с объектами
исключительных
ситуаций существуют
специальные конструкции языка Object Pascal — блоки try .. except и try ..
finally. Они контролируют выполнение операторов, помещенных внутри
блока до ключевого слова except или finally. В случае возникновения
исключительной
ситуации
штатное
выполнение
вашей
программы
немедленно прекращается, и управление передается операторам, идущим за
указанными ключевыми словами. Хотя синтаксис двух видов блоков похож,
но они принципиально отличаются назначением и решаемыми задачами.
Блок Try..Except
Вот как выглядит оператор контроля исключительных ситуаций:
try
{исполняемый код};
except
on Exception1 do {код, исполняемый в случае возникновения ошибки 1};
on Exception2 do {код, исполняемый в случае возникновения ошибки 2};
else
{код, обработчик всех не перехваченных ранее ошибок};
end;
Если при выполнении кода, размещенного в разделе try, генерируется
исключение, то выполнение этого раздела прекращается и управление
передается коду, размещенному в разделе except.
Раздел except может использоваться двумя способами.

Во-первых, в нем могут располагаться любые операторы, кроме
обработчиков исключений, начинающихся с приставки on. Это и операторы
сообщения об ошибке, и команды, позволяющие освобождать системные
ресурсы, а также другие операторы и команды.
144
Во-вторых, раздел except используется для обработки исключений. В

этом случае в него могут включаться только операторы обработки
исключений.
Если
среди
обработчиков
встретился
обработчик,
соответствующий сгенерированному исключению, то выполняется оператор
этого обработчика, исключение разрушается и управление передается коду,
расположенному после оператора on Exception do.
Раздел, расположенный после ключевого слова else, служит для обработки
любых исключений, не описанных в разделе except. Этот раздел не является
обязательным. Если при обработке исключительной ситуации не будет
найден подходящий обработчик, то произойдет обработка системным
обработчиком исключений.
Пример:
обработка исключительной ситуации деления на ноль.
а:=10;
b:=0;
try
c:=a/b;
except
on EZeroDivide do MessageBox('Делить на ноль нельзя!');
end;
Оператор on..do
Данный оператор находится внутри раздела except и может иметь две
формы.
on <класс исключения> do <оператор>;
или
on <имя>: <класс исключения>do <операторы, в которых можно
использовать свойства исключения>
Например:
145
on EZeroDivide do MessageBox('Делить на ноль нельзя!');
Этот оператор обрабатывает только тот класс исключений, который в нем
указан. При указании родительского (базового) класса, все классы
исключений - потомки данного класса - также будут обработаны. Для
обработки всех исключений можно обратиться к базовому классу всех
исключений: Exception. После обработки исключения оно разрушается.
Вторая форма оператора on .. do отличается от первой тем, что данному
исключению можно временно присвоить имя и обращаться к свойствам
исключения. Обращаться к свойствам исключения можно с помощью
конструкции <имя>.<имя свойства>.
Пример:
обращения к свойствам исключения.
try
ScrollBar1.Max := ScrollBar1.Min - 1;
except
on E: EInvalidOperation do
MessageDlg( 'Игнорируем исключение: '- + E.Message, mtInformation,
[mbOK], O)
end;
В приведенном примере мы присваиваем исключению EInvalidOperation
временное имя Е. Затем в окне сообщения выводим текст ошибки E.Message,
выдаваемый Delphi по умолчанию.
Команда Raise – регенерация исключений
Иногда, бывает необходимо, чтобы после обработки исключительной
ситуации своим кодом вызывался стандартный обработчик ошибки.
Например, в случае возникновения некоторой ошибки вы хотите, чтобы
приложение сообщало пользователю какую-либо информацию, а затем
передавало управление стандартному обработчику ошибок. Как вы уже
146
знаете,
после
уничтожается.
обработки
Для
того
исключения
чтобы
вашим
самостоятельно
кодом,
вызвать
исключение
снова
это
исключение, можно воспользоваться регенерацией исключений. Для
регенерации исключения служит команда raise.
try
{ операторы }
except
on <класс исключения> do
begin
{операторы обработки исключения}
raise; // Регенерация исключения
end;
end;
После выполнения операторов обработки исключения, написанных
программистом, выполняется команда raise, которая снова принудительно
вызывает это исключение, после чего управление передается стандартному
обработчику исключений.
Блок Try…Finally
Следующая конструкция try .. finally служит для защиты кода, записанного в
разделе finally от исключительных ситуаций, которые в силу каких-либо
причин могут происходить в разделе try.
try
{операторы, способные создать исключительную ситуацию};
finally
{защищенные операторы, выполняемые в любом случае};
end;
Итак, операторы, которые размещены после ключевого слова
finally,
будут выполняться в любом случае, была сгенерирована исключительная
147
ситуация или нет. Если в разделе try была сгенерирована исключительная
ситуация, то управление немедленно передается разделу finally. Также, если
исключительной ситуации в разделе, try не было, блок finally будет
выполняться. Даже если в разделе finally произойдет ошибка, выполнение
операторов этого раздела будет продолжено до конца.
В конструкции try .. finally не происходит обработка исключений, она
используется в основном для освобождения ресурсов памяти, закрытия
ненужных файлов и других операций освобождения ресурсов. Таким
образом, в данной конструкции нуждаются операции с файлами, памятью,
ресурсами Windows и объектами.
Вложенные исключительные ситуации
148
Молчаливые исключения
При разработке приложений на Delphi часто возникают ситуации, когда
программисту не требуется обрабатывать исключения, а необходимо лишь
прервать
нежелательное
действие,
вызывающее
ошибку.
Для
этого
применяются так называемые молчаливые исключения. Молчаливые
исключения являются потомками стандартного исключения EAbort.
ИС EAbort отличается тем, что для нее обработка по умолчанию не
предусматривает вывода сообщений на экран.
Для того чтобы сгенерировать молчаливое исключение, можно вызвать
процедуру Abort. Она автоматически сгенерирует исключение EAbort,
которое прервет текущую операцию без вывода сведения об ошибке на
экран.
Рассмотрим пример. Пусть форма содержит пустой список (ListBox1) и
кнопку (Button1). Запишем в обработчик события кнопки onclick следующий
код:
procedure TForm1.Button1Click(Sender: TObject);
var I: Integer;
begin
for I := 1 to 10 do (цикл 10 раз}
begin
ListBox1.Items.Add(IntToStr(I)); {добавляем номер в список}
if I = 7 then Abort; {прерываем добавление номеров в список после
добавления седьмого}
end;
end;
В результате работы программы, после нажатия кнопки Button1, в список
будет добавлено семь строк с номерами от 1 до 7.
149
Настройка Delphi – отключение реагирования на исключительные
ситуации
При работе программы под управлением Delphi, система будет сама
реагировать на исключительные ситуации, мешая работе операторов
обработки исключений. Чтобы проверить их действие, можно запускать
программу непосредственно из папки (exe-файл). Или можно отключить
реакцию системы на исключительные ситуации, тем самым давая
возможность отработать специально для этого написанным фрагментам
программы - нашим операторам try/except/end. Для этого откроем пункт
системного меню Delphi Tools -> Debugger Options.... В появившемся
окошке нужно снять галку в чекбоксе Stop on Delphi Exceptions,
расположенном на вкладке Language Exceptions. Теперь система Delphi
будет
предоставлять
вашей
программе
возможность
самостоятельно
обрабатывать исключительные ситуации, среди которых могут быть и
ситуации, возникновение которых прописано специально как удобный
инструмент достижения необходимых результатов.
Вопросы:
1) Что называют исключительной ситуацией?
2) Какие исключительные ситуации предусмотрены?
3) Какие существуют специальные конструкции языка Object Pascal
для работы с объектами исключительных ситуаций ?
4) Как работает блок Try…Excert?
5) Как работает оператор on … do?
6) Сколько форм имеет оператор on…do? В чем их отличее7
7) Для чего используется блок Try…Finaly?
8) Что называют молчаливыми исключениями?
150
Задание
1.
Разработать
приложение,
обрабатывающее
исключительную ситуацию.
Ход работы: Создайте форму с пятью полями редактирования и пятью
соответствующими надписями, которые поясняют, какой вид проверки
осуществляет соответствующий компонент Edit. Форма также содержит
кнопку для проверки содержимого первого поля редактирования.
Событие OnClick кнопки должно проверять целочисленность введенного в
первое поле значения, например:
Var Number, Code : Integer ;
begin
if Edit1.Text <> ‘ ’ then
begin
val(Edit1.Text, Number, Code);
if Code <> 0 then
begin
Edit1.SetFocus;
MessageDlg (‘Not a number in the first edit ‘ , mtError, [mbOK], 0);
end;
end;
end;
При выходе из компонента Edit2 (событие OnExit) осуществляется
аналогичная проверка.
Var Number, Code : Integer ;
begin
if (Sender as TEdit ). Text <> ‘ ’ then
begin
val ((Sender as TEdit ). Text, Number, Code) ;
if Code <> 0 then
151
begin
(Sender as TEdit ).SetFocus ;
MessageDlg (‘The edit field number ‘ + IntToStr((Sender as TEdit
).Tag) +‘ does not have a valid number’, mtError, [mbOK], 0) ;
end;
end;
end;
Текст сообщения об ошибке может варьироваться.
Третий компонент Edit выполняет аналогичную проверку при каждом
изменении его содержимого (используя событие OnChange)/ Записать код
для события события OnKeyPress компонента Edit4 и проверить, не является
ли введенный символ числом или клавишей Backspace (которая имеет
числовое значение 8).
begin
if not ( key in [ ‘0’ . . ‘9’ , # 8] ) then
begin
Key := # 0 ;
MessageBeep ($ FFFFFFFF) ;
end;
end;
Для события OnEnter компонента Edit5 записать код, в котором
необходимо преобразовать введенные символы в число с помощью функции
StrToInt. Использовать исключение для обработки ошибки EConvertError.
Задание 2. Написать программу, которая демонстрирует обработку
исключений при помощи инструкции try…except.
152
153
Урок 17 Отображение графики на канве Canvas
Канва Canvas не является компонентом. Но поскольку многие
компоненты, в частности формы, имеют канву. Канва предоставляет
возможность выводить различную графическую информацию, то некоторые
начальные сведения о канве все-таки целесообразно знать.
Канва представляет собой область компонента, на которой можно
рисовать или отображать готовые изображения. Она содержит свойства и
методы,
существенно
упрощающие
графику
Delphi.
Все
сложные
взаимодействия с системой спрятаны для пользователя, так что рисовать в
Delphi может человек, совершенно не искушенный в машинной графике.
Каждая точка канвы имеет координаты X и Y. Система координат
канвы, как и везде в Delphi, имеет началом левый верхний угол канвы.
Координата X возрастает при перемещении слева направо, а координата Y —
при перемещении сверху вниз. Координаты измеряются в пикселях. Пиксель
— это наименьший элемент поверхности рисунка, с которым можно
манипулировать. Важнейшее свойство пикселя — его цвет.
Канва имеет свойство Pixels. Это свойство представляет собой
двумерный
массив,
который
отвечает
за
цвета
канвы.
Например,
Canvas.Pixels[10,20] соответствует цвету пикселя, 10-го слева и 20-го сверху.
С массивом пикселей можно обращаться как с любым свойством: изменять
цвет, задавая пикселю новое значение, или определять его цвет по
хранящемуся в нем значению. Например, Canvas.Pixels[10,20] := 0 или
Canvas.Pixels[10,20] := clBlack — это задание пикселю черного цвета.
Свойство Pixels можно использовать для рисования на канве.
Канва — объект класса TCanvas имеет множество методов, которые
позволяют рисовать графики, линии, фигуры с помощью свойства Pen —
перо. Это свойство является объектом, в свою очередь имеющим ряд свойств.
Одно из них уже известное вам свойство Color — цвет, которым наносится
154
рисунок. Второе свойство — Width (ширина линии). Ширина задается в
пикселях. По умолчанию ширина равна 1.
Свойство Style определяет вид линии. Это свойство может принимать
следующие значения:
psSolid
Сплошная линия
psDash
Штриховая линия
psDot
Пунктирная линия
psDashDot Штрих-пунктирная линия
psDashDotDot
psClear
Линия, чередующая штрих и два пунктира
Отсутствие линии
psInsideFrame
Сплошная линия, но при Width > 1 допускающая цвета,
отличные от палитры Windows
У канвы имеется свойство PenPos типа TPoint. Это свойство
определяет в координатах канвы текущую позицию пера. Перемещение пера
без прорисовки линии, т.е. изменение PenPos, производится методом канвы
MoveTo(X,Y). Здесь (X, Y) — координаты точки, в которую перемещается
перо. Эта текущая точка становится исходной, от которой методом
LineTo(X,Y) можно провести линию в точку с координатами (X,Y). При этом
текущая точка перемещается в конечную точку линии, и новый вызов LineTo
будет проводить точку из этой новой текущей точки. Перо может рисовать не
только прямые линии, но и фигуры. Полный список методов канвы,
использующих перо, смотрите во встроенной справке Delphi
Фигуры в общем случае рисуются не пустыми, а закрашенными с
помощью свойства канвы Brush — кисть. Свойство Brush является
объектом, имеющим в свою очередь ряд свойств. Свойство Color определяет
цвет
заполнения.
Свойство
Style
определяет
шаблон
заполнения
(штриховку). По умолчанию значение Style равно bsSolid, что означает
сплошное закрашивание цветом Color.
155
У пера Pen имеется еще одно свойство. Это свойство — Mode (режим).
По умолчанию значение Mode = pmCopy. Это означает, что линии
проводятся цветом, заданным в свойстве Color. Но возможны и другие
режимы, в которых учитывается не только цвет Color, но и цвет
соответствующих пикселей фона. Наиболее интересным из этих режимов
является
режим pmNotXor
—
сложение
с
фоном по
инверсному
исключающему ИЛИ. Если задан этот режим, то повторное рисование той же
фигуры на том же месте канвы убирает ранее нарисованное изображение и
восстанавливает цвета пикселей, которые были до первого изображения
фигуры.
Эту особенность режима pmNotXor можно использовать для создания
простенькой анимации. Достаточно нарисовать нечто, затем стереть
нарисованное, перерисовать немного измененным — и рисунок будет
представляться ожившим.
На канве можно отображать не только программно создаваемые
изображения, но и изображения, хранящиеся в графических файлах. Только
сама канва не имеет метода загрузки изображения из файла. Поэтому
загружать файл надо в какой-нибудь другой графический объект, способный
воспринимать информацию графических файлов. А затем переписывать
изображение из этого объекта на канву с помощью метода канвы Draw. Его
описание:
procedure Draw(X, Y: Integer; Graphic: TGraphic);
Здесь параметры Х и Y определяют координаты левого верхнего угла
размещения изображения на канве, a Graphic — объект, хранящий
информацию. В качестве такого объекта может выступать, например, объект
типа TBitMap, предназначенный для хранения битовых матриц.
Если окно какого-то другого приложения перекрывает на время окно
вашего приложения, то изображение, нарисованное на канве формы,
портится.
156
а) Изображение на канве
б) при перекрытии другим окном
Устранить этот недостаток можно используя метод копирования
CopyRect:
procedure CopyRect(Dest: TRect; Canvas: TCanvas; Source: TRect);
Метод копирует указанную параметром Source область изображения в
канве источника изображения Canvas в указанную параметром Dest область
данной канвы. Тип TRect, характеризующий прямоугольные области Source и
Dest. Например, оператор
Canvas.CopyRect(MyRect2, Bitmap.Canvas, MyRect1); - копирует на канву
формы в область MyRect2 изображение из области MyRect1 канвы
компонента Bitmap.
Копирование
методом
CopyRect
производится
в
режиме,
установленном свойством CopyMode. По умолчанию это свойство имеет
значение
cmSrcCopy,
что
означает
просто
замену
изображения,
содержащегося ранее в области Dest, на копируемое изображение.
Компоненты Image и PaintBox
Компоненты
Image
и
PaintBox
представляют
собой
некоторую
ограниченную поверхность с канвой, на которую можно заносить
изображения. При этом компонент PaintBox, собственно говоря, не дает
ничего нового по сравнению с рисованием на канве формы. Рисование на
157
PaintBox вместо формы не имеет никаких преимуществ, кроме, может быть,
некоторого облегчения в расположении одного или нескольких рисунков в
площади окна.
Компонент Image на много богаче по своим возможностям и удобнее, чем
PaintBox. Компонент Image имеет существенное преимущество: в нем не
приходится думать о перерисовке изображения, испорченного из-за
перекрытия данного окна другими. Все, связанное с обработкой событий
OnPaint в Image осуществляется автоматически. Кроме того с помощью
Image проще, чем при непосредственном рисовании на канве формы,
расположить в окне приложения несколько изображений и управлять ими.
При этом отпадает необходимость сложных и нудных расчетов координат
канвы
формы,
обеспечивающих
требуемое
взаимное
расположение
изображений, т.е. в полной мере проявляются преимущества визуального
программирования. Так что, вероятно, во всех случаях лучше работать с
канвой Image, чем с канвой формы. Но помимо этих возможностей у
компонента Image имеются свойства, позволяющие работать с различными
типами графических файлов.
Delphi поддерживает три типа файлов — битовые матрицы, пиктограммы
и метафайлы. Все три типа файлов хранят изображения; различие
заключается лишь в способе их хранения внутри файлов и в средствах
доступа к ним.
Битовая матрица (файл с расширением .bmp) отображает цвет каждого
пикселя в изображении. При этом информация хранится таким образом, что
любой
компьютер
может
отобразить
изображение
с
разрешающей
способностью и количеством цветов, соответствующим его конфигурации.
Пиктограммы (файлы с расширением .ico) — это маленькие битовые
матрицы.
Они
повсеместно
используются
для
обозначения
значков
приложений, в быстрых кнопках, в пунктах меню, в различных списках.
Способ хранения изображений в пиктограммах
схож с хранением
информации в битовых матрицах, но имеются и различия. В частности,
158
пиктограмму невозможно масштабировать, она сохраняет тот размер, в
котором была создана.
Метафайлы (Metafiles) хранят не последовательность битов, из которых
состоит изображение, а информацию о способе создания картинки. Они
хранят последовательности команд рисования, которые и могут быть
повторены при воссоздании изображения. Это делает такие файлы, как
правило, более компактными, чем битовые матрицы.
Компонент Image позволяет отображать информацию, содержащуюся в
графических файлах всех указанных типов. Для этого служит его свойство
Picture — объект типа TPicture.
Рис. 4.3 Окно "Picture Editor"
Если установить свойство AutoSize в true, то размер компонента Image
будет автоматически подгоняться под размер помещенной в него картинки.
Если же свойство AutoSize установлено в false, то изображение может не
поместиться в компонент или, наоборот, площадь компонента может
оказаться много больше площади изображения.
159
Другое свойство — Stretch позволяет подгонять не компонент под
размер рисунка, а рисунок под размер компонента. Установите AutoSize в
false, растяните или сожмите размер компонента Image и установите Stretch в
true. Рисунок займет всю площадь компонента, но поскольку вряд ли реально
установить размеры Image точно пропорциональными размеру рисунка, то
изображение будет искажаться. Устанавливать Stretch в true может иметь
смысл только для каких-то узоров, но не для картинок. Свойство Stretch не
действует на изображения пиктограмм, которые не могут изменять своих
размеров.
Свойство — Center, установленное в true, центрирует изображение на
площади Image, если размер компонента больше размера рисунка.
Рассмотрим еще одно свойство — Transparent (прозрачность). Если
Transparent равно true, то изображение в Image становится прозрачным. Это
можно использовать для наложения изображений друг на друга. Одно из
возможных применений этого свойства — наложение на картинку надписей,
выполненных в виде битовой матрицы. Эти надписи можно сделать с
помощью встроенной в Delphi программы "Image Editor". Свойство
Transparent действует только на битовые матрицы. При этом прозрачным (т.е.
заменяемым на цвет расположенного под ним изображения) делается по
умолчанию цвет левого нижнего пикселя битовой матрицы.
Свойство Picture позволяет также легко организовать обмен с
графическими файлами любых типов в процессе выполнения приложения.
Чтоб пояснить технику такого обмена, надо сначала подробнее рассмотреть
свойство Picture.
Это свойство является объектом, который имеет в свою очередь
подсвойства, указывающие, на хранящийся графический объект. Если в
Picture хранится битовая матрица, на нее указывает свойство Picture.Bitmap.
Если хранится пиктограмма, на нее указывает свойство Picture.Icon. На
хранящийся метафайл указывает свойство Picture.Metafile. Наконец, на
графический объект произвольного типа указывает свойство Picture.Graphic.
160
Объект Picture и его свойства Bitmap, Icon, Metafile и Graphic имеют
методы файлового чтения и записи LoadFromFile и SaveToFile:
procedure LoadFromFile(const FileName: string);
procedure SaveToFile(const FileName: string);
Для свойств Picture.Bitmap, Picture.Icon и Picture.Metafile формат файла
должен соответствовать классу объекта: битовой матрице, пиктограмме,
метафайлу. При чтении файла в свойство Picture.Graphiс файл должен иметь
формат метафайла. А для самого объекта Picture методы чтения и записи
автоматически подстраиваются под тип файла.Если будут открываться
только файлы битовых матриц, то оператор загрузки файла можно заменить
на
Image1.Picture.Bitmap.LoadFromFile(OpenPictureDialog1.FileName);
Для пиктограмм можно было бы использовать оператор
Image1.Picture.Icon.LoadFromFile(OpenPictureDialog1.FileName);
а для метафайлов — оператор
Image1.Picture.Metafile.LoadFromFile(OpenPictureDialog1.FileName);
или
Image1.Picture.Graphic.LoadFromFile(OpenPictureDialog1.FileName) ;
Но во всех этих случаях, если формат файла не совпадет с
предполагаемым,
возникнет
ошибка.
Аналогично
работает
и
метод
SaveToFile с тем отличием, что примененный к Picture или к Picture.Graphic
он сохраняет в файле изображение любого формата.
Абсолютно идентично для изображений любого формата будет
работать программа, если оператор сохранения вы замените на
Image1.Picture.Graphic.SaveToFile(SavePictrureDialog1.FileName);
использующий свойство Picture.Graphic. А если вам известен формат
хранимого в компоненте Image изображения, то вы можете применить метод
SaveToFile к свойствам Picture.Bitmap, Picture.Icon и Picture.Metafile.
Для всех рассмотренных объектов Picture, Picture.Bitmap, Picture.Icon и
Picture.Metafile определены методы присваивания значений объектов:
161
procedure Assign(Source: TPersistent);
Однако, для BitMap, Icon и Metafile присваивать можно только
значения
однородных
объектов:
соответственно
битовых
матриц,
пиктограмм, метафайлов. При попытке присвоить значения разнородных
объектов генерируется исключение ЕConvertError. Объект Picture —
универсальный, ему можно присваивать значения объектов любых из
остальных трех классов. А значение Picture можно присваивать только тому
объекту, тип которого совпадает с типом объекта, хранящегося в нем.
При загрузке разных изображений размер окна приложения может
оказаться или слишком маленьким, и тогда вы увидите только часть
изображения, или слишком большим, и тогда изображение будет некрасиво
размещено в левом верхнем углу формы, оставляя много пустого
пространства. Этот недостаток можно устранить, если воспользоваться
свойствами Height (высота) и Width (ширина) компонента Image. При
свойстве AutoSize установленном в true размеры Image автоматически
устанавливаются равными размерам загруженного изображения. И этими
размерами
можно
воспользоваться
для
соответствующего
изменения
размеров формы.
Вопросы:
1. Что представляет собой канва?
2. Нарисуйте систему координат Delphi?
3. Как переместить перо без прорисовки линии?
4. Для чего можно использовать значение pmNotXor свойства Mode?
5. Чем отличаются компоненты Image и PaintBox?
6. Какие типы файлов поддерживает Delphi и опишите их?
7. Какое свойство позволяет подгонять не компонент под размер рисунка,
а рисунок под размер компонента?
162
Задание 1 Нарисовать по пикселям график синусоиды (рис1) на канве
формы. Для этого в обработчик события формы OnPaint (прорисовка) нужно
вставить следующий код:
procedure TForm1.FormPaint(Sender: TObject);
var
X,Y: real;
// координаты функции
PX,PY: longint; // координаты пикселей
begin
Color := clWhite;
for PX := 0 to ClientWidth do
begin
{X — аргумент графика, соответствующий пикселю с координатой РХ}
X := PX*4*Pi/ClientWidth;
Y:=Sin(X);
{PY — координата пикселя,соответствующая координате Y}
PY:=trunc(ClientHeight - (Y+1)*ClientHeight/2);
{Устанавливается черный цвет выбранного пикселя}
Canvas.Pixels [PX, PY] := 0;
end;
end;
Рис. 1 График синусоиды, построенный по пикселям
163
Задание 2. Нарисовать пером график синуса из предыдущего примера
(рис2 ).
Рис. 2 График синусоиды, построенный по линиям
Как видите, качество графика существенно улучшилось.
Задание 3. Попробуйте сделать сами простенькую мультипликацию —
движущуюся
окружность.
Начните
новое
приложение
и
в
раздел
implementation вставьте объявление
var X,Y: integer;
Тем самым вы введете глобальные переменные X и Y — текущие
координаты изображения.
В событие формы OnPaint вставьте операторы
Canvas.Brush.Color := clWhite;
Color := clWhite;
Canvas.Pen.Mode := pmNotXor;
Первый из этих операторов задает белый цвет кисти Brush. Значит, ваша
окружность будет закрашена внутри белым цветом. Второй оператор задает
белый цвет фона поверхности формы. Третий оператор устанавливает режим
пера pmNotXor, который позволит вам стирать прежнее изображение прежде,
чем нарисовать новое.
164
Даже самая простая мультипликация нуждается в синхронизации. Иначе
скорость движения будет определяться быстродействием компьютера.
Поэтому перенесите на форму компонент Timer — таймер со страницы
"System". А пока задайте его свойство Interval равным, например, 30 (это
время выдержки в миллисекундах, но реальное время выдержки будет
больше) и установите свойство Enabled равным false (это означает, что
таймер не будет запускаться автоматически в момент запуска приложения).
В обработчик события этого компонента OnTimer вставьте операторы
// Стирание прежнего изображения
Canvas.Ellipse(Х-5, Y, X+5, Y-10);
Inc(X);
// Рисование нового изображения
Canvas.Ellipse(Х-5, Y, X+5, Y-10);
// Останов при достижении конца формы
if (X >= ClientWidth-20) then
Timer1.Enabled := false;
Первый из этих операторов рисует окружность в том месте, где она была
нарисована ранее, т.е. стирает прежнее изображение. Далее увеличивается на
единицу функцией Inc текущая координата X и изображение окружности
рисуется в новой позиции. Последний оператор останавливает изображение у
края формы.
Теперь перенесите на форму кнопку Button и в обработчик щелчка на ней
поместите операторы
Х:=10;
Y:=100;
Canvas.Ellipse(X-5, Y, X+5, Y-10);
Timer1.Enabled:=true;
165
Первые два оператора задают начальные координаты окружности. Третий
оператор рисует окружность в ее начальном положении, а четвертый —
запускает таймер.
Оттранслируйте приложение, запустите его на выполнение, щелкните на
кнопке. Вы увидите изображение окружности, перемещающееся по форме
слева направо.
Задание 4. Подключите вашу фантазию и преобразуйте приложение
из задания 4 во что-нибудь более увлекательное.
Задание 5. Откройте новое приложение, перенесите на форму
компонент OpenPictureDialog со страницы "Dialogs"
и кнопку «Файл».
Разместите OpenPictureDialog в любом месте формы, так как этот компонент
невизуальный, а кнопку разместите внизу формы. В обработчик щелчка на
кнопке занесите код:
procedure TForm1.Button1Click(Sender: TObject);
var
BitMap:TBitMap;
begin
// Выбор пользователем графического файла
if OpenPictureDialog1.Execute then
begin
// Создание объекта BitMap типа TBitMap
BitMap:=TBitMap.Create;
// Загрузка в BitMap выбранного графического файла
BitMap.LoadFromFile(OpenPictureDialog1.FileName);
// Перенос изображения на канву формы
Canvas.Draw(10, 10, BitMap);
166
// Уничтожение объекта BitMap
BitMap.Free;
end;
end;
Этот код создает временный объект типа TBitMap с именем BitMap.
Затем вызывается диалог открытия графического файла OpenPictureDialog1
и, если пользователь выбрал файл, то он загружается в BitMap методом
LoadFromFile. Затем методом Draw загруженное изображение копируется на
канву в область, с координатами левого верхнего угла (10, 10). После этого
временный объект BitMap уничтожается.
Запустите ваше приложение и щелкните на его кнопке. Вы увидите, что
можете загрузить любой графический файл типа .bmp и он отобразится на
канве формы.
167
Урок 18 Полоса состояния StatusBar
Строка состояния - это управляющий элемент, с помощью которого
пользователю выдается разного рода вспомогательная информация о ходе
выполнения приложения.
Компонент StatusBar представляет собой ряд панелей, отображающих
полосу состояния в стиле Windows. Обычно эта полоса размещается внизу
формы.
Свойство SimplePanel определяет, включает ли полоса состояния одну
или множество панелей. Если SimplePanel = true, то вся полоса состояния
представляет собой единственную панель, текст которой задается свойством
SimpleText. Если же SimplePanel = false, то полоса состояния является
набором панелей, задаваемых свойством Panels. В этом случае свойство
SizeGrip определяет, может ли пользователь изменять размеры панелей в
процессе выполнения приложения.
Каждая
TStatusPanels.
панель
полосы
состояния
Свойства панелей
вы
является
объектом
типа
можете задавать специальным
редактором наборов. Вызвать редактор можно тремя способами: из
Инспектора Объектов кнопкой с многоточием около свойства Panels,
двойным щелчком на компоненте StatusBar или из контекстного меню,
выбрав команду Panels Editor. В окне редактора вы можете перемещаться по
панелям, добавлять новые или уничтожать существующие. При перемещении
по панелям в окне Инспектора Объектов вы будете видеть их свойства.
Основное свойство каждой панели — Text, в который заносится
отображаемый
в
панели
текст.
Его
можно
занести
в
процессе
проектирования, а затем можно изменять программно во время выполнения.
Другое существенное свойство панели — Width (ширина).
Программный
доступ
к
текстам
отдельных
панелей
можно
осуществлять двумя способами: через индексированное свойство Panels или
168
через его индексированное подсвойство Items. Например, два следующих
оператора дадут идентичный результат:
StatusBar1.Panels[0].Text := 'текст 1';
или
StatusBar1.Panels.Items[0].Text := 'текст 1';
Оба они напечатают текст «текст 1» в первой панели.
Количество
панелей
полосы
состояния
можно
определить
из
подсвойства Count свойства Panels. Например, следующий оператор
очищает тексты всех панелей:
for i := 0 to StatusBar1.Panels.Count - 1 do
StatusBar1.Panels[i].Text := '';
Основные свойства
Свойство
Описание
Property AutoHint: Boolean;
AutoHint
Определяет автоматическое отображение в первой
панели полосы состояния вторых частей Hint
type TAlign=(alNone, alTop, alButton, alLeft, alRight
Align
alClient);
Property Align:TAlign;
Выравнивание полосы на форме
Property Canvas: TCanvas;
Canvas
Канва, позволяющая рисовать на панели в
обработчике
OnDrawPanel
Panels
SimplePanel
Property Panels: TStatusPanels;
Собрание панелей
Property SimplePanel: Boolean;
169
Отражает ли одну или несколько панелей на полосе
Состояния
SimleText
Property SimleText: string;
Текст на самой полосе
Property SizeGrip: Boolean;
SizeGrip
Определяет будет ли захват внизу справа, чтобы
Можно было менять размер формы
Из событий это OnDrawPanel и OnHint.
Первое это событие происходит если надо перерисовать панель состояния,
а второе – наступает перед тем, как в полосе состояния должна отображаться
подсказка.
Создание подсказки
Строка состояния — это еще стандартное место отображения подсказок к
пунктам меню. Когда вы активизируете меню, строка состояния, состоящая
из нескольких панелей, превращается в простую длинную панель и на ней
отображается подсказка текущего пункта меню. Когда вы завершаете работу
с меню (например, выбираете команду), строка состояния восстанавливает
свой первоначальный вид.
Для того чтобы вы могли получить строку состояния с описанной выше
логикой работы, в компоненте StatusBar предусмотрен режим отображения
простого текста. Его обеспечивает булевское свойство SimplePanel. По
умолчанию оно равно значению False и в строке состояния отображаются
панели объекта Panels. Если установить свойство SimplePanel в значение
True, то в строке состояния будет отображаться текст, хранящийся в
свойстве SimpleText. Итак, задача состоит в том, чтобы при активизации
меню записывать подсказку выбранного пункта в свойстве SimpleText и, в
том случае если подсказка содержит текст, устанавливать свойство
170
SimplePanel в значение True. Для решения этой задачи вы должны
представлять механизм работы подсказок. Его суть состоит в следующем.
Каждый пункт меню имеет свойство Hint для хранения подсказки. Когда
вы выделяете пункт меню с помощью мыши или клавиатуры, текст
подсказки переписывается из пункта меню в объект Application, у которого
тоже есть свойство Hint. При этом в объекте Application возникает событие
OnHint. Все, что нам нужно — написать обработчик этого события, который
отобразит значение свойства Hint объекта Application в строке состояния.
Объект Application не виден в окне свойств, но вы можете получить
доступ к его событиям на этапе проектирования. Для этого в форму
помещается специальный компонент ApplicationEvents, который вы найдете
в палитре компонентов на вкладке Additional. У этого компонента всего два
свойства: Name и Tag.
Вопросы:
1) Где обычно располагается полоса состояния?
2) Как организовать набор панелей в полосе состояния?
3) Как задать свойства панелей полосы состояния?
4) С какого индекса начинается нумерация панелей в полосе
состояния?
5) Для чего используется свойство Hint?
Задание 1. Разделите панели состояния на 2 части и отобразите
необходимую информацию. Поместите на форму компонент TStatusBar и
TButton, в обработчике событий OnClick компонента TButton запишите:
171
Рис.1
procedure TForm1.Button1Click(Sender: TObject);
begin
StatusBar1.Panels.Add;
StatusBar1.Panels.Add;
StatusBar1.Panels[0].Text :='Секция 1';
StatusBar1.Panels[1].Text :='Секция 2';
end;
Задание 2. Создайте программу, на основе компонента RichEdit,
содержащую полосу состояния. В ее первой панели отображается номер
строки и символа, перед которым находится курсор, во второй —
отображается, модифицирован текст в окне, или нет. В третьей панели
отображаются координаты курсора мыши.
Рис. 2
172
Для реализации такой полосы состояния надо в обработчиках событий
OnKeyDown, OnKeyUp, OnMouseDown и OnMouseUp компонента RichEdit1
и события OnResize формы обеспечить выполнение операторов:
StatusBar1.Panels[0].Text:=IntToStr(RichEdit1.CaretPos.Y+1)
+
':'+IntToStr
(RichEdit1.CaretPos.X+1);
if RichEdit1.Modified
then StatusBar1.Panels[1].Text := 'модиф.' else StatusBar1.Panels[1].Text := '';
Эти операторы заполняют первые две панели полосы состояния, третью
панель полосы состояния заполните самостоятельно.
Задание 3. Расположите на форме компоненты StatusBar, Edit,
Memo, Timer, ApplicationEvents, как на рисунке. Напишите свойство Hint для
Edit и Memo, допустим Фамилия и общие сведения. Для компонента
StatusBar создадим три панели. Для первой панели, где у нас будет
отображаться дата, ширину установим равную 60.
Рис. 3
Компоненту
ApplicationEvents событию onHint создадим такой
обработчик:
procedure TForm1.ApplicationEvents1Hint(Sender: TObject);
begin
StatusBar1.Panels[2].Text := Application.Hint;
end;
173
Он будет выводить подсказки элементов формы в третьей панели. Для
события onTimer (для того чтобы время и дата выводились в первой и второй
панели соответственно) компонента Timer procedure TForm1.Timer1Timer(Sender: TObject);
begin
StatusBar1.Panels[0].text:=DateToStr(now);
StatusBar1.Panels[1].text:=TimeToStr(now);
end;
Задание 4. Поместите на форму компонент ApplicationEvents.
Теперь в свойстве Hint каждого пункта меню впишите угодную вам строкуподсказку (рис. 4).
Рис. 4
Выполните компиляцию и запустите программу. Проверьте работу
механизма подсказок в строке состояния (рис. 5).
174
Рис. 5
Задание 5. Создайте программу с полосой состояния из двух панелей,
в которых отображается текст «Время работы с программой:», а во второй
идет отсчет времени работы с программой.
Задание 6. Необходимо создать приложение, отражающее различные
возможности работы со строкой состояния.
В панелях будет отображаться следующая информация:
• Панель 0: значение текущей всплывающей подсказки (hint), то есть
подсказки для того элемента, над которым в данный момент находится
указатель мыши.
• Панель 1: цвет текста в поле редактора Memo.
• Панель 2: стиль шрифта в поле редактора Memo (обычный или курсив).
• Панель 3: состояние кнопки Caps Lock (если кнопка включена, то
выводится строка 'Большие буквы', если выключена, то отображается строка
'Маленькие буквы').
• Панель 4: количество строк, содержащихся в редакторе Memo.
• Панель 5: текущее время.
175
Рис. 6
Для компонента StatusBar свойству AutoHint присваивается значение
True.
176
Урок 19 Горячие клавиши — компонент HotKey
Компонент HotKey, расположенный в библиотеке на странице "Win32",
является вспомогательным, обеспечивающим возможность задания самим
пользователем горячих клавиш, определяющих быстрый доступ к разделам
меню. К тому же этот компонент позволяет задать такие сочетания горячих
клавиш, которые не предусмотрены в выпадающем списке свойства разделов
меню ShortCut.
Компонент HotKey внешне выглядит как обычное окно редактирования
Edit. Но если в него входит пользователь, то оно переводит нажимаемые им
клавиши в тип TShortCut, хранящий комбинацию горячих клавиш. Например,
если пользователь нажимает клавиши Ctrl-ф, то в окне HotKey появится текст
«"Ctrl + ф"».
Основное свойство компонента — HotKey, равное по умолчанию
комбинации клавиш Alt-А.
Свойство Modifiers указывает модификатор — вспомогательную
клавишу, нажимаемую перед символьной Свойство Modifiers определяет
какие управляющие клавиши по умолчанию используются для назначения
комбинации клавиш. По виду понятно, что речь идет о клавишах Shift, Ctrl,
Alt. Значение hkExt - говорит о том что нет управляющих клавиш.
. Это свойство является множеством, которое может включать значения
hkShift, hkCtrl, hkAlt, hkExt, что соответствует клавишам Shift, Ctrl, Alt, Extra.
По умолчанию Modifiers =[hkAlt]. Если вы хотите, например, задать вместо
177
этого значения в качестве модификатора клавишу Ctrl, вы должны выполнить
оператор:
HotKey1.Modifiers: = [hkCtrl];
Свойство InvalidKeys задает недопустимые клавиши или их комбинации.
Значения свойства InvalidKeys:
hcNone
Обычные
алфавитно-цифровые
клавиши
должны
нажиматься вместе с управляющими
hcShift
используется клавиша Shift
hcCtrl
используется клавиша Ctrl
hcAlt
используется клавиша Alt
hcShiftCtrl
используются клавиши Shift + Ctrl
hcShiftAlt
используются клавиши Shift + Alt
hcCtrlAlt
используются клавиши Ctrl + Alt
hcShiftCtrlAlt
используются клавиши Shift + Ctrl + Alt
Если вы хотите задать программно значение свойства HotKey, то
можете это сделать, например, операторами
HotKey1.HotKey := ord('F');
HotKey1.Modifiers := [hkAlt];
Эти операторы зададут комбинацию горячих клавиш Alt+F.
Вопросы:
1. Для чего используют компонент HotKey?
2. Как выглядит компонент HotKey?
3. Перечислите свойства компонента HotKey?
4. Как задать комбинацию горячих клавиш Shift+V.
178
Задание 1. На форме расположим компоненты меню, Edit,
HotKey и label. В меню сделаем один пункт – «Сообщение». Label будет
иметь заголовок - Горячая клавиша.
Рис.1
Обработчик события пункта меню:
procedure TForm1.N1Click(Sender: TObject);
begin
ShowMessage('Нажатие горячих клавиш');
end;
События
(onCreate)
создания
формы
и
onChange
(изменения)
компонента HotKey будут одинаковыми, они будут задавать "горячие
клавиши" для пункта меню:
procedure TForm1.FormCreate(Sender: TObject);
begin
n1.shortCut := HotKey1.HotKey;
end;
procedure TForm1.HotKey1Change(Sender: TObject);
begin
n1.shortCut := HotKey1.HotKey;
end;
179
В первый раз задайте
"горячие клавиши", второй выполните команду.
(Фокус ввода должен быть на Edit)
Задание 2. Пусть у вас есть главная форма приложения, содержащая
компонент MainMenu и пусть вы хотите ввести команду настройки,
позволяющую пользователю изменить установленные для разделов меню
горячие клавиши. Для упрощения задачи будем считать, что меню,
сконструированное в MainMenu:
1. не каскадное (т.е. состоит только из двух уровней — заголовков меню
и выпадающих списков разделов)
2. в свойствах Caption разделов меню не использованы амперсанты
3. в меню отсутствуют разделители
Эти предположения сделаны просто для того, чтобы упростить код.
Начните новое приложение, разместите на форме компонент MainMenu и
сконструируйте
с
его
помощью
любое
меню,
удовлетворяющее
перечисленным требованиям. Задайте каким-то из разделов меню быстрые
клавиши. Один из разделов меню должен называться "Настройка" и при
выборе его мы хотим предоставить пользователю вспомогательную форму
для настройки быстрых клавиш.
Добавьте в приложение еще одну форму (команда "File | New Form"). Эта
форма будет вспомогательной. В обработчик команды "Настройка" главной
формы вставьте оператор
Form2.ShowModal;
Этот оператор покажет пользователю окно вспомогательной формы как
модальное — т.е. пользователь не сможет вернуться в главную форму, пока
не закроет вспомогательную. Чтобы компилятор понял этот оператор, надо в
модуль главной формы Unit1 вставить оператор uses, ссылающийся на
модуль вспомогательной формы Unit2. Можете сделать это вручную или,
перейдя в окне Редактора Кода в модуль Unit1, выполните команду "File | Use
180
Unit" и укажите, что хотите связаться с модулем Unit2. Поскольку из модуля
Unit2 надо будет видеть меню модуля Unit1, то аналогичным образом
введите и обратную связь — свяжите модуль Unit2 c Unit1.
Теперь давайте спроектируем вспомогательную форму. Она может
иметь вид, представленный на рис. 2. На ней расположено два списка
ListBox. ListBox1, в котором отображаются заголовки меню, и ListBox2, в
котором отображаются разделы меню, соответствующие выбранному
заголовку. В нижней части формы расположен компонент HotKey и кнопка
Button, которая фиксирует в меню сделанный пользователем выбор и
закрывает форму. В компоненте HotKey надо стереть с помощью Инспектора
Объектов свойство HotKey, которое содержит некоторое значение по
умолчанию.
Рис. 2
Теперь надо написать обработчики событий, которые загружали бы
списки
ListBox1
пользователем
и
ListBox2
быстрых
названиями
клавиш
фиксировали
соответствующем разделе меню формы Form1.
Код может выглядеть следующим образом:
procedure TForm2.FormShow(Sender: TObject);
var i: integer;
разделов
бы
и
при
этот
выборе
выбор
в
181
begin
//Загрузка ListBox1 заголовками меню при событии OnShow формы Form2
ListBox1.Clear;
for i:=0 to Form1.MainMenu1.Items.Count-1 do
ListBox1.Items.Add(Form1.MainMenu1.Items[i].Caption);
ListBox1.ItemIndex:=0;
ListBox1Click(Sender); //Обращение к процедуре загрузки ListBox2
end;
Загрузка
ListBox2
заголовками
разделов
меню
MainMenu1.Items[ListBox1.ItemIndex], выделенного пользователем в ListBox1
при событии OnShow формы Form2
procedure TForm2.ListBox1Click(Sender: TObject);
var i: integer;
begin
ListBox2.Clear;
for i:=0 to
Form1.MainMenu1.Items[ListBox1.ItemIndex].Count-1 do
ListBox2.Items.Add(Form1.MainMenu1.Items[
ListBox1.ItemIndex].Items[i].Caption);
ListBox2.ItemIndex:=0;
end;
Занесение горячих клавиш выделенного в ListBox2 раздела в
компонент HotKey1
procedure TForm2.ListBox2Click(Sender: TObject);
begin
HotKey1.HotKey:=Form1.MainMenu1.Items[ListBox1.ItemIndex].Items[ListBox
2.ItemIndex].ShortCut;
end;
182
Изменение горячих клавиш выбранного раздела меню и закрытие
вспомогательной формы
procedure TForm2.Button1Click(Sender: TObject);
begin
Form1.MainMenu1.Items[
ListBox1.ItemIndex].Items[
ListBox2.ItemIndex].Shortcut :=
HotKey1.HotKey;
Close;
end;
При событии OnShow формы Form2 происходит загрузка списка
ListBox1 заголовками меню. Цикл загрузки перебирает индексы от 0 до
Form1.MamMenu1.Items.Count-1. Это значение на 1 меньше значения
MainMenu1.Items.Count,
которое
равно
числу элементов
в
свойстве
MainMenu1.Items.
При щелчке пользователя на списке ListBox1 происходит загрузка
списка ListBox2. При этом к соответствующим разделам меню получается
доступ
с
помощью
Form1.MainMenu1.Items[ListBox1.ItemIndex].Items[i].
выражения
В
этом
выражении
Form1.MainMenu1.Items[ListBox1.ItemIndex] — элемент головного раздела
меню, выбранного пользователем в ListBox1. Каждый такой раздел можно
рассматривать как элемент массива меню и в то же время он сам является
массивом разделов второго уровня. Поэтому его свойство Items[i] указывает
на подраздел с индексом i.
При щелчке пользователя на списке ListBox2 происходит загрузка
компонента HotKey1 символами горячих клавиш выбранного пользователем
раздела. Если раздел не имеет горячих клавиш, то в окне HotKey1
отображается текст «"Нет"». Далее пользователь может войти в окно
HotKey1 и нажать сочетание клавиш, которое он хочет назначить
183
выбранному им разделу меню. Обработка щелчка на кнопке фиксирует это
сочетание в разделе меню и закрывает вспомогательную форму.
Опробуйте это приложение в работе. И вам станет ясней механизм
работы с разделами меню и с быстрыми клавишами.
184
Урок 20 Воспроизведение немых видео клипов — компонент Animate
Рассмотрим способ воспроизведения в приложении Delphi стандартных
мультипликаций Windows и файлов .avi — клипов без звукового
сопровождения. Это позволяет сделать компонент Animate, расположенный
на странице Win32 библиотеки.
Компонент Animate позволяет воспроизводить на форме стандартные
видеоклипы Windows (типа копирования файлов, поиска файлов и т.п.) и
немые видео файлы .avi — Audio Video Interleaved. Эти файлы представляют
собой последовательность кадров битовых матриц. Они могут содержать и
звуковую дорожку, но компонент Animate воспроизводит только немые
клипы AVI.
Воспроизводимое им изображение задается одним из двух свойств:
FileName или CommonAVI. Первое из этих свойств, как ясно из его
названия, позволяет в процессе проектирования или программно задать имя
воспроизводимого
файла.
А
свойство
CommonAVI
позволяет
воспроизводить стандартные мультипликации Windows. Это свойство
объявлено следующим образом:
type TCommonAVI = (aviNone, aviFindFolder, aviFindFile,
aviFindComputer, aviCopyFiles, aviCopyFile,
aviRecycleFlle, aviEmptyRecycle, aviDeleteFile);
property CommonAVI: TCommonAVI;
Тип TCommonAVI определяет множество предопределенных в
Windows мультипликаций типа копирования файлов, поиска файлов,
удаления файлов и т.п..
Свойство Repetitions компонента Animate задает число повторений
воспроизведения клипа. Если оно равно 0 (значение по умолчанию), то
воспроизведение повторяется вновь и вновь до тех пор, пока не будет
выполнен метод Stop. При выполнении этого метода генерируется событие
185
OnStop, которое можно использовать, например, чтобы стереть изображение
— сделать его невидимым.
Вы можете посмотреть воспроизводимое изображение по кадрам. Для
этого щелкните на компоненте правой кнопкой мыши и из всплывшего меню
выберите разделы Next Frame (следующий кадр) или Previous Frame
(предыдущий кадр). Это позволит вам выбрать фрагмент клипа, если вы не
хотите воспроизводить клип полностью. Воспроизвести фрагмент клипа
можно, установив соответствующие значения свойств StartFrame —
начальный кадр воспроизведения, и StopFrame — последний кадр
воспроизведения.
Воспроизводить фрагмент клипа можно и методом Play, который
определен следующим образом:
procedure Play(FromFrame, ToFrame: Word; Count: Integer);
Метод воспроизводит заданную последовательность кадров клипа от
FromFrame до ToFrame включительно, и воспроизведение повторяется
Count раз. Если FromFrame = 1, то воспроизведение начинается с первого
кадра. Значение ToFrame должно быть не меньше FromFrame, и не больше
значения, определяемого свойством FrameCount (свойство только для
чтения), указывающим полное число кадров в клипе. Если Count = 0, то
воспроизведение повторяется до тех пор, пока не будет выполнен метод Stop.
Выполнение Play идентично заданию StartFrame равным FromFrame,
StopFrame равным ToFrame, Repetitions равным Count и последующей
установке Active в true.
В компоненте Animate предусмотрены события OnClose, OnOpen,
OnStart и OnStop, генерируемые соответственно в моменты закрытия и
открытия компонента, начала и окончания воспроизведения.
Полезно также установить свойство AutoSize в false, а свойство Center
в true, чтобы изображение всегда появлялось в центре экрана.
186
Вопросы
1) Для чего предназначен компонент Animate?
2) Что означает каждое значение свойства TCommonAVI компонента
Animate?
3) Как организовать пошаговый просмотр анимации?
4) Как изображение расположить в центре экрана?
5) Опишите события предусмотренные в компоненте Animate?
Задание 1. Напишите программу, в главном окне которой, сразу
после появления
окна,
воспроизводится не
сопровождаемая
звуком
анимация, например рекламный ролик. Анимация должна воспроизводиться
один раз.
Рис. 1. Форма программы Анимация
Задание
2.
Создать
приложение,
в
котором
можно
воспроизвести несколько вариантов анимации некоторое заранее заданное,
количество раз.
187
Рис. 2
В приложении будем имитировать начало и окончание события,
которое должно сопровождаться мультипликацией, нажатиями кнопок
запуска и остановки воспроизведения. При этом будем независимо
устанавливать как видео фрагмент, так и количество демонстраций. Для
этого поместим на форму компонент Edit1 и установим значение свойства
Text равным 1, для того чтобы видео фрагмент демонстрировался по
умолчанию один раз.
Задание 3. Создайте новое приложение и положите на форму
компоненты Animate1, Label1, ProgressBar1, Button1,Timer1.
Рисунок 3 - Результат работы программы
188
У компонента Animate1 измените свойство CommonAvi на aviCopyFiles, у
компонента Timer1 измените свойство Enabled на False, Interval на 60.
Теперь пропишите обработчик события OnClick кнопки Button1
Пропишите обработчик события OnTimer таймера Timer1:
ProgressBar1.Position:=ProgressBar1.Position+1;
If ProgressBar1.Position>=ProgressBar1.Max then
begin
Timer1.Enabled:=False;
ProgressBar1.Position:=0;
Animate1.Stop;
end;
Label1.Caption:='Выполнено: ' +IntToStr(ProgressBar1.Position)+ '%';
Задание 4. Напишите программу, используя которую можно
просматривать анимацию (содержимое AVI-файла) в реальном масштабе
времени или по кадрам.
Для выбора файла анимации используйте стандартное диалоговое окно
Открытие файла. Чтобы пользователь мог выбрать файл изображения
компоненту OpenDialog задайте фильтр (свойство Filter) равным
видео *.avi
*.avi
Рис. 4.
189
Литература
1) Архангельский А.Я. 100 компонентов общего назначения библиотеки
Delphi 5. - М.: Бином, 2002. - 272 с.
2) Архангельский, А.Я. Программирование в Delphi. Учебник по
классическим версиям Delphi (+ дискета); М.: Бином, 2006. - 415 c.
3) Бобровский, Сергей Delphi 7. Учебный курс; СПб: Питер, 2008. - 736 c.
4) Сухарев, М.В. Основы Delphi. Профессиональный подход; М.: Наука и
техника, 2004. - 600 c.
Download