-
Здравствуйте, уважаемые. Вопрос по экспертам, такой. Имеется шаблон плагина и формы настроек. Я сделал эксперта (спасибо доброму человеку за исходники, в которые я внимательно смотрел), который генерирует исходники проекта плагина и модуля реализации. Но у меня не получается сгенерировать исходники формы. Подскажите, пожалуйста, как нужно делать/где почитать.
Основная проблема как раз в том, что всё это должно быть в одном эксперте.
-
> Но у меня не получается сгенерировать исходники формы.
Я когда-то развлекался, вроде генерируется и .pas и .dfm unit TestRepositoryWizard;
interface
uses
Windows, Classes, ToolsApi;
type
TTestClassGenerator = class(TInterfacedObject, IOTACreator, IOTAModuleCreator)
private
FUnitIdent : String;
FClassName : String;
public
function GetAncestorName : String;
function GetImplFileName : String;
function GetIntfFileName : String;
function GetFormName : String;
function GetMainForm : Boolean;
function GetShowForm : Boolean;
function GetShowSource : Boolean;
function NewFormFile(const FormIdent, AncestorIdent : String) : IOTAFile;
function NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent : String) : IOTAFile;
function NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent : String) : IOTAFile;
procedure FormCreated (const FormEditor : IOTAFormEditor);
function GetCreatorType: String;
function GetExisting : Boolean;
function GetFileSystem : String;
function GetOwner : IOTAModule;
function GetUnnamed : Boolean;
constructor Create (UnitIdent, ClassName : String); virtual;
property CreatorType : String read GetCreatorType;
property Existing : Boolean read GetExisting;
property FileSystem : String read GetFileSystem;
property Owner : IOTAModule read GetOwner;
property Unnamed : Boolean read GetUnnamed;
property AncestorName : String read GetAncestorName;
property FormName : String read GetFormName;
property ImplFileName : String read GetImplFileName;
property IntfFileName : String read GetIntfFileName;
property MainForm : Boolean read GetMainForm;
property ShowForm : Boolean read GetShowForm;
property ShowSource : Boolean read GetShowSource;
end;
TTestFormWizard = class(TNotifierObject, IOTAWizard, IOTARepositoryWizard,
IOTAFormWizard, IOTACreator, IOTAModuleCreator)
private
FUnitIdent : String;
FFileName : String;
FClassName : String;
FTestClassName : String;
FTestUnitName : String;
protected
function GetIDString : String;
function GetName : String;
function GetState : TWizardState;
procedure Execute;
function GetAuthor : String;
function GetComment : String;
function GetPage : String;
function GetGlyph : Cardinal;
function GetCreatorType : String;
function GetExisting : Boolean;
function GetFileSystem : String;
function GetOwner : IOTAModule;
function GetUnnamed : Boolean;
function GetAncestorName : String;
function GetImplFileName : String;
function GetIntfFileName : String;
function GetFormName : String;
function GetMainForm : Boolean;
function GetShowForm : Boolean;
function GetShowSource : Boolean;
function NewFormFile (const FormIdent, AncestorIdent : String) : IOTAFile;
function NewImplSource (
const ModuleIdent, FormIdent, AncestorIdent : String) : IOTAFile;
function NewIntfSource (
const ModuleIdent, FormIdent, AncestorIdent : String) : IOTAFile;
procedure FormCreated (const FormEditor : IOTAFormEditor);
end;
procedure Register;
implementation
uses
SysUtils,
DesignIntf, DesignEditors,
TestAbstractForm,
TestClassDlg,
Controls, Forms;
type
TBaseFile = class(TInterfacedObject)
private
FModuleName : String;
FFormName : String;
FAncestorName : String;
public
constructor Create (const ModuleName, FormName, AncestorName : String);
end;
TUnitFile = class(TBaseFile, IOTAFile)
private
FTestClassName : String;
FTestUnitName : String;
protected
function GetSource : String;
function GetAge : TDateTime;
public
constructor Create (const ModuleName, FormName, AncestorName,
TestClassName, TestUnitName : String);
end;
TFormFile = class(TBaseFile, IOTAFile)
protected
function GetSource : String;
function GetAge : TDateTime;
end;
TTestClassFile = class(TBaseFile, IOTAFile)
protected
function GetSource : String;
function GetAge : TDateTime;
end;
procedure Register;
begin
RegisterPackageWizard(TTestFormWizard.Create);
end;
продолжение следует...
-
продолжение
procedure TTestFormWizard.Execute;
begin
with TfTestClassDlg.Create(Application) do
try
if ShowModal() <> mrOk then
Exit;
FTestClassName := ClassNameEdit.Text;
FTestUnitName := UnitNameEdit.Text;
finally
Free();
end;
(BorlandIDEServices as IOTAModuleServices).CreateModule (
TTestClassGenerator.Create(FTestUnitName, FTestClassName));
(BorlandIDEServices as IOTAModuleServices).GetNewModuleAndClassName (
'fAbstractTest', FUnitIdent, FClassName, FFileName);
(BorlandIDEServices as IOTAModuleServices).CreateModule (Self);
end;
procedure TTestFormWizard.FormCreated(const FormEditor: IOTAFormEditor);
begin
end;
function TTestFormWizard.GetAncestorName: String;
begin
Result := 'TfAbstractTest';
end;
function TTestFormWizard.GetAuthor: String;
begin
Result := 'Igor Schevchenko';
end;
function TTestFormWizard.GetComment: String;
begin
Result := 'Creates new Test Suite form';
end;
function TTestFormWizard.GetCreatorType: String;
begin
Result := '';
end;
function TTestFormWizard.GetExisting: Boolean;
begin
Result := false;
end;
function TTestFormWizard.GetFileSystem: String;
begin
Result := '';
end;
function TTestFormWizard.GetFormName: String;
begin
Result := FClassName;
end;
function TTestFormWizard.GetGlyph: Cardinal;
begin
Result := 0; end;
function TTestFormWizard.GetIDString: String;
begin
Result := 'TestSuite.NewFormWizard';
end;
function TTestFormWizard.GetImplFileName: String;
var
CurrDir : array[0..MAX_PATH] of char;
begin
GetCurrentDirectory(SizeOf(CurrDir), CurrDir);
Result := Format('%s\%s%s', [CurrDir, FUnitIdent, '.pas']);
end;
function TTestFormWizard.GetIntfFileName: String;
begin
Result := '';
end;
function TTestFormWizard.GetMainForm: Boolean;
begin
Result := false;
end;
function TTestFormWizard.GetName: String;
begin
Result := 'Test Suite New Form Wizard';
end;
function TTestFormWizard.GetOwner: IOTAModule;
var
I : Integer;
ModServ : IOTAModuleServices;
Module : IOTAModule;
ProjGrp : IOTAProjectGroup;
begin
Result := nil;
ModServ := BorlandIDEServices as IOTAModuleServices;
for I:=0 to Pred(ModServ.ModuleCount) do begin
Module := ModServ.Modules[I];
if CompareText(ExtractFileExt(Module.FileName), '.bpg') = 0 then
if Module.QueryInterface (IOTAProjectGroup, ProjGrp) = S_OK then begin
Result := ProjGrp.GetActiveProject;
Exit;
end;
end;
end;
function TTestFormWizard.GetPage: String;
begin
Result := 'TestSuite';
end;
function TTestFormWizard.GetShowForm: Boolean;
begin
Result := true;
end;
function TTestFormWizard.GetShowSource: Boolean;
begin
Result := true;
end;
function TTestFormWizard.GetState: TWizardState;
begin
Result := [wsEnabled];
end;
function TTestFormWizard.GetUnnamed: Boolean;
begin
Result := true;
end;
function TTestFormWizard.NewFormFile(const FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := TFormFile.Create('', FormIdent, AncestorIdent);
end;
function TTestFormWizard.NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := TUnitFile.Create(ModuleIdent, FormIdent, AncestorIdent,
FTestClassName, FTestUnitName);
end;
function TTestFormWizard.NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := nil;
end;
-
constructor TBaseFile.Create(const ModuleName, FormName,
AncestorName: String);
begin
inherited Create;
FModuleName := ModuleName;
FFormName := FormName;
FAncestorName := AncestorName;
end;
constructor TUnitFile.Create(const ModuleName, FormName, AncestorName,
TestClassName, TestUnitName: String);
begin
inherited Create (ModuleName, FormName, AncestorName);
FTestClassName := TestClassName;
FTestUnitName := TestUnitName;
end;
function TUnitFile.GetAge: TDateTime;
begin
Result := -1;
end;
function TUnitFile.GetSource: String;
var
Text : String;
ResInstance : THandle;
HRes : HRSRC;
begin
ResInstance := FindResourceHinstance (HInstance);
HRes := FindResource(ResInstance, 'CODEGEN', RT_RCDATA);
Text := PChar(LockResource(LoadResource(ResInstance,HRes)));
SetLength(Text, SizeOfResource(ResInstance, HRes));
Result := Format(Text, [FModuleName, FFormName, FAncestorName,
FTestClassName, FTestUnitName]);
end;
function TFormFile.GetAge: TDateTime;
begin
Result := -1;
end;
function TFormFile.GetSource: String;
const
FormText = 'inherited %0:s: T%0:s'#13#10'end';
begin
Result := Format(FormText, [FFormName]);
end;
constructor TTestClassGenerator.Create(UnitIdent, ClassName: String);
begin
FUnitIdent := UnitIdent;
FClassName := ClassName;
end;
procedure TTestClassGenerator.FormCreated(
const FormEditor: IOTAFormEditor);
begin
end;
function TTestClassGenerator.GetAncestorName: String;
begin
Result := ''; end;
function TTestClassGenerator.GetCreatorType: String;
begin
Result := '';
end;
function TTestClassGenerator.GetExisting: Boolean;
begin
Result := false; end;
function TTestClassGenerator.GetFileSystem: String;
begin
Result := '';
end;
function TTestClassGenerator.GetFormName: String;
begin
Result := FClassName;
end;
function TTestClassGenerator.GetImplFileName: String;
var
Buffer : array[0..MAX_PATH] of char;
begin
GetCurrentDirectory (SizeOf(Buffer), Buffer);
Result := Format ('%s\%s.pas', [Buffer, FUnitIdent]);
end;
function TTestClassGenerator.GetIntfFileName: String;
begin
Result := '';
end;
function TTestClassGenerator.GetMainForm: Boolean;
begin
Result := false;
end;
function TTestClassGenerator.GetOwner: IOTAModule;
var
I : Integer;
ModServ : IOTAModuleServices;
Module : IOTAModule;
ProjGrp : IOTAProjectGroup;
Project : IOTAProject;
begin
Result := nil;
ModServ := BorlandIDEServices as IOTAModuleServices;
for I:=0 to Pred(ModServ.ModuleCount) do begin
Module := ModServ.Modules[I];
if Module.QueryInterface(IOTAProjectGroup, ProjGrp) = S_OK then begin
Result := ProjGrp.ActiveProject;
Break;
end else if Module.QueryInterface(IOTAProject, Project) = S_OK then begin
Result := Project;
Break;
end;
end;
end;
function TTestClassGenerator.GetShowForm: Boolean;
begin
Result := false;
end;
function TTestClassGenerator.GetShowSource: Boolean;
begin
Result := true;
end;
function TTestClassGenerator.GetUnnamed: Boolean;
begin
Result := false;
end;
function TTestClassGenerator.NewFormFile(const FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := nil;
end;
function TTestClassGenerator.NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := TTestClassFile.Create(ModuleIdent, FormIdent, AncestorIdent);
end;
function TTestClassGenerator.NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := nil;
end;
function TTestClassFile.GetAge: TDateTime;
begin
Result := -1;
end;
function TTestClassFile.GetSource: String;
var
Text : String;
ResInstance : THandle;
HRes : HRSRC;
begin
ResInstance := FindResourceHinstance (HInstance);
HRes := FindResource(ResInstance, 'CLASSGEN', RT_RCDATA);
Text := PChar(LockResource(LoadResource(ResInstance,HRes)));
SetLength(Text, SizeOfResource(ResInstance, HRes));
Result := Format(Text, [FModuleName, FFormName]);
end;
end.
-
ну и сами ресурсы: codegen.rc CODEGEN RCDATA codegen.txt
CLASSGEN RCDATA classgen.txt classgen.txt unit %0:s;
interface
uses
Windows, Messages, SysUtils, Classes, Forms, TestAbstractTest;
type
T%1:s = class (TAbstractTest)
private
protected
procedure Setup; override;
procedure TearDown; override;
public
procedure RunTests; override;
end;
implementation
procedure T%1:s.RunTests;
begin
end;
procedure T%1:s.Setup;
begin
end;
procedure T%1:s.TearDown;
begin
end;
initialization
RegisterTestClass(T%1:s);
end. codegen.txt unit %0:s;
interface
uses
Windows, Messages, SysUtils, Classes, Forms, TestAbstractForm;
type
T%1:s = class (%2:s)
private
protected
public
procedure RunTests; override;
end;
implementation
uses
%4:s;
procedure T%1:s.RunTests;
var
TestObject : T%3:s;
begin
TestObject := T%3:s.Create(Self);
try
TestObject.RunTests();
finally
TestObject.Free();
end;
end;
end.
-
Спасибо! Старательно всё скопипастил, ушёл экспериментировать.
О результатах отпишусь.
-
А что должно содержаться в модуле TestAbstractForm ?
-
> А что должно содержаться в модуле TestAbstractForm ?
Я извиняюсь, но я выкладывал код не для копипаста, а для анализа. В модуле TestAbstractForm содержится обычная форма, никоим образом с генерацией не связанная. Точно также, как и в TestAbstractTest.
Насколько я понял, проблемы именно с генерацией, а не с воспроизведением моего кода ?
-
Именно так. Извиняюсь за копипастинг - я сначала компилировал предоставленный исходник (первоначальный, теперь Ваш), потом, меняя его текст, анализировал происходящие изменения в выдаче. Я догадался включить в ресурсы текст своей формы. Сейчас я переделал Ваш код так:
TDMFormWizard = class(TNotifierObject, IOTAWizard, IOTARepositoryWizard,
IOTAFormWizard, IOTACreator, IOTAModuleCreator)
private
FTestClassName : String;
FTestUnitName : String;
FOptions:TDMPluginWizardOptions;
protected
function GetIDString : String;
function GetName : String;
function GetState : TWizardState;
procedure Execute; overload;
procedure Execute(Options: TDMPluginWizardOptions); overload;
function GetAuthor : String;
function GetComment : String;
function GetPage : String;
function GetGlyph : Cardinal;
function GetCreatorType : String;
function GetExisting : Boolean;
function GetFileSystem : String;
function GetOwner : IOTAModule;
function GetUnnamed : Boolean;
function GetAncestorName : String;
function GetImplFileName : String;
function GetIntfFileName : String;
function GetFormName : String;
function GetMainForm : Boolean;
function GetShowForm : Boolean;
function GetShowSource : Boolean;
function NewFormFile (const FormIdent, AncestorIdent : String) : IOTAFile;
function NewImplSource (
const ModuleIdent, FormIdent, AncestorIdent : String) : IOTAFile;
function NewIntfSource (
const ModuleIdent, FormIdent, AncestorIdent : String) : IOTAFile;
procedure FormCreated (const FormEditor : IOTAFormEditor);
end;
TFormFile = class(TInterfacedObject, IInterface, IOTAFile)
private
FOptions:TDMPluginWizardOptions;
public
function GetAge:TDateTime;
function GetSource:string;
constructor Create(Options:TDMPluginWizardOptions; const FormIdent:string);
end;
...
-
...и реализация
procedure TDMFormWizard.Execute;
begin
(BorlandIDEServices as IOTAModuleServices).CreateModule (Self);
end;
procedure TDMFormWizard.Execute(Options: TDMPluginWizardOptions);
begin
FOptions:=Options;
(BorlandIDEServices as IOTAModuleServices).CreateModule (Self);
end;
procedure TDMFormWizard.FormCreated(const FormEditor: IOTAFormEditor);
begin
end;
function TDMFormWizard.GetAncestorName: String;
begin
Result := 'TForm';
end;
function TDMFormWizard.GetAuthor: String;
begin
Result := 'Alexander Kornienko';
end;
function TDMFormWizard.GetComment: String;
begin
Result := 'Creates new Download Master plugin''s setup form';
end;
function TDMFormWizard.GetCreatorType: String;
begin
Result := '';
end;
function TDMFormWizard.GetExisting: Boolean;
begin
Result := false;
end;
function TDMFormWizard.GetFileSystem: String;
begin
Result := '';
end;
function TDMFormWizard.GetFormName: String;
begin
Result:=FOptions.FormName;
end;
function TDMFormWizard.GetGlyph: Cardinal;
begin
Result := 0; end;
function TDMFormWizard.GetIDString: String;
begin
Result := 'DownloadMaster.SetupFormWizard';
end;
function TDMFormWizard.GetImplFileName: String;
begin
Result:='';
end;
function TDMFormWizard.GetIntfFileName: String;
begin
Result := '';
end;
function TDMFormWizard.GetMainForm: Boolean;
begin
Result := false;
end;
function TDMFormWizard.GetName: String;
begin
Result := 'Download Master Setup Form Wizard';
end;
function TDMFormWizard.GetOwner: IOTAModule;
var
I : Integer;
ModServ : IOTAModuleServices;
Module : IOTAModule;
ProjGrp : IOTAProjectGroup;
begin
Result := nil;
ModServ := BorlandIDEServices as IOTAModuleServices;
for I:=0 to Pred(ModServ.ModuleCount) do begin
Module := ModServ.Modules[I];
if CompareText(ExtractFileExt(Module.FileName), '.bpg') = 0 then
if Module.QueryInterface (IOTAProjectGroup, ProjGrp) = S_OK then begin
Result := ProjGrp.GetActiveProject;
Exit;
end;
end;
end;
function TDMFormWizard.GetPage: String;
begin
Result := 'DownloadMaster';
end;
function TDMFormWizard.GetShowForm: Boolean;
begin
Result := true;
end;
function TDMFormWizard.GetShowSource: Boolean;
begin
Result := true;
end;
function TDMFormWizard.GetState: TWizardState;
begin
Result := [wsEnabled];
end;
function TDMFormWizard.GetUnnamed: Boolean;
begin
Result:=false;
end;
function TDMFormWizard.NewFormFile(const FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := TFormFile.Create(Foptions , FormIdent);
end;
function TDMFormWizard.NewImplSource(const ModuleIdent, FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := nil;
end;
function TDMFormWizard.NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent: String): IOTAFile;
begin
Result := nil;
end;
constructor TFormFile.Create(Options:TDMPluginWizardOptions; const FormIdent:string);
begin
FOptions := Options;
FOptions.FormName := FormIdent;
end;
function TFormFile.GetAge:TDateTime;
begin
Result := -1;
end;
function TFormFile.GetSource:string;
begin
Result := LoadResourceText('PLUGINFORMUNIT');
Result := ReplaceMacros(Result, FOptions);
end;
В другом эксперте я создаю экземпляр TDMFormWizard, затем вызываю его Execute - и получаю AV read of address 00000000
-
Возможно, я недостаточно точно очертил задачу. В одном эксперте требуется: 1. Создать исходный текст проекта (library xxxx, dpr) 2. Создать исходный текст модуля реализации (unit xxxx_Impl, pas) 3. Создать исходный текст формы (unit xxxx_SetupForm, pas&dpr) В качестве бонуса на форме лежат два BitButton (OK и Cancel).
-
Korney San © (25.03.09 16:55) [10]
Мой эксперт генерировал форму и дополнительный модуль в уже существующем проекте, созданием проекта с нуля я не занимался, но судя по всему, это не зло не столь большой руки, было бы желание.
Насчет бонуса - так в заготовку для формы можно вставить необходимые компоненты.
Я не совсем понимаю другое - эксперт, насколько я понимаю, нужен, чтобы генерировать код по шаблону с параметрами, причем, такими параметрами, которые непосредственно влияют на сам код (имена классов, еще что-нибудь, верятно, логика работы).
А для генерации цельного проекта - а, если не секрет, что именно там параметризуется ?
-
Параметризуется следующее: 1. Имя проекта (оно же <имя файла проекта>.dpr, <имя файла модуля>_Impl.pas, <имя файла формы>SetupForm.pas/.dfm) 2. Класс плагина (он же <класс формы>SetupForm) Остальные подстановки - чисто замена шаблонов в исходниках заполненным текстом, поэтому я их здесь не привожу. Шаблон исходного кода для .dpr и .pas зашил в ресурсы, как в примерах. На текущий момент я добился того, что у меня: 1. Создаётся .dpr с заданным именем файла и "правильным" исходным текстом. 2. Создаётся .pas модуля с заданным именем файла и "правильным" исходным текстом. 3. Всё это открывается в IDE. Хочется ещё создать и файл исходного текста формы с соответствующим .dfm . Следуя исходным текстам эксперта - достаточно было бы ещё одного IOTAModuleCreator, но кто тогда создаст .dfm ?
P.S. Ваш откомпилированный эксперт создаёт и открывает форму... Завидно...
-
Korney San © (25.03.09 18:01) [12]
Насколько я вспоминаю, каждый модуль создается вызовом (BorlandIDEServices as IOTAModuleServices).CreateModule
у меня таких вызовов два, одним создается форма, другим создается дополнительный модуль - у меня эксперт создает три файла, два .pas и один .dfm
Я к чему - может, следует вызывать CreateModule столько раз, сколько модулей надо получить ?
-
Вы не поверите! После вашего совета я всё-таки справился с этой задачкой! Немного ковыряния в справке, и вот оно:
type
TFormCreator = class(TInterfacedObject, IInterface, IOTACreator, IOTAModuleCreator)
private
FOwner:IOTAModule;
FOptions:TDMPluginWizardOptions;
public
procedure FormCreated(const FormEditor:IOTAFormEditor);
function GetAncestorName:string;
function GetCreatorType:string;
function GetExisting:Boolean;
function GetFileSystem:string;
function GetFormName:string;
function GetImplFileName:string;
function GetIntfFileName:string;
function GetMainForm:Boolean;
function GetOwner:IOTAModule;
function GetShowForm:Boolean;
function GetShowSource:Boolean;
function GetUnnamed:Boolean;
function NewFormFile(const FormIdent:string;
const AncestorIdent:string):IOTAFile;
function NewImplSource(const ModuleIdent:string;
const FormIdent:string; const AncestorIdent:string):IOTAFile;
function NewIntfSource(const ModuleIdent:string;
const FormIdent:string; const AncestorIdent:string):IOTAFile;
constructor Create(const Owner:IOTAModule; Options:TDMPluginWizardOptions);
end;
TFormImpl = class(TInterfacedObject, IInterface, IOTAFile)
private
FOptions:TDMPluginWizardOptions;
public
function GetAge:TDateTime;
function GetSource:string;
constructor Create(Options:TDMPluginWizardOptions; const FormIdent:string);
end;
constructor TFormCreator.Create(const Owner:IOTAModule; Options:TDMPluginWizardOptions);
begin
FOwner := Owner;
FOptions := Options;
end;
procedure TFormCreator.FormCreated(const FormEditor:IOTAFormEditor);
var
Container: IOTAComponent;
begin
Container:=nil;
FormEditor.CreateComponent(nil, 'TBitBtn', 96, 200, 75, 25);
FormEditor.CreateComponent(nil, 'TBitBtn', 280, 200, 75, 25);
end;
function TFormCreator.GetAncestorName:string;
begin
Result := '';
end;
function TFormCreator.GetCreatorType:string;
begin
Result:=sForm; end;
function TFormCreator.GetExisting:Boolean;
begin
Result := false;
end;
function TFormCreator.GetFileSystem:string;
begin
Result := '';
end;
function TFormCreator.GetFormName:string;
begin
Result:=Copy(FOptions.FormClassName, 2, 255); end;
function TFormCreator.GetImplFileName:string;
begin
Result:=FOptions.FormUnitName+'.pas';
end;
function TFormCreator.GetIntfFileName:string;
begin
Result := '';
end;
function TFormCreator.GetMainForm:Boolean;
begin
Result := false;
end;
function TFormCreator.GetOwner:IOTAModule;
begin
Result := FOwner;
end;
function TFormCreator.GetShowForm:Boolean;
begin
Result := true;
end;
function TFormCreator.GetShowSource:Boolean;
begin
Result := true;
end;
function TFormCreator.GetUnnamed:Boolean;
begin
Result:=false;
end;
function TFormCreator.NewFormFile(const FormIdent, AncestorIdent:string):IOTAFile;
begin
Result := nil;
end;
function TFormCreator.NewImplSource(const ModuleIdent, FormIdent, AncestorIdent:string):IOTAFile;
begin
Result := TFormImpl.Create(FOptions, FormIdent);
end;
function TFormCreator.NewIntfSource(const ModuleIdent, FormIdent,
AncestorIdent:string):IOTAFile;
begin
Result := nil;
end;
constructor TFormImpl.Create(Options:TDMPluginWizardOptions; const FormIdent:string);
begin
FOptions := Options;
FOptions.FormUnitName := FormIdent;
end;
function TFormImpl.GetAge:TDateTime;
begin
Result := -1;
end;
function TFormImpl.GetSource:string;
begin
Result := LoadResourceText('PLUGINFORMUNIT');
Result := ReplaceMacros(Result, FOptions);
end;
Теперь мне осталось узнать, как изменить свойства полученной формы (в частности, BorderType) и повесить на созданные кнопки обработчики, прописанные в тексте...
-
Разобрался, как изменять свойства созданной формы:
procedure TFormCreator.FormCreated(const FormEditor:IOTAFormEditor);
var
OContainer: IOTAComponent;
NContainer: INTAComponent;
Component: TComponent;
procedure RefClean;
begin
Component:=nil;
NContainer:=nil;
OContainer:=nil;
end;
begin
RefClean;
OContainer:=FormEditor.GetRootComponent;
OContainer.QueryInterface(INTAComponent, NContainer);
Component:=NContainer.GetComponent;
(Component as TForm).BorderStyle:=bsSingle;
(Component as TForm).Caption:='frmSetupForm';
(Component as TForm).ClientHeight:=250;
(Component as TForm).ClientWidth:=457;
(Component as TForm).Position:=poMainFormCenter;
RefClean;
OContainer:=FormEditor.CreateComponent(nil, 'TBitBtn', 96, 200, 75, 25);
OContainer.QueryInterface(INTAComponent, NContainer);
Component:=NContainer.GetComponent;
(Component as TBitBtn).Kind:=bkOk;
RefClean;
OContainer:=FormEditor.CreateComponent(nil, 'TBitBtn', 280, 200, 75, 25);
OContainer.QueryInterface(INTAComponent, NContainer);
Component:=NContainer.GetComponent;
(Component as TBitBtn).Kind:=bkCancel;
RefClean;
end;
Остался последний вопрос - как назначить/связать с названием, указанным в тексте шаблона, обработчик события, к примеру, OnCreate формы?
-
> Остался последний вопрос - как назначить/связать с названием, > указанным в тексте шаблона, обработчик события, к примеру, > OnCreate формы?
Я бы при генерации задавал, генерируется же простой текстовый файл, как .dfm, так и .pas, и я полагаю, что при открытии сгенерированного файла происходит точно такой же его синтаксический разбор, как и при обычном открытии.
-
Ээээ... а как оно собразит такой код
(Component as TForm).OnCreate:=%formclass%.FormCreate;
?
-
Я в том смысле, что эксперт на момент компиляции ещё не знает, что у некого (Component as TForm) есть привнесённый FormCreate. Как компилятор будет разбираться с этой ситуацией?
-
Korney San © (27.03.09 14:32) [18]
Я немного другое имел в виду. Эскперт генерирует текстовые файлы - вот пусть он их и сгенерирует вместе с событием. То есть, назначать событие не во время работы эксперта, а во время генерации кода, в самом шаблоне.
-
Вы упускаете из виду, что как минимум одно событие должно быть назначено "вживую", для того, чтобы поназначать остальные события. Например, генерируется:
procedure TForm.FormCreate;
begin
OnDestroy:=FormDestroy;
end;
procedure TForm.FormDestroy;
begin
end;
И чтобы FormCreate сработало, его нужно "повесить" как раз во время работы эксперта. Или я что-то упускаю?
-
Вот у меня в эксперте есть генерация формы: function TFormFile.GetSource: String;
const
FormText = 'inherited %0:s: T%0:s'#13#10'end';
begin
Result := Format(FormText, [FFormName]);
end; если я FormText заменю на inherited %0:s: T%0:s'#13#10' OnCreate = FormCreate end'; а в генерируемом тексте добавлю type
T%1:s = class (%2:s)
procedure FormCreate (Sender: TObject);
private
protected
public
procedure RunTests; override;
end; и, соответственно, реализацию, разве этого не будет достаточно ?
-
Спасибо, Вы всё-таки толкнули меня на правильный путь. Я разобрался и сделал следующее:
TFormFile = class(TInterfacedObject, IInterface, IOTAFile)
private
FOptions:TDMPluginWizardOptions;
protected
function GetSource : String;
function GetAge : TDateTime;
public
constructor Create(Options:TDMPluginWizardOptions);
end;
function TFormCreator.NewFormFile(const FormIdent, AncestorIdent:string):IOTAFile;
begin
Result:= TFormFile.Create(FOptions);
end;
constructor TFormFile.Create(Options:TDMPluginWizardOptions);
begin
FOptions := Options;
end;
function TFormFile.GetAge: TDateTime;
begin
Result := -1;
end;
function TFormFile.GetSource: String;
const
FormText = 'inherited %0:s: %1:s'#13#10'OnCreate = FormCreate'#13#10'end';
begin
Result := Format(FormText, [Copy(FOptions.FormClassName, 2, 255), FOptions.FormClassName]);
end;
Форма генерируется с прописанным свойством OnCreate. Для меня данная тема завершена успешно. Огромное Вам спасибо! Надеюсь, озвученные здесь Ваши подсказки и мой опыт помогут избежать подобных "граблей" кому-то ещё... ;)
|