0


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;

一方、フォームのclassを使用してフォームへのユーザーアクセスを検証する検証メソッド(ValidateAccessと呼ばれます)があります。 このため、同じ種類のフォームを使用する場合、「グループの定義」、「通貨の定義」、「国の定義」などのすべてのオプションへのアクセスが制限されます。 ValidateAccessメソッドには異なるクラスがあります。

システムにすでに登録されている多くの異なるフォームが存在するため、ValidateAccessメソッドを書き換えることはできません。

使用するタイトルと表を変更するだけで、新しいフォームタイプと新しいユニットを何度も作成したくありません。

前もって感謝します。

6 Answer


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メソッド(パラメーターの名前が_F​​orm_であると仮定)で、次のようなものを確認できます。

if Form is TCurrencyForm then
else if Form is TGroupsForm then

新しいフォームクラス宣言にアクセスできない場合は、代わりにForm.ClassNameを使用できます。


2


Uweが問題を解決したようです。 記録のために、実行時に新しいクラス型を追加することが可能であると述べる必要があります。 クラスは、VMT(仮想メソッドテーブル)へのポインターであるクラス参照によって定義されます。VMTのレイアウトがわかっている場合は、独自のクラス参照を作成できます。 http://tech.turbu-rpg.com/3/dynamic-class-creation [昨年CodeRageでセッションを行いました。]残念ながら、音質は悪くなりました。 :(

もちろん、スクリプトエンジンを使用している場合など、コンパイル時に定義を使用できないクラスを作成する必要がない限り、これはあまり役に立ちません。 必要な情報がすべてコンパイル時に利用可能になったら、Uweが説明したようなものを使用してください。


1


フォームの新しいサブクラスを作成する必要があるのはなぜですか? 実行時に既存のクラスと異なるようにするために、その新しいクラスについて何も変更することはできません。 i.e. 新しいメソッドやプロパティを追加することはできません。

1つのフォームクラスには1つのインスタンスしか持てないと考えているのではないかと思われます。 しかし、そうではありません。 フォームのインスタンスを必要な数だけ作成できます。

var
  formA : TMyForm;
  formB : TMyForm;
begin
  formA := TMyForm.Create(Application);
  formB := TMyForm.Create(Application);
  formA.Show;
  formB.Show;
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`では(ほとんどの場合 `case`で)さまざまな状況を処理します。 `FFormKind`の値に。

そしてそれを使う:

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


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;


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;