0

Is possible create (register) a new class in runtime using delphi.

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

i want 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 dont look create a new instance of the same base class, i need create an new class type in runtime derived from another class.

UPDATE 2

Thank you very much for your interest. but the purpose is a bit complex to explain (because my bad english). I have a form that allows you to edit multiple master data tables, all these tables have the same fields code (an integer primary key) and description (a varchar field), they serve to define currencies, countries, projects, groups, etc.

as logic is the same for all these tables, so only need this form by passing as parameters the title of the table name , to manage these tables. something like this

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 validates the users access to the forms using the form's class . because of this if you use the same kind of form is restricted access to all the options like "define groups","define currencys", "define countrys" (which I do not want that to happen), because that i need to pass to the ValidateAccess method a diferent class.

I cannot rewrite the ValidateAccess method because exist many diferents forms already registered in the system.

I dont want create a new form type and a new unit over and over just changing the title and the table to use.

Thanks in Advance.

vfclists
  • 19,193
  • 21
  • 73
  • 92
Salvador
  • 16,132
  • 33
  • 143
  • 245
  • 1
    WHY?! Your "new class" will be identical in *every* respect (except in having some name that no compiled code can be aware of and be able to use) to the "original" class. What can you possibly hope to achieve by doing this? – Deltics Feb 18 '10 at 05:32
  • How does ValidateAccess check the classtype of the supplied Form? If it checks TObject.ClassType you are out of luck, you would need to build a custom RTTI record with a new classname in it. I don't know if that is possible. – Ozan Feb 18 '10 at 06:39

6 Answers6

2

I don't know if I get you right, 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 don't have access to the new form class declarations you can use Form.ClassName instead.

vfclists
  • 19,193
  • 21
  • 73
  • 92
Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
  • Form.SubType:TMyEnum, where TMyEnum = (fGeneric,fCurrency,fGroups,...) and checking that would be so much less smelly. – Warren P Feb 18 '10 at 14:03
2

It looks like Uwe managed to solve your problem. I should just state for the record that it is possible to add new class types at runtime. Classes are defined by their class reference, which is a pointer to a VMT (Virtual Method Table), and if you know how VMTs are laid out you can create one of your own. I did a session on it at CodeRage last year. Unfortunately, the audio quality sucked. :(

Of course, this isn't much use to you unless you have to create classes whose definition is not available at compile time, for example if you're using a scripting engine. When all the information you need is available at compile time, go with something like what Uwe described.

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • The original guy doesn't seem to have a good reason to need such a class. Which means, that if it was possible to do it another way (such as Plainth's answer) then it would have been preferable. – Warren P Feb 18 '10 at 14:06
1

Why do you need to create a new subclass of the form? You cannot change anything about that new class to make it different from the existing class at runtime. i.e. you cannot add new methods or properties.

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

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

If this isn't what you require, you will need to provide more information about just what exactly it is you are trying to achieve.

Deltics
  • 22,162
  • 2
  • 42
  • 70
  • @Deltics, thanks for you answer, i am really knew that. but i am looking create a new class type. – Salvador Feb 18 '10 at 05:30
  • I do not want to change the methods or properties or the behaviour of the new class. – Salvador Feb 18 '10 at 05:37
  • 2
    Ok, but without understanding what it is you are trying to achieve by doing this, an answer is impossible. You can't do what you are asking, but there may be a way to achieve what you are trying to do in some other way. Like someone that asks for someone to build them a bridge so that they can cross a river.... there may not be enough wood to build a bridge, but we may be able to build you a boat, and if getting across the river is your goal then that will be good enough. But if you simply keep insisting on building a bridge, nobody can help. Just trying to be helpful you understand. – Deltics Feb 18 '10 at 05:42
  • thanks for your time and comments, please see my update to the question. – Salvador Feb 18 '10 at 06:12
1

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 in your SetTitle will also set the form's caption, in your SetFormKind you will do your coressponding initialization(s) if necessary whereas in ValidateAccess you will handle (most probably in a case) the different situations according to the value of FFormKind.

And to 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 perhaps you'll find better to separate the layers and have a different class to handle the validation, according to the form's properties etc.

John Thomas
  • 4,075
  • 3
  • 29
  • 41
0

I have similar problem, and find some runtime solution. Only request is that MyForm already created in 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;
Janko
  • 11
  • 1
0

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, like Python.

If you are trying to create a new form, populated with different controls, you can do this, but you need to create each individual control, make the form it's parent (and owner) and set it's position and caption 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;
Nat
  • 5,414
  • 26
  • 38