Если вы программировали в Delphi, Lazarus или Visual Basic, то знаете, что формой в этих средах называется окно Windows. Форма имеет заголовок и кнопки управления. Пример формы показан на рисунке.
В DataExpress форма является контейнером, который может отображаться либо в окне, либо в другом контейнере – например, в закладке. В скриптах форма представлена классом TdxForm, который основан на классе TCustomPanel. Примеры форм показаны ниже.
Форма является не просто визуальным компонентом, а сложным механизмом, который управляет всеми компонентами на форме. Программа автоматически увязывает компоненты на форме с данными, заполняет списки из справочников, отслеживает изменения, заполняет таблицы и запросы, отслеживает изменения в полях и вычисляет выражения, и многое-многое другое. Форма считывает записи из базы и хранит в наборе данных. Количество записей определяется фильтром формы. Сама форма может отображать одну запись и записи подчиненных форм и запросов. Множество записей формы отображаются в табличной части формы. На рис. 12 табличная часть находится слева от формы. Формы и табличная часть неразрывно связаны друг с другом. К табличной части формы можно обратиться через свойство Grid (класс TdxGrid).
Все визуальные компоненты формы и сама форма тесно связаны с набором данных. Набор данных хранит в оперативной памяти некоторое множество записей, которая программа считывает из базы данных по запросу пользователя. Проделанные изменения отправляются обратно в базу. Набор данных можно представить в виде таблицы, строки таблицы – это записи, а столбцы – поля записи. По сути, в табличной части формы мы видим содержимое набора данных. Визуальные компоненты синхронизируются с набором данных. Они отображают его содержимое, при изменении содержимого компонентов, данные сохраняются в набор. Т. е. получается, что кроме того, что компонент сам непосредственно хранит данные, еще вдобавок, данные хранятся в наборе. Такой способ хранения может показаться избыточным, но следует учесть, что компонент способен хранить только одно значение, а набор данных хранит множество значений. Кроме этого, набор данных знает какие записи сохранять в базу, а какие нет. В наборе данных может быть активна только одна запись, та, на которой установлен курсор. Курсор – это указатель на текущую запись. Одновременно изменять можно только одну запись, текущую. Когда пользователь перемещается по записям, происходит смена позиции курсора. Вместе с этим происходит обновление содержимого компонентов формы. Набор данных не имеет соответствующего компонента и отдельного класса. Вместо этого он интегрирован в форму (а также в запрос), а управление им осуществляется через методы и свойства формы.
Для тех, кто программировал в среде Delphi или Lazarus, эта технология должна быть хорошо знакома. В этих средах набор данных представлен базовым классом TDataset.
Далее в руководстве вы будете встречать фразы «открытие набора данных», «закрытие набора данных». При открытии набора программа отправляет sql-запрос серверу базы данных и сохраняет возвращаемые сервером записи у себя в наборе. При закрытии происходит очистка и освобождение памяти, занятая набором данных.
Модуль формы создается по необходимости, когда вам нужно написать какой-то скрипт, работающий внутри формы. В модуле формы есть две стандартные процедуры, которые вызываются программой при создании и уничтожении формы: Form_Create и Form_Destroy. В процедуре Form_Create вы можете подключиться к событиям формы и ее компонентов, а также выполнить какую-либо инициализацию. В этой процедуре обращаться к данным нельзя, т. к. они еще не прочитаны из базы. В процедуре Form_Destroy можно выполнить какие-либо завершающие действия и освободить память. В модуле формы вы можете обращаться к ее компонентам по их именам.
С формой может быть связано окно редактирования записи. Доступно через свойство EditWindow, если представление формы «Только таблица» или форма подчиненная. В противном случае EditWindow = nil
. Программа автоматически создает необходимые компоненты окна и помещает форму в окно.
Окно редактирования представлено классом 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);
Конструктор имеет единственный параметр:
Форма, созданная таким образом, имеет представление «Только таблица» независимо от того, что было задано в дизайнере. Это необходимо для того, чтобы было создано окно редактирования. Она является полностью функциональной: скрипты, выражения, таблицы, запросы и т. д. – все работает.
После создания формы нужно прочитать данные из базы методами Open, OpenRecord или OpenRecords. Такую форму можно использовать для какой-либо скрытой обработки данных, печати, редактирования записей и т. д.
Форма уничтожается методом Free. При уничтожении, если набор данных не был закрыт (методом Close), он закрывается автоматически.
Обратиться к форме можно по имени компонента формы, например Form1. Но лучше обращаться к форме через специальную переменную Self, которая всегда указывает на текущую форму в модуле.
К сожалению ограничения Pascal Script не позволяют обратиться к компоненту формы по его имени через точку:
Self.Forms['…'].dxEdit1.Color := clRed;
Этот код работать не будет. Для доступа к компоненту можно воспользоваться методом FindComponent:
TdxEdit(Self.Forms['…'].FindComponent('dxEdit1')).Color := clRed;