Registering a new class at runtime using Delphi

It is possible to create (register) a new class at runtime using delphi.

I have a class called TMyForm, it is possible to create a new form derived from TMyForm, but with a new class type.

I need something like this

var Myform : TMyForm; MyFormClassBase : TFormClass; begin MyFormClassBase := TFormClass(RegisterMyNewClass('TMyNewClass'));//obviously RegisterMyNewClass does not exist Myform := MyFormClassBase.Create(Application); Myform.Show; end; 

I am using delphi 7

UPDATE 1

I'm not looking to create a new instance of the same base class, I need to create a new type of class at runtime derived from another class.

UPDATE 2

Thanks so much for your interest. but the goal is a little complicated to explain (because my bad english). I have a form that allows you to edit several master data tables, all these tables have the same field code (integer primary key) and description (varchar field), they serve to determine currencies, countries, projects, groups, etc.

since the logic is the same for all of these tables, so this form is needed, passing as the parameters the header of the table name to manage these tables. something like that

 FormCurrency:= TMyForm.Create( 'Define currencys', 'CURRENCYTABLE') if ValidateAccess(FormCurrency) then FormCurrency.Show else FormCurrency.Close; FormGroups:= TMyForm.Create( 'Define Groups', 'GROUPSTABLE') if ValidateAccess(FormGroups) then FormGroups.Show else FormGroups.Close; 

On the other hand, I have a validation method (called ValidateAccess) that checks user access to forms using the form class. because of this, if you use the same form, this is limited access to all parameters, such as "define groups", "define currencys", "define countrys" (which I do not want this to happen), because I need pass to ValidateAccess method is another class.

I cannot rewrite the ValidateAccess method because there are many different forms already registered in the system.

I do not want to create a new type of form and a new block again and again, just changing the title and table to use.

Thanks at Advance.

0
source share
6 answers

I do not know if I understand correctly, but what I understand can be achieved in this way:

 type TCurrencyForm = class(TMyForm); TGroupsForm = class(TMyForm); FormCurrency:= TCurrencyForm.Create( 'Define currencys', 'CURRENCYTABLE') if ValidateAccess(FormCurrency) then FormCurrency.Show else FormCurrency.Close; FormGroups:= TGroupsForm.Create( 'Define Groups', 'GROUPSTABLE') if ValidateAccess(FormGroups) then FormGroups.Show else FormGroups.Close; 

In your ValidateAccess method (assuming the parameter is named Form) you can check something like:

 if Form is TCurrencyForm then else if Form is TGroupsForm then 

If you do not have access to the declarations of the new form class, you can use Form.ClassName instead.

+2
source

Looks like Uwe managed to solve your problem. I should just point out for the record that new class types can be added at runtime. Classes are defined by their reference to the class, which is a pointer to a virtual table of virtual machines (VMTs), and if you know how VMTs line up, you can create your own. Last year I had a session at CodeRage. Unfortunately, the sound quality sucked.: (

Of course, this is not very useful for you if you do not need to create classes whose definition is not available at compile time, for example, if you use the scripting mechanism. When all the information you need is available at compile time, go on to something like what is described in Uwe.

+2
source

Why do you need a new subclass of the form? You cannot change anything in this new class so that it differs from the existing class at runtime. those. You cannot add new methods or properties.

I suspect that you made a mistake believing that one form class can have only one instance. But this is not so. You can create as many instances of the form as you want:

 var formA : TMyForm; formB : TMyForm; begin formA := TMyForm.Create(Application); formB := TMyForm.Create(Application); formA.Show; formB.Show; end; 

If this is not what you need, you need to provide additional information about what exactly you are trying to achieve.

+1
source

IIUC, you can have something like this:

 TmyForm = class... //your normal form ... public property Title: string read FTitle write SetTitle; property FormKind: TFormKind read FFormKind write SetFormKind; function ValidateAccess: boolean; ... end; 

Where TFormKind = (fkCurrency, fkCountry, ...);

And the form header will also be set in your SetFormKind , in your SetFormKind you will optionally perform your initialization (s) if you will process it in ValidateAccess (most likely in the case ), depending on the value of FFormKind .

And use it:

 myForm:=TmyForm.Create(Application); //since we'll free it the owner can be also 'nil' myForm.Title:='Boo!'; myForm.Kind:=fkCurrency; if myForm.ValidateAccess then myForm.ShowModal; //btw your 'if' structure is a little bit 'odd' to say at least. You don't need to call Close on a form which isn't showing myForm.Free; //get rid of it. - of course this applies if we created it. Not applicable if you use 'Show' only, of course. 

However, you may find it better to separate the layers and have a different class to handle validation according to the properties of the form, etc.

+1
source

Delphi is a β€œstatic” language, so you cannot create a new type (or class) at run time. You can do this in some "dynamic" languages, such as Python.

If you are trying to create a new form filled with various controls, you can do it, but you need to create each separate control, make it the form of the parent (and owner) and set its position and signature, etc.

 procedure TForm1.Button1Click(ASender: TObject); var LForm: TForm; LLabel: TLabel; begin LForm := TForm.Create(nil); try LForm.Width := 100; LForm.Height := 100; LLabel := TLabel.Create(LForm); LLabel.Parent := LForm; LLabel.Caption := 'Hello World!'; LForm.ShowModal; finally FreeAndNil(LForm); end; end; 
0
source

I have a similar problem and find some solution to execute. The only request is that MyForm is already created at runtime.

  var vOldForm,vNewForm:TObject; begin vOldForm:=Application.FindComponent('MyForm'); If vOldForm<>nil then vNewForm:=TFormClass(vOldForm.ClassType).Create(Application); If vNewForm is vOldForm.ClassType then (vNewForm as TForm).Show; end; 
0
source

All Articles