6. Формы

Если вы программировали в Delphi, Lazarus или Visual Basic, то знаете, что формой в этих средах называется окно Windows. Форма имеет заголовок и кнопки управления. Пример формы показан на рисунке.
Рис 10
В DataExpress форма является контейнером, который может отображаться либо в окне, либо в другом контейнере – например, в закладке. В скриптах форма представлена классом TdxForm, который основан на классе TCustomPanel. Примеры форм показаны ниже.

Рис 11
Рис 12

Форма является не просто визуальным компонентом, а сложным механизмом, который управляет всеми компонентами на форме. Программа автоматически увязывает компоненты на форме с данными, заполняет списки из справочников, отслеживает изменения, заполняет таблицы и запросы, отслеживает изменения в полях и вычисляет выражения, и многое-многое другое. Форма считывает записи из базы и хранит в наборе данных. Количество записей определяется фильтром формы. Сама форма может отображать одну запись и записи подчиненных форм и запросов. Множество записей формы отображаются в табличной части формы. На рис. 12 табличная часть находится слева от формы. Формы и табличная часть неразрывно связаны друг с другом. К табличной части формы можно обратиться через свойство Grid (класс TdxGrid).

Набор данных

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

Для тех, кто программировал в среде Delphi или Lazarus, эта технология должна быть хорошо знакома. В этих средах набор данных представлен базовым классом TDataset.

Далее в руководстве вы будете встречать фразы «открытие набора данных», «закрытие набора данных». При открытии набора программа отправляет sql-запрос серверу базы данных и сохраняет возвращаемые сервером записи у себя в наборе. При закрытии происходит очистка и освобождение памяти, занятая набором данных.

Модуль формы

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

Окно редактирования записи (EditWindow)

С формой может быть связано окно редактирования записи. Доступно через свойство EditWindow, если представление формы «Только таблица» или форма подчиненная. В противном случае EditWindow = nil. Программа автоматически создает необходимые компоненты окна и помещает форму в окно.

Рис 13

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

  • ScrollBox: TScrollBox – контейнер, в который помещается форма. Если форма не помещается полностью в контейнер, то появляются полосы прокрутки.
  • Form: TdxForm – сама форма.
  • Buttons: TButtonPanel – панель кнопок.

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

procedure AnyButtonClick(Sender: TObject); 
begin
 Self.Append; 
 Self['Дата'] := Date;
 if Self.EditWindow.ShowModal = mrOk then
  Self.Post
 else
  Self.Cancel;
end;

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

Создание и уничтожение формы в скрипте

Форма создается конструктором класса TdxForm:

constructor Create(const FormName: String);

Конструктор имеет единственный параметр:

  • FormName – имя формы.

Форма, созданная таким образом, имеет представление «Только таблица» независимо от того, что было задано в дизайнере. Это необходимо для того, чтобы было создано окно редактирования. Она является полностью функциональной: скрипты, выражения, таблицы, запросы и т. д. – все работает.

После создания формы нужно прочитать данные из базы методами Open, OpenRecord или OpenRecords. Такую форму можно использовать для какой-либо скрытой обработки данных, печати, редактирования записей и т. д.

Форма уничтожается методом Free. При уничтожении, если набор данных не был закрыт (методом Close), он закрывается автоматически.

Обращение к форме

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

Обращение к компонентам формы из другого модуля (FindComponent)

К сожалению ограничения Pascal Script не позволяют обратиться к компоненту формы по его имени через точку:

Self.Forms['…'].dxEdit1.Color := clRed;

Этот код работать не будет. Для доступа к компоненту можно воспользоваться методом FindComponent:

TdxEdit(Self.Forms['…'].FindComponent('dxEdit1')).Color := clRed;