Грузим формы из базы данных или Как зарегистрировать класс по его имени
Оформил: DeeCo
Автор: Рощупкин А.В.
Рощупкин А.В. Уральский государственный университет путей
сообщения, лаборатория математического моделирования и компьютерных
технологий, Екатеринбург
Идея хранения ресурсов формы - файлов dfm - в
базе данных не нова. При правильном использовании этого метода, можно сделать
достаточно легко настраиваемое под требования пользователя, в плане
интерфейса, ядро для приложений (для этого нужно иметь редактор форм).
Виденные мной реализации загрузки форм из базы данных имели одно слабое место:
реализация регистрации классов. Для правильной загрузки формы должны быть
зарегистрированы все классы, используемые в этой форме. Ранее регистрация
проходила "напрямую", то есть создавалась процедура, в которой при помощи
процедуры RegisterClass, производилась регистрация всех требуемых классов. В
данной статье предлагается другой способ регистрации классов: получаем имена
требуемых классов из ресурса форма и регистрируем их по имени.
База данных.
В данной статье используется база данных MS
Access, содержащей только одну таблицу FRM с полями: CLSNME (текстовое поле) -
для имени класса формы, FRMDFM (поле MEMO) - для хранения ресурса формы.
Ресурс формы храним в текстовом представлении и берем его из файла dfm
(поставить галочку "Text DFM" в контекстном меню формы в редакторе форм
Delphi).
Загрузка формы из базы данных.
Для загрузки ресурса формы из базы данных
поместим результат запроса к полю FRMDFM в поле класса TBlobField. Пример
создания такого поля можно посмотреть в файле помощи Delphi для конструктора
класса TBlobField. Далее сохраняем информацию из этого поля в TMemoryStream.
Для того чтобы преобразовать текст, который мы сохранили в TMemoryStream, к
формату ресурса формы воспользуемся функцией ObjectTextToResource. После этого
можно создавать форму при помощи функции ReadComponentRes класса
TMemoryStream. Текст кода, отвечающего за загрузку формы, смотри в прилагаемом
примере (функция TFormLoader.LoadForm, файл UntDynamicLoad).
Регистрация классов.
После того как мы считали ресурс формы в
TMemoryStream и перед ее созданием из этого ресурса при помощи функции
ReadComponentRes должны быть зарегистрированы все классы, используемые в
загружаемой форме. Получить все эти классы можно пропарсив ресурс формы в его
текстовом виде (каждое имя класса стоит после двоеточия в строке со словом
object).
Далее требуется зарегистрировать этот класс, если он ранее не был
зарегистрирован.
Класс регистрируется при помощи процедуры
RegisterClass(AClass: TPersistentClass). После того как мы пропарсили ресурс
формы мы имеем только имя класса. Delphi не предоставляет стандартных процедур
регистрации класса по его имени (получения указатель на класс при помощи
функции GetClass(const ClassName: string), если он еще не зарегистрирован,
естественно нельзя).
Я достаточно долго искал способ сделать это. В
русскоязычном интернете я так ничего и не нашел. Способ был найден на
http://www.tamaracka.com/ (Search Borland* Newsgroups: Ludovic Dubois Classes
Hack). Ludovic Dubois предложил код, который из исполняемого файла и файлов
bpl может вытащить указатели на классы (TClass) по их имени (или получить все
классы определенные в exe и bpl). Естественно, если проект не использует
runtime packages, то есть все пакеты будут слинкованы прямо в исполняемый
файл, достаточно смотреть только exe-файл. В противном случае, необходимо
просматривать все используемы runtime пакеты (получить их список при помощи
EnumModules не составляет труда). Код Ludovic Dubois включен в прилагаемый
пример с добавлением определения некоторых используемых им типов.
Пример программы, загружающей форму из базы данных.
Все функции для работы с загрузкой формы вынесены
в отдельный не визуальный класс TFormLoader (файл UntDynamicLoad). Функции
POSearchClasses, POSearchClassesCallBack принадлежат Ludovic Dubois и служат
для получения TClass из exe или bpl файлов по его имени. Проект настроен на
использование runtime packages. Функция CollectAllPackages возвращает список
всех используемых модулей (они будут просматриваться на предмет вхождения в
них искомого класса). Функция LoadForm собственно создает и загружает форму из
базы данных. Исходные тексты можно взять тут: programme.zip
(71 Kb)
|