Адрес этой странички: 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. Это значит, что ежели мы «не доберемся до конца», то по этому признаку в разделе FINALLYEND сможем освободить занятые ресурсы. 

        List.ADD('  Yes := FALSE;');

 Сначала, создадим форму (она будет являться владельцем всех остальных создаваемых компонентов). 

        List.ADD('  Result := TForm.Create(nil);'); 

Весь дальнейший код защитим конструкцией TRYFINALLYEND для того, чтобы в случае «сбоя» освободить ресурсы. 

        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.
В противном случае, внутри блока FINALLYEND будет выполнена попытка освободить ресурсы, занятые формой.

        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

 

           

 

 

Hosted by uCoz