Лекция № 7
Тема: "Приемы работы с формами"
План
1. Инициализация форм в программе
2. Создание формы- заставки
3. Окна непрямоугольной формы
4. Анимация форм
1. Инициализация форм в программе
По умолчанию все формы, которые входят в проект Delphi, содержатся в разделе Auto-Create Forms, что означает их автоматическое создание при запуске программы. Если форм будет много, то запуск программы может затянуться во времени (пока все формы не будут созданы и размещены в оперативной памяти). Кроме того, некоторые формы могут и не использоваться пользователем в текущем сеансе работы, но все равно они создаются и "засоряют" память компьютера.
Для оптимизации работы приложений рекомендуется автоматически создавать только главную форму, которая появится на экране первой, а все другие размещать в разделе Available Forms.
По мере необходимости форму можно будет создать, отобразить, а при закрытии удалить из памяти компьютера.
Для создания формы нужно выполнить следующее:
· ввести команду:
имя_формы:=Тимя_ формы.Create(nil);
· после создания формы ее можно отобразить с помощью команды:
имя_ формы.Show;
или
имя_ формы.ShowModal;
· на динамически созданной форме иногда могут некорректно отображаться визуальные компоненты. Для устранения этого недостатка форму после отображения на экране нужно перерисовывать с помощью команды:
имя_ формы.Repaint;
Для удаления формы из памяти в ее событии OnClose добавьте команду:
Action:=caFree;
Соблюдение этих рекомендаций позволит сделать ваше приложение менее требовательным к объему памяти компьютера и загружаться оно будет быстрее.
Пример. Пусть есть главная форма Form1, на которой находится кнопка для открытия формы Form2. Форма Form2 для экономии памяти при проектировании перенесена в список Available Forms. Для кнопки на форме Form1 напишем код:
procedure TForm1.Button1Click(Sender: TObject);
begin
//создаем экземпляр формы в памяти
//и помещаем его в переменную form2
form2:=TForm2.Create(nil);
//отображаем форму на экране
form2.Show;
//перерисовываем форму для отображения
//всех ее компонентов
form2.Repaint;
end;
Для удаления формы из памяти после ее закрытия в событии OnClose формы Form2 напишите код:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;
2. Создание формы- заставки
Форма-заставка должна появляться в начале загрузки всех форм приложения. Если таких форм будет много, то загрузка может выполняться долго и пользователь может подумать, что программа "зависла". Если же перед стартом программы сначала вывести заставку с сообщением о необходимости дождаться окончания загрузки, то это решит данную проблему.
Форма заставка должна появиться до началу создания других форм, поэтому код для ее отображения необходимо писать в файле проекта. При этом форма-заставка не должна содержать строки заголовка окна и границ. Для этого установите свойство формы BorderStyle=bsNone.
Для корректного отображения такой формы- заставки используют подход, который показан на примере. Пусть имеется форма-заставка с именем frmZast, которая помещена в список Available Forms. Также есть главная форма Form1, до загрузки которой должна появиться форма-заставка. Для решения данной задачи нужно выполнить следующее:
· с помощью команды Project – View Source откройте код проекта;
· в разделе Uses добавьте имя модуля Windows (он содержит реализацию функции Sleep - создание паузы для отображения формы-заставки);
· после ключевого слова Begin вставьте команды:
//создаем экземпляр формы-заставки
frmzast:=TfrmZast.Create(nil);
//отображаем заставку на экране
frmZast.Show;
//перерисовываем форму для отображения всех ее компонентов
frmZast.Repaint;
//делаем паузу в миллисекундах
Sleep(1000);
· перед командой запуска приложения Application.Run; вставьте команду:
//удаляем окно с экрана и из памяти
frmZast.Free;
Таким образом форма-заставка появится до выполнения команд Application.Create(…), которые создают формы и помещают их в память, и закроется перед запуском основной программы.
3. Окна непрямоугольной формы
Для создания окон непрямоугольной формы можно использовать несколько подходов.
Окно по контуру рисунка
Первый способ заключается в размещении на форме некоторого рисунка. Исходная форма "обрезывается" по контуру этого рисунка. Для реализации такого подхода необходимо выполнить следующее:
· в графическом редакторе создать изображение-шаблон с белым фоном и сохранить в формате BMP;
· на форме разместить компонент Image (Additional) и задать для него свойства: Align = alСlient; Picture = файл с нужным изображением; Stretch = True;
· для формы задать свойства: TransparentColor = True; TransparentColorValue = clWhite.
При запуске программы вы увидите, что форма "обрезалась" по контуру рисунка.
Указанный подход имеет недостаток: используемый рисунок имеет формат BMP, а значит большой размер. Итоговый размер EXE файла приложения будет увеличиваться на размер рисунка. Файлы форматов jpeg, gif и др. не подходят, потому что возле границы рисунка имеют не чистый белый цвет, и граница формы делается размытой.
Окно с помощью региона
Второй способ создания окон непрямоугольной формы осуществляется с помощью понятия региона. Регион – это часть окна, которая воспринимается как форма. Все, что находится за регионом, игнорируется системой и не отображается на экране.
Регион – это объект типа HRGN, в котором формируется форма окна. Если регион создан, то его применение к окну осуществляется с помощью специальной функции:
SetWindowRgn (дескриптор, регион, флажок);
· дескриптор – это указатель на окно. Каждое окно, которое отображается на экране автоматически получает от операционной системы уникальную метку (дескриптор), с помощью которой к окну можно обратиться. Окно в программах Delphi имеет специальное свойство Handle, с помощью которого можно обратиться к его дескриптору;
· регион – имя объекта типа HRGN, в котором хранится форма будущего окна;
· флажок – признак, который принимает два значения: true – немедленное перерисовывание окна согласно новому региону, false – автоматическое перерисовывание не происходит
Для создания региона окна используют ряд функций:
//прямоугольник
CreateRectRgn(x1,y1,x2,y2);
//прямоугольник со скругленными углами
//коэффициенты a и b задают степень скругления углов
CreateRoundRectRgn(x1,y1,x2,y2,a,b);
//эллипс
CreateEllipticRgn(x1,y1,x2,y2);
Пример. Создать форму в виде эллипса. Для этого в событии формы OnCreate напишем код:
procedure TForm1.FormCreate(Sender: TObject);
//опишем переменную для задания региона
var myregion:HRGN;
begin
//создаем регион в виде эллипса на весь размер формы
myregion:=CreateEllipticRgn(0,0,ClientWidth,ClientHeight);
//применяем регион к форме
SetWindowRgn(Handle,myregion,true);
end;
Кроме прямоугольников и эллипсов существует возможность создания окон в виде произвольных многоугольников. Для задания региона в виде многоугольника используют функцию:
CreatePolygonRgn (массив, n, Alternate);
где:
· массив – это массив точек многоугольника;
· N – количество точек из массива, которые фактически нужно использовать при создании региона.
Пример. Создать форму в виде ромба. Для этого сначала определим координаты всех точек многоугольника с помощью схемы:

Чаще всего формы непрямоугольного вида имеют фиксированный размер. Поэтому координаты точек для многоугольного региона удобно задавать с помощью стандартных графических редакторов, например Paint. Для этого необходимо выполнить следующие операции:
- в редакторе Paint откройте нужное изображение;
- для формы в Delphi задайте размер, совпадающие с размером изображения (свойства ClientWidth и ClientHeight);
- наводите указатель мыши в редакторе Paint на каждую точку и в строке статуса считывайте координаты этой точки;
- указывайте считанные координаты для очередной точки массива в коде.
На рисунке показано, как в Paint в правом нижнем углу окна отображаются координаты точки изображения (220, 217):

Пример. Пусть изображение в Paint имеет размер 228х225 и координаты точек определены как показано на рисунке:

Необходимо отобразить форму в виде звезды с заданными размерами.
Для формы задайте свойства: BorderStyle = bsNone (скрываем границу окна), ClinetWidth = 280 (ширина исходного рисунка), ClientHeight = 225 (высота исходного рисунка), Position = poDesktopCenter (запуск по центру экрана).
В событии OnCreate формы напишем код в соответствии с определенными координатами.
procedure TForm1.FormCreate(Sender: TObject);
var
//описываем переменную для задания региона
myregion:HRGN;
//описываем массив для задания точек многоугольника
//у звезды 10 точек
p:array [0..9] of TPoint;
begin
//задаем координаты каждой точки
//начинаем с любой и двигаемся по кругу
//по часовой или против часовой стрелки
//например, мы начнем с верхней точки
//и будем двигаться по часовой стрелке
p[0]:=Point(138,1);
p[1]:=Point(171,83);
p[2]:=Point(271,87);
p[3]:=Point(192,138);
p[4]:=Point(222,220);
p[5]:=Point(138,170);
p[6]:=Point(52,220);
p[7]:=Point(83,138);
p[8]:=Point(4,87);
p[9]:=Point(106,83);
//формируем регион в виде многоугольника (10 точек)
myregion:=CreatePolygonRgn(p,10,Alternate);
//применяем регион к форме
SetWindowRgn(Handle,myregion,true);
end;
4. Анимация окон
Для придания интерефейсу более привлекательного вида существует возможность задавать анимационные эффекты при появлении или закрытия окна.
Код анимации нужно писать в событиях формы OnShow (анимация при появлении) и OnClose (анимация при закрытии окна).
Для создание анимационного эффекта использую процедуру вида:
AnimateWindow(Handle, время, вид_анимации);
Время – это число миллисекунд, на протяжении еоторых будет выполняться анимация.
Вид анимации задаем эффект и может принимать значения:
· AW_SLIDE – эффект появления слайда. Не может использоваться вместе с эффектов aw_center ($ 40000);
· AW_ACTIVATE – после анимации делает окно активным ($ 20000);
· AW_BLEND – эффект появления. Может применяться только к окну верхнего уровня ($ 80000);
· AW_HIDE – скрытие окна. Данный флаг является дополнением ко всем остальным флагам анимации ($ 10000)
· AW_CENTER – появление или скрытие окна в центре экрана. Не может использоваться вместе с другими эффектами ($ 10);
· AW_HOR_POSITIVE – слайд слева направо. Используется вместе с aw_slide ($ 1);
· AW_HOR_NEGATIVE - слайд справа налево. Используется вместе с aw_slide ($ 2);
· AW_VER_POSITIVE – слайд сверху вниз. Используется вместе с aw_slide ($ 4);
· AW_VER_NEGATIVE - слайд снизу вверх. Используется вместе с aw_slide ($ 8).
Для объединения флагов использует оператор or.
//отобразить окно из точки по центру
AnimateWindow(Handle, 1000, AW_CENTER);
//убрать окно в точку по центру
AnimateWindow(Handle, 1000, AW_CENTER OR AW_HIDE);
//показать окно как слайд слева направо
AnimateWindow(Handle, 1000, AW_SLIDE or AW_HOR_POSITIVE);
//скрыть окно как слайд справа налево
AnimateWindow(Handle, 1000, AW_SLIDE or AW_HOR_NEGATIVE or AW_HIDE);
//показать окно как слайд из левого верхнего угла
AnimateWindow(Handle, 1000, AW_SLIDE or AW_HOR_POSITIVE or AW_VER_POSITIVE);
//скрыть окно как слайд в правый верхний угла
AnimateWindow(Handle, 1000, AW_SLIDE or AW_HOR_POSITIVE or AW_VER_NEGATIVE or AW_HIDE);
Пример. Пусть форма появляется с эффектом анимации с точки по центру экрана.
В событии формы OnShow напишем код:
procedure TForm1.FormShow(Sender: TObject);
begin
// центрируем форму на экране
Left:=(Screen.Width - Width) div 2;
Top:=(Screen.Height - Height) div 2;
// задаем анимацию и делаем окно активным
AnimateWindow(Handle, 1000, $ 10 OR $ 20000 )
end;
Закроем форму как слайд слева направо.
В событии формы OnClose напишем код:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// окно как слайд слева направо закрывается
AnimateWindow(Handle, 1000, $ 40000 OR $ 1 OR $ 10000 )
end;
Вопросы для самоконтроля
1. Для чего форма должна создаваться динамически?
2. Какие действия нужно выполнить, чтобы форма не создавалась автоматически при запуске основной программы?
3. Как динамически можно создать форму? Приведите пример кода. Как удалить динамично созданную форму при закрытии из памяти?
4. Какие действия нужно выполнить для создания формы-заставки? Приведите только описание всех свойств и компонентов (без кода)
6. Приведите код отображения формы-заставки в программе. В каком месте программы этот код нужно писать?
7. Опишите процедуру создания формы, которая повторяет контур размещенного на ней рисунка.
8. Какой код позволяет создать форму в виде эллипса или прямоугольника? В каком событии надо писать этот код?
9. Приведите код для создания формы в виде многоугольника (пять углов)?