Адрес этой странички: http://spcalc.narod.ru/tsp_fs_formdesign/sp_fs_formdesign.htm
Компонент TSP_fs_FormDesign
(Delphi-5).
Версия 1.01
от 01.03.2005
Freeware
(c)
: Sergey Popov, Usinsk, Komi, 2005
e-mail : sapopov@mail.ru
http://spcalc.narod.ru
Назначение :
Разработка ФОРМ для FastScript
(Fast
Reports
Inc.)
с использованием среды Delphi-5.
Исходный текст компонента приведен в
качестве демонстрации возможностей
использования среды Delphi-5
для разработки ФОРМ и генерации соотв.
исходного кода для пакета FastScript
версии 1.4 (синтаксис Pascal).
Ясно, что разработка интерфейса Пользователя – это один из самых нудных и трудоемких этапов разработки приложений. Любая «автоматизация» в этом вопросе – весьма желанна.
Трудно (а вероятнее всего и не нужно)
конкурировать в этом вопросе с фирмой Borland.
Можно просто использовать возможности
среды Delphi-5
для этих целей.
Что мы и сделаем в нашем простом примере.
Т.е., создадим простой компонент, который
позволит нам генерировать исходный код (для
FastScript-1.4,
синтаксис Pascal)
на основе созданной в Delphi-5
произвольной (в пределах разумного) формы.
Вариант статьи в формате MS WORD (включая исходники и примеры), 1106 Кб
В данной (демонстрационной) версии
компонента поддерживаются след. визуальные
компоненты на форме :
TPanel, TGroupBox, TButton, TSpeedButton, TLabel, TEdit, TListBox, TMemo, TSplitter, TCheckBox, TRadioButton .
После установки нашего компонента (пакет SP_FS_Delphi50.dpk) на странице SP появится иконка компонента.
Как
использовать.
1) Создать новый проект,
разместить на форме нужные компоненты и
присвоить компонентам
соотв. свойства.
Скачать пример (приложение
+ исходники), 222 Кб.
2) Кинуть на форму
компонент TSP_fs_FormDesign
3) Присвоить необходимые
значения свойств компонента
TSP_fs_FormDesign
Пояснения
:
FileName – полное имя файла, где будет
размещен исходный код ФОРМЫ
ComponentsName_Not_Save
- имена компонентов (через запятую)
которые не следует учитывать при генерации
исходного кода
Comment – комментарий, который будет
выведен в исходный код
Version – версия
компонента (ReadOnly)
OverwritePrompt -
если TRUE, то запрос на подтверждение, если
файл с именем FileName
уже существует
fsGenerateSource_for_Event
– если TRUE,
то дополнительно будет генерироваться «пустой»
код обработчиков событий компонентов
fsSource_for_Event_before_Var
– если TRUE,
то код обработчиков событий будет размещен
ПЕРЕД объявлением глобальных переменных (где
объявлены компоненты формы). В противном
случае, после
объявления глобальных переменных.
Следует отметить, что кнопка <Сформировать
код для FastScript> имеет
имя Button1
и необходима только для выполнения метода SaveToFile_FS
компонента TSP_fs_FormDesign.
Т.е., в результирующем коде (в FastScript) эта кнопка не нужна.
Поэтому, имя этой кнопки указано в свойстве
ComponentsName_Not_Save
компонента TSP_fs_FormDesign.
4) Изменить
обработчик нажатия на кнопку <Сформировать
код для FastScript> :
procedure
TForm1.Button1Click(Sender: TObject);
begin
Memo_Res.Lines.Clear;
SP_fs_FormDesign1.SaveToFile_FS; //Формируем
исходник
для
FastScript
//--------------------------------
//Для наглядности выведем на экран
if
FileExists(SP_fs_FormDesign1.FileName) then begin
Memo_Res.Lines.LoadFromFile(SP_fs_FormDesign1.FileName);
end;
//--------------------------------
end;
5)
Скомпилировать проект, запустить на
выполнение и нажать на кнопку <Сформировать
код для FastScript>.
Если файл уже существует, то следует запрос на продолжение :
После этого, соотв. исходный код будет сформирован в текстовом файле (C:\~SP_fs_FormDesign.txt) и (для наглядности) размещен в компоненте TMemo_Res.
6) Вот, собственно, и все, чего мы хотели.
Здесь приведен текст сгенерированного исходного кода.
Для проверки нашего скрипта создадим
простой тестировщик :
fsScriptTest.exe
(скачать приложение и
исходники, 665 Кб).
Запустим его.
Скопируем через Clipboard или прочитаем из файла (кнопка ) текст нашего скрипта и выполним его (кнопка ).
ВНИМАНИЕ !!!
Перед компиляцией этого проекта (если
есть желание потренироваться) необходимо
установить пакет FastScript !!!
В результате получим :
Т.е., сгенерированный компонентом TSP_fs_FormDesign скрипт вполне корректен.
Исходный
текст компонента TSP_fs_FormDesign
Скачать исходники
компонента, 29 Кб
1) Наш компонент будет наследником от TComponent.
Создадим «пустышку» нашего компонента :
unit sp_fs_FormDesign;
interface
uses
stdctrls,
ExtCtrls, Buttons, Windows,
Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TSP_fs_FormDesign = class(TComponent) //Наш компонент
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
end;
procedure
Register;
implementation
constructor
TSP_fs_FormDesign.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
end;
destructor
TSP_fs_FormDesign.Destroy;
begin
inherited Destroy;
end;
//==============================================================
procedure Register;
begin
RegisterComponents('SP', [TSP_fs_FormDesign]);
end;
end.
2) Укажем необходимые свойства нашего
компонента
(далее, по тексту, все изменения будут
отмечены красным цветом)
type
TSP_fs_FormDesign = class(TComponent) //Наш компонент
private
{ Private declarations }
fVersion
: string;
fFileName
: string;
fCompName_IsNot_Save
: string;
fCommment
: string;
fOverwritePrompt : boolean;
fGenerateSource_for_Event : boolean;
fSource_for_Event_before_Var : boolean;
published
{ Published declarations }
property FileName : string read fFileName write
fFileName;
property ComponentsName_Not_Save : string read
fCompName_IsNot_Save write fCompName_IsNot_Save;
property Comment : string read fCommment write
fCommment;
property Version : string read fVersion;
property OverwritePrompt : boolean read
fOverwritePrompt write fOverwritePrompt default TRUE;
property fsGenerateSource_for_Event
: boolean read fGenerateSource_for_Event write fGenerateSource_for_Event default
TRUE;
property fsSource_for_Event_before_Var : boolean read
fSource_for_Event_before_Var write fSource_for_Event_before_Var;
end;
Здесь :
FileName –
полное имя файла, где будет размещен
исходный код ФОРМЫ
ComponentsName_Not_Save
- имена компонентов (через запятую)
которые не следует учитывать при генерации
исходного кода
Comment – комментарий, который будет
выведен в исходный код
Version – версия компонента (ReadOnly)
OverwritePrompt -
если TRUE, то запрос на подтверждение, если
файл с именем FileName
уже существует
fsGenerateSource_for_Event
– если TRUE,
то дополнительно будет генерироваться «пустой»
код обработчиков событий компонентов
fsSource_for_Event_before_Var
– если TRUE,
то код обработчиков событий будет размещен
ПЕРЕД объявлением глобальных переменных (где
объявлены компоненты формы). В противном
случае, после
объявления глобальных переменных.
Описания вспомогательных процедур и
функций :
AllTrim, AllTrim99,
ReplaceSubStrInString, UpCaseCyrLatStr99, saStrToInt, saBooleanToStr,
ItsNotReadOnlyDisk_1, GetNewNameFile
будут
пропущены, как несущественные в контексте
данной статьи
(исходные тексты этих функций прилагаются).
3) Перепишем метод Create нашего компонента.
implementation
Const
VersionX = '1.01 (01.03.2005)'; //Версия компонента
constructor TSP_fs_FormDesign.Create(AOwner
: TComponent);
begin
inherited Create(AOwner);
fVersion:=VersionX;
AllTrim(fFileName);
if length(fFileName)<=0 then FileName:='C:\~SP_fs_FormDesign.pas';
fOverwritePrompt:=TRUE;
fGenerateSource_for_Event:=TRUE;
AllTrim(fCommment);
AllTrim(fCompName_IsNot_Save);
if length(fCompName_IsNot_Save)>0 then begin
fCompName_IsNot_Save:=ReplaceSubStrInString(fCompName_IsNot_Save,'
',',');
fCompName_IsNot_Save:=UpCaseCyrLatStr99(fCompName_IsNot_Save);
end;
end;
Нам потребуются функции, генерирующие
текстовое представление значений
некоторых свойств визуальных компонентов
на форме. Эти функции не нуждаются в
пояснениях (исходные тексты этих функций прилагаются):
Пример
функции :
function FormStyleToStr_FS(V :
TFormStyle) : string;
//Конвертация значений типа TFormStyle в строковое представление
begin
Result:='fsNormal';
if V=fsNormal then Result:='fsNormal';
if V=fsMDIChild then Result:='fsMDIChild';
if V=fsMDIForm then Result:='fsMDIForm';
if V=fsStayOnTop then Result:='fsStayOnTop';
end;
Остальные функции построены
по этому же принципу.
Поэтому, ниже представлены только их
заголовки.
function BevelCutToStr_FS(V :
TBevelCut) : string;
function ScrollBarsToStr_FS(V : TScrollStyle) : string;
function BorderStyleToStr_FS(V : TBorderStyle)
: string;
function FormBorderStyleToStr_FS(V : TFormBorderStyle)
: string;
function AlignToStr_FS(V : TAlign) : string;
function AlignmentToStr_FS(V : TAlignment) : string;
function TextLayoutToStr_FS(V : TTextLayout) : string;
function PositionToStr_FS(V : TPosition) : string;
function FontStyleToStr_FS(V : TFontStyles) : string;
function WindowStateToStr_FS(V : TWindowState) : string;
function CheckBoxStateToStr_FS(V : TCheckBoxState) : string;
Определим константы, соотв.
разным типам визуальных компонентов на
форме :
uses
stdctrls, ExtCtrls, Buttons,
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
//Константы
для идентификации типов компонентов на
форме
Const
tc_Is_TPanel
= 1;
tc_Is_TSplitter
= 2;
tc_Is_TGroupBox = 3;
tc_Is_TCheckBox = 4;
tc_Is_TRadioButton = 5;
tc_Is_TButton
= 6;
tc_Is_TSpeedButton = 7;
tc_Is_TLabel
= 8;
tc_Is_TMemo
= 9;
tc_Is_TListBox =
10;
tc_Is_TEdit
= 11;
Для идентификации этих
компонентов, напишем след. методы :
public
{ Public declarations }
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
//Вспомогательная
: Идентификация Типа компонента
function GetTypeControl_FS(Comp : TComponent) : integer;
//Вспомогательная
: Идентификация Типа компонента (наименование
типа)
function GetTypeNameControl_FS(Comp : TComponent) : string;
//Вспомогательная
: вычисление имени обработчика события
function GetNameProcEvent_FS(Comp : TComponent;NameProc : string)
: string;
implementation
function
TSP_fs_FormDesign.GetTypeControl_FS(Comp : TComponent) : integer;
//"Распознаватель" типов
поддерживаемых компонентов
begin
Result:=0;
if (Comp is TPanel) then Result:=tc_is_TPanel;
if (Comp is TGroupBox) then Result:=tc_is_TGroupBox;
if (Comp is TButton) then Result:=tc_is_TButton;
if (Comp is TSpeedButton) then Result:=tc_is_TSpeedButton;
if (Comp is TLabel) then Result:=tc_is_TLabel;
if (Comp is TEdit) then Result:=tc_is_TEdit;
if (Comp is TListBox) then Result:=tc_is_TListBox;
if (Comp is TMemo) then Result:=tc_is_TMemo;
if (Comp is TSplitter) then Result:=tc_Is_TSplitter;
if (Comp is TCheckBox) then Result:=tc_Is_TCheckBox;
if (Comp is TRadioButton) then Result:=tc_Is_TRadioButton;
end;
function
TSP_fs_FormDesign.GetTypeNameControl_FS(Comp : TComponent) : string;
//Конвертировать тип компонента в текстовое значение
begin
Result:='';
if (Comp is TPanel) then Result:='TPanel';
if (Comp is TGroupBox) then Result:='TGroupBox';
if (Comp is TButton) then Result:='TButton';
if (Comp is TSpeedButton) then Result:='TSpeedButton';
if (Comp is TLabel) then Result:='TLabel';
if (Comp is TEdit) then Result:='TEdit';
if (Comp is TListBox) then Result:='TListBox';
if (Comp is TMemo) then Result:='TMemo';
if (Comp is TSplitter) then Result:='TSplitter';
if (Comp is TCheckBox) then Result:='TCheckBox';
if (Comp is TRadioButton) then Result:='TRadioButton';
end;
function
TSP_fs_FormDesign.GetNameProcEvent_FS(Comp : TComponent;NameProc : string) :
string;
//Сформировать заголовок процедуры (обработчик
события) для заданного компонента
begin
Result:='';
AllTrim(NameProc);
if length(NameProc)>0 then begin
if GetTypeControl_FS(Comp)>0 then
begin
Result:='procedure '+Comp.Name+'_'+NameProc+'(Sender: '+GetTypeNameControl_FS(Comp)+');';
end;
end;
end;
Теперь напишем метод, который будет генерировать «пустышки» для обработчиков событий визуальных компонентов на форме. Полный текст метода приведен в исходниках компонента (прилагается). Здесь отметим лишь некоторые его фрагменты.
public
{ Public declarations }
function GetNameProcEvent_FS(Comp : TComponent;NameProc : string) :
string;
//Метод,
формирующий текст обработчиков событий
//для
каждого «известного» визуального
компонента на форме.
function
Create_Source_for_Event_FS(Form99 : TForm; List : TStrings) : integer;
implementation
Здесь, Form99
это форма, для которой создается скрипт.
List – список (TStrings),
где будет размещен текст формируемого
скрипта.
function
TSP_fs_FormDesign.Create_Source_for_Event_FS (Form99 : TForm; List
: TStrings) : integer;
//Сгенерировать исходный код обработчиков
событий для FastScript
Var
TypeComp : integer;
Tmp : TComponent;
i : integer;
SxCN : string;
Sx : string;
begin
Result:=0;
if fGenerateSource_for_Event then begin
Если
свойство fsGenerateSource_for_Event
= TRUE, то генерируем «пустышки» для
обработчиков событий.
Чтобы
упростить проверку свойства ComponentsName_Not_Save (перечень
имен компонентов, для которых не следует
генерировать код) – нормализуем это
свойство (так, чтобы имена компонентов были
разделены запятыми).
AllTrim(fCompName_IsNot_Save);
if length(fCompName_IsNot_Save)>0 then begin
fCompName_IsNot_Save:=ReplaceSubStrInString(fCompName_IsNot_Save,'
',',');
fCompName_IsNot_Save:=UpCaseCyrLatStr99(fCompName_IsNot_Save);
end;
Опять же,
для упрощения, в конце строки (значение
свойства ComponentsName_Not_Save) добавим запятую.
SxCN:=fCompName_IsNot_Save;
if length(SxCN)>0 then
begin
if SxCN[length(SxCN)]<>','
then SxCN:=SxCN+',';
end;
List.Add('//*************************************');
List.ADD('//Обработчики
событий для элементов управления на форме');
Сканируем список
компонентов формы, выделяем из них только «известные»
и «разрешенные»
for
i := 0 to (Form99.ComponentCount - 1) do
//цикл
по списку
компонентов
begin
Tmp :=
Form99.Components[i];
//читаем
очередной
компонент
TypeComp:=GetTypeControl_FS(Tmp);
//определяем
тип
компонента
if
TypeComp>0
then
begin
//продолжаем, если тип – «известный»
if
POS(UpCaseCyrLatStr99(Tmp.Name)+',',SxCN)<=0 then begin
//продолжаем, если этот компонент НЕ
указан в свойстве ComponentsName_Not_Save
//Здесь будет генерироваться исходный
код для
//«пустышек» обработчиков событий по
каждому компоненту
end;
end;
end;
List.Add('');
List.Add('//*************************************');
Если все Ok
, то мы можем генерировать код для
обработчиков событий данного компонента.
Для примера, рассмотрим только один
компонент (TEdit).
Остальные – по тому же принципу.
if TypeComp=tc_is_TEdit then begin
Это компонент TEdit
– генерируем код
List.Add('//......................................');
List.Add('//'+Tmp.Name);
Генерируем «пустышку»
обработчика для события OnClick
Sx:=Alltrim99(GetNameProcEvent_FS(Tmp,'Click'));
if length(Sx)>0 then begin
List.Add(Sx);
List.Add('//Event
: OnClick');
List.Add('begin');
List.Add('');
List.Add('end;');
end;
List.Add('');
Генерируем «пустышку»
обработчика для события OnDblClick
Sx:=Alltrim99(GetNameProcEvent_FS(Tmp,'DblClick'));
if length(Sx)>0 then begin
List.Add(Sx);
List.Add('//Event
: OnDblClick');
List.Add('begin');
List.Add('');
List.Add('end;');
end;
List.Add('');
Генерируем «пустышку»
обработчика для события OnMouseMove
Sx:=Alltrim99(GetNameProcEvent_FS(Tmp,'MouseMove'));
if length(Sx)>0 then begin
List.Add(Sx);
List.Add('//Event
: OnMouseMove');
List.Add('begin');
List.Add('');
List.Add('end;');
end;
List.Add('');
Генерируем «пустышку»
обработчика для события OnEnter
Sx:=Alltrim99(GetNameProcEvent_FS(Tmp,'Enter'));
if length(Sx)>0 then begin
List.Add(Sx);
List.Add('//Event
: OnEnter');
List.Add('begin');
List.Add('');
List.Add('end;');
end;
List.Add('');
Генерируем «пустышку»
обработчика для события OnExit
Sx:=Alltrim99(GetNameProcEvent_FS(Tmp,'Exit'));
if length(Sx)>0 then begin
List.Add(Sx);
List.Add('//Event
: OnExit');
List.Add('begin');
List.Add('');
List.Add('end;');
end;
List.Add('//......................................');
end;
Т.е., здесь все прозрачно и просто.
Для остальных компонентов используется такой же подход.
И, наконец, напишем метод, который и
будет генерировать исходный код для FastScript
:
public
{ Public declarations }
function Create_Source_for_Event_FS(Form99 : TForm;
List : TStrings) : integer;
//формирование исходников
в список List
function
CreateScript_FormDesign_For_FS(Form99 : TForm; List : TStrings) : integer;
implementation
Как и раньше, коснемся только существенных
фрагментов кода этого метода.
Заголовок метода
:
function TSP_fs_FormDesign.CreateScript_FormDesign_For_FS
(Form99 : TForm; List : TStrings) : integer;
//Сгенерировать исходный код заданной формы
(Form99) для FastScript
Здесь,
Form99
– форма, для которой генерируется исходный
код (для FastScript)
List
– список (TStrings),
где будет размещен сгенерированный
исходный код.
Явно укажем интерпретатору FastScript,
что синтаксис кода - Pascal
:
List.ADD('#language
PascalScript');
Если свойство fsSource_for_Event_before_Var = TRUE, генерируем код «пустышек» обработчиков событий компонентов ПЕРЕД объявлением переменных
if fSource_for_Event_before_Var then begin
List.Add('');
Create_Source_for_Event_FS(Form99,List);
List.Add('');
end;
Формируем список переменных (компоненты,
которые размещены на форме).
Имя формы (в FastScript)
будет всегда : FormMain.
List.Add('//Список
переменных');
List.Add('Var');
List.Add(' NrRes
: integer; //Возвращаемое значение, если ShowModal');
List.Add(' FormMain
: TForm; //Создаваемая форма');
Сканируем
список компонентов формы, выделяем из них
только «известные» и «разрешенные»
for i := 0 to (Form99.ComponentCount - 1) do //цикл
по
списку
компонентов
begin
Tmp :=
Form99.Components[i];
//читаем
очередной
компонент
TypeComp:=GetTypeControl_FS(Tmp);
//определяем
тип
компонента
if
TypeComp>0 then begin
//продолжаем,
если тип – «известный»
if POS(UpCaseCyrLatStr99(Tmp.Name)+',',SxCN)<=0 then
begin
//продолжаем, если этот компонент НЕ
указан в свойстве ComponentsName_Not_Save
Sx:=' '+Tmp.Name+' : ';
Sx:=Sx+GetTypeNameControl_FS(Tmp);
Sx:=Sx+';';
List.Add(Sx);
end;
end;
end;
Если свойство fsSource_for_Event_before_Var = FALSE,
генерируем код «пустышек» обработчиков
событий компонентов ПОСЛЕ объявлениея
переменных
if not fSource_for_Event_before_Var then begin
List.Add('');
Create_Source_for_Event_FS(Form99,List);
List.Add('');
end;
Теперь, сгенерируем код функции, которая
будет создавать форму и компоненты на ней.
Ест-нно, что сама функция не будет ничего
создавать.
Создавать будет интепретатор FastScript
по «указанию» этой функции.
Функция Create_FormMain
возвращает значение типа TForm.
Рассмотрим только существенные фрагменты
кода :
List.Add('function
Create_FormMain : TForm;');
List.Add('//Создаем
форму и соотв. компоненты на ней ...');
List.ADD('Var');
List.ADD('
Yes : boolean;');
List.ADD('begin');
Вспомогательная переменная Yes
используется, как признак того, что процесс
создания формы и
компонентов на ней закончился успешно. Это
для нужно для того, чтобы в случае «сбоя» (Yes=FALSE)
освободить ресурсы.
По умолчанию присвоим переменной Yes
значение FALSE.
Это значит, что ежели мы «не доберемся до
конца», то по этому признаку в разделе FINALLY
… END сможем
освободить занятые ресурсы.
List.ADD('
Yes := FALSE;');
Сначала, создадим форму (она
будет являться владельцем всех остальных
создаваемых компонентов).
List.ADD('
Result := TForm.Create(nil);');
Весь дальнейший код защитим конструкцией TRY
… FINALLY … END
для того, чтобы в случае «сбоя» освободить
ресурсы.
List.ADD('
TRY');
Генерируем код для инициализации соотв.
свойств формы.
List.Add('
//------------------------');
List.ADD('
//Свойства формы');
List.ADD('
Result.Caption := '+#39+Form99.Caption+#39+';');
List.ADD(' Result.Left
:= '+IntTostr(Form99.Left)+';');
List.ADD(' Result.Top
:= '+IntTostr(Form99.Top)+';');
List.ADD(' Result.Width
:= '+IntTostr(Form99.Width)+';');
List.ADD(' Result.Height
:= '+IntTostr(Form99.Height)+';');
List.ADD(' Result.FormStyle
:= '+FormStyleToStr_FS(Form99.FormStyle)+';');
List.ADD(' Result.Position
:= '+PositionToStr_FS(Form99.Position)+';');
List.ADD(' Result.BorderStyle
:= '+FormBorderStyleToStr_FS(Form99.BorderStyle)+';');
List.ADD(' Result.BorderWidth
:= '+IntToStr(Form99.BorderWidth)+';');
List.ADD(' Result.WindowState
:= '+WindowStateToStr_FS(Form99.WindowState)+';');
List.ADD(' Result.Color
:= '+ColorToString(Form99.Color)+';');
List.ADD(' Result.Font.Name
:= '+#39+Form99.Font.Name+#39+';');
List.ADD(' Result.Font.Size
:= '+IntToStr(Form99.Font.Size)+';');
List.ADD(' Result.Font.Color
:= '+ColorToString(Form99.Font.Color)+';');
if length(FontStyleToStr_FS(Form99.Font.Style))>0
then begin
List.ADD(' Result.Font.Style
:= '+FontStyleToStr_FS(Form99.Font.Style)+';');
end;
List.ADD(' Result.Font.CharSet
:= '+IntToStr(Form99.Font.CharSet)+';');
List.Add(' //------------------------');
Теперь создадим остальные компоненты на форме и инициализируем их свойства.
Для этого, сканируем список компонентов формы, выделяем из них только «известные» и «разрешенные» (рассмотрим только существенные фрагменты кода).
for i := 0 to (Form99.ComponentCount - 1) do //цикл
по
списку
компонентов
begin
Tmp :=
Form99.Components[i];
//читаем
очередной
компонент
TypeComp:=GetTypeControl_FS(Tmp);
//определяем
тип
компонента
if
TypeComp>0 then begin
//продолжаем,
если тип – «известный»
if POS(UpCaseCyrLatStr99(Tmp.Name)+',',SxCN)<=0 then
begin
//продолжаем, если этот компонент НЕ
указан в свойстве ComponentsName_Not_Save
//Здесь
мы разместим участок кода, создающего
очередной компонент.
end;
end;
end;
Процесс создания очередного
компонента достаточно прост.
По типу компонента (TypeComp)
вызываем конструктор соотв. типа
компонента.
Например, если тип
создаваемого компонента : TPanel,
то вызываем соотв. конструктор
if TypeComp=tc_is_TPanel then begin
List.ADD('
'+Tmp.Name+'
:= TPanel.Create(Result);');
end;
Например, если тип создаваемого компонента : TGroupBox, то вызываем соотв. конструктор
if
TypeComp=tc_is_TGroupBox then begin
List.ADD('
'+Tmp.Name+'
:= TGroupBox.Create(Result);');
end;
Следует отметить, что в
качестве параметра вызываемого
конструктора мы передаем созданную ранее
форму (Result).
Теперь, нужно присвоить
свойству Parent
каждого создаваемого компонента соотв.
значение :
if UpCaseCyrLatStr99((Tmp as
TControl).Parent.Name) = UpCaseCyrLatStr99(Form99.Name) then begin
//Это - форма
List.ADD('
'+Tmp.Name+'.Parent := Result;');
end
else begin
//Это – другой компонент на
форме
List.ADD('
'+Tmp.Name+'.Parent := '+(Tmp as TControl).Parent.Name+';');
end;
И т.д., для всех компонентов формы.
Теперь (после того, как
очередной компонент создан) –
инициализируем свойства компонента.
Воспользовавшись
тем, что все наши компоненты
(TPanel,
TGroupBox, TButton,
TSpeedButton,
TLabel, TEdit,
TListBox, TMemo,
TSplitter, TCheckBox,
TRadioButton)
являются наследниками TControl, инициализируем соотв.
свойства (независимо от типа компонента).
List.ADD(' '+Tmp.Name+'.Left
:= '+IntTostr((Tmp as TControl).Left)+';');
List.ADD(' '+Tmp.Name+'.Top
:= '+IntTostr((Tmp as TControl).Top)+';');
List.ADD(' '+Tmp.Name+'.Width
:= '+IntTostr((Tmp as TControl).Width)+';');
List.ADD(' '+Tmp.Name+'.Height
:= '+IntTostr((Tmp
as TControl).Height)+';');
List.ADD(' '+Tmp.Name+'.Visible := '+saBooleanToStr((Tmp as TControl).Visible,1)+';');
List.ADD(' '+Tmp.Name+'.Tag
:= '+IntToStr((Tmp as TControl).Tag)+';');
После этого, установим «специфичные»
свойства для каждого компонента, в
зависимости от его типа. Например, для типа TPanel
:
if
TypeComp=tc_is_TPanel then begin
List.Add('
'+Tmp.Name+'.Caption := '+#39+(Tmp as TPanel).Caption+#39+';');
List.ADD('
'+Tmp.Name+'.Align := '+AlignToStr_FS((Tmp as TPanel).Align)+';');
List.ADD('
'+Tmp.Name+'.Color := '+ColorToString((Tmp
as TPanel).Color)+';');
List.ADD('
'+Tmp.Name+'.Font.Name := '+#39+(Tmp as TPanel).Font.Name+#39+';');
List.ADD('
'+Tmp.Name+'.Font.Size := '+IntToStr((Tmp as TPanel).Font.Size)+';');
List.ADD('
'+Tmp.Name+'.Font.Color := '+ColorToString((Tmp as TPanel).Font.Color)+';');
if length(FontStyleToStr_FS((Tmp as TPanel).Font.Style))>0
then begin
List.ADD('
'+Tmp.Name+'.Font.Style := '+FontStyleToStr_FS((Tmp
as TPanel).Font.Style)+';');
end;
List.ADD('
'+Tmp.Name+'.Font.CharSet := '+IntToStr((Tmp as TPanel).Font.CharSet)+';');
List.ADD('
'+Tmp.Name+'.BevelWidth
:= '+IntToStr((Tmp as TPanel).BevelWidth)+';');
List.ADD('
'+Tmp.Name+'.BorderWidth
:= '+
IntToStr((Tmp as TPanel).BorderWidth) +';');
List.ADD('
'+Tmp.Name+'.BevelInner := '+ BevelCutToStr_FS((Tmp as TPanel).BevelInner)
+';');
List.ADD('
'+Tmp.Name+'.BevelOuter
:= '+ BevelCutToStr_FS((Tmp as TPanel).BevelOuter)
+';');
List.ADD('
'+Tmp.Name+'.TabOrder := '+ IntToStr((Tmp as TPanel).TabOrder)
+';');
List.ADD('
'+Tmp.Name+'.TabStop := '+
saBooleanToStr((Tmp as TPanel).TabStop,1) +';');
List.ADD(' '+Tmp.Name+'.AutoSize
:= '+ saBooleanToStr((Tmp as TPanel).AutoSize,1) +';');
List.ADD('
'+Tmp.Name+'.Enabled := '+saBooleanToStr((Tmp as TPanel).Enabled,1)+';');
List.ADD('
'+Tmp.Name+'.Hint := '+#39+(Tmp as TPanel).Hint+#39+';');
List.ADD(' '+Tmp.Name+'.ShowHint := '+saBooleanToStr((Tmp as TPanel).ShowHint,1)+';');
Если свойство fsGenerateSource_for_Event = TRUE – то ранее были сформированы «пустышки» для обработчиков событий. Теперь нужно эти «пустышки» присвоить соотв. обработчикам событий созданного компонента :
if fGenerateSource_for_Event then begin
List.ADD('
'+Tmp.Name+'.OnClick := @'+Tmp.Name+'_Click'+';');
List.ADD('
'+Tmp.Name+'.OnDblClick := @'+Tmp.Name+'_DblClick'+';');
List.ADD('
'+Tmp.Name+'.OnMouseMove := @'+Tmp.Name+'_MouseMove'+';');
end;
end;
Остальные процедуры и
функции созданного скрипта – не вызывают
какого-либо интереса.
Процедура Free_FormMain
предназначена для того, чтобы освободить
ресурсы, занятые формой FormMain.
Функция FormMain_Execute
предназначена для удобства создания,
инициализации и визуализации Формы с
последующим освобождением ресурсов формы.
Завершающий код функции
Create_FormMain
предназначен для того, чтобы в случае «сбоя»
освободить ресурсы, занятые созданной
формой.После того, как цикл по создаваемым
компонентам формы завершен, установим
переменную Yes =
TRUE.
В противном случае, внутри блока FINALLY
… END будет
выполнена попытка освободить ресурсы,
занятые формой.
List.ADD('
Yes
:= TRUE;');
List.ADD('
FINALLY');
List.ADD('
if
not Yes
then begin');
List.ADD(' if
Result<>NIL then begin');
List.ADD('
//Освобождаем
ресурсы, если неудачно ...');
List.ADD('
Result.Free;');
List.ADD('
Result:=NIL;');
List.ADD('
end;');
List.ADD('
end;');
List.ADD('
END;');
List.ADD('end;
//Create_FormMain');
Вот, собственно, и все, что «умеет»
делать метод CreateScript_FormDesign_For_FS
нашего компонента (TSP_fs_FormDesign).
Для удобства использования нашего
компонента (TSP_fs_FormDesign)
– интегрируем вызовы
соотв. методов таким образом, чтобы можно
было сгенерировать соотв. скрипт вызовом
одного метода (SaveToFile_FS)
с сохранением текста скрипта в заданный
файл.
Никакого интереса текст этого метода не
представляет и здесь не приводится.
FastScript - великолепный пакет (рекомендую)
!!!
***********************************
Правами
на на пакет FastScript обладает :
Fast Reports Inc.
Author: Alexander Tzyganenko
e-mail: tz@fast-report.com
home page: http://www.fastreport.ru
http://www.fast-report.com
***********************************
Данная статья
(и все исходные тексты, что к ней
прилагаются) имеет статус Freeware.
Т.е., можно использовать все это по своему
усмотрению.
Но … Автор совершенно не
обидится, ежели при использовании
материалов этой статья будет указываться
ссылка на эту статью …
Вариант статьи в формате MS
WORD (включая исходники и примеры), 1106 Кб
Данный документ (html-формат) "висит" на
адресе :
http://spcalc.narod.ru/tsp_fs_formdesign/sp_fs_formdesign.htm