2010-02-18 33 views
0

可以使用delphi在运行时创建(注册)一个新类。使用Delphi在运行时注册一个新类

我有一个名为TMyForm的类,可以创建一个从TMyForm派生的新表格,但是可以使用新的类类型。

我想是这样的

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

我使用德尔福7

更新1

我不看创建相同的基类的新实例,我需要创建一个新类类型在运行时从另一个类派生。

更新2

非常感谢您的关注。但目的有点复杂(因为我的英语不好)。我有一个表单,允许您编辑多个主数据表,所有这些表具有相同的字段代码(一个整数主键)和描述(一个varchar字段),它们用于定义货币,国家,项目,组等。

由于所有这些表的逻辑是相同的,所以只需要通过传递参数作为表名的标题来管理这些表。像这样

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; 

,另一方面我有一个验证方法(称为ValidateAccess),用于验证的用户可以访问使用窗体类的形式。因为这个,如果你使用相同类型的表单是限制访问像“定义组”,“定义currencys”,“定义国家”(我不希望这种情况发生)的所有选项,因为我需要通过到ValidateAccess方法是一个不同的类。

我不能重写ValidateAccess方法,因为在系统中已存在许多不同的表单。

我不想创建一个新的表单类型和一个新的单位反复只是改变标题和表使用。

在此先感谢。

+1

WHY?你的“新课堂”在*每个方面都是相同的(除了有一些名字)在没有编译代码可以知道并能够使用)到“原始”类。你可能希望通过这样做来达到什么目的? – Deltics 2010-02-18 05:32:42

+0

ValidateAccess如何检查提供的表单的类型?如果它检查了TObject.ClassType,那么你运气不好,你需要用一个新的类名创建一个自定义的RTTI记录。我不知道这是否可能。 – Ozan 2010-02-18 06:39:51

回答

2

我不“知道如果我得到你的权利,但我明白可以以这种方式来实现:

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; 

在你ValidateAccess方法(假设参数被命名为表格),您可以检查类似:

if Form is TCurrencyForm then 
else if Form is TGroupsForm then 

如果您没有访问,您可以使用Form.ClassName而不是新的窗体类的声明。

+0

+1000非常感谢,他们的解决方案适合我。 – Salvador 2010-02-18 12:30:03

+0

Form.SubType:TMyEnum,其中TMyEnum =(fGeneric,fCurrency,fGroups,...)并检查它会不那么臭。 – 2010-02-18 14:03:58

1

为什么你需要创建一个新的窗体子类?您无法更改有关该新类的任何内容,以使其在运行时与现有类不同。即您不能添加新的方法或属性。

我怀疑你犯了一个错误,认为一个表单类只能有一个实例。但这种情况并非如此。如你愿意,你可以创建一个表单的多个实例:

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

如果这不是你需要什么,你需要提供有关它只是究竟你正在努力实现的更多信息。

+0

@Deltics,谢谢你的回答,我真的很清楚。但我正在寻找创建一个新的类类型。 – Salvador 2010-02-18 05:30:55

+0

我不想更改新类的方法或属性或行为。 – Salvador 2010-02-18 05:37:26

+2

好吧,但不知道你是通过这样做来达到的,答案是不可能的。你不能做你正在问的东西,但是可能有办法以其他方式实现你正在尝试做的事情。就像有人要求某人为他们建造一座桥,以便他们可以穿过一条河......可能没有足够的木材来建造一座桥,但是我们也许可以为你建造一艘船,如果穿越这条河那么你的目标就足够好了。但是,如果你只是坚持建造一座桥,任何人都无法提供帮助。只是试图帮助你理解。 – Deltics 2010-02-18 05:42:55

0

Delphi是一种'静态'语言,因此您不能在运行时创建新类型(或类)。你可以用一些'动态'语言来做到这一点,比如Python。

如果您尝试创建一个新窗体,并使用不同的控件进行填充,您可以执行此操作,但需要创建每个单独的控件,将窗体设置为父窗体并设置其位置和标题等。

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; 
1

IIUC,你可以有这样的事情:

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

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

而在你SetTitle也会设置表格的标题,在您的SetFormKind中,如果有必要,您将根据需要进行核心初始化,而在ValidateAccess中,您将根据FFormKind的值处理(很可能在case中)不同情况。

,并使用它:

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. 

但是也许你会发现更好的分离各层,并有不同的类来处理验证,根据窗体的属性等

+0

更好的解决方案,然而这家伙喜欢邪恶的kludge。 – 2010-02-18 14:05:06

2

它看起来像Uwe设法解决您的问题。我应该声明可以在运行时添加新的类类型。类是通过它们的类引用来定义的,它是一个指向VMT(虚拟方法表)的指针,如果你知道VMT是如何布置的,你可以创建一个你自己的。 I did a session on it at CodeRage last year.不幸的是,音频质量很糟糕。 :(

当然,这对你来说没有多大用处,除非你必须在编译时创建其定义不可用的类,例如,如果你使用的是脚本引擎。当你需要的所有信息可在编译的时候,去的东西像什么乌韦描述。

+0

原来的家伙似乎没有理由需要这样的班级。这意味着,如果有可能以另一种方式做到这一点(比如Plainth的答案),那么它就会更好。 – 2010-02-18 14:06:27

0

我有类似的问题,并找到了一些运行时解决方案。 唯一的要求是,在MyForm的运行已经创建。

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; 
相关问题