2011-07-06 18 views
2

多くのイベントハンドラを含むデザインと実行時コンポーネントがあります。私は今それをTNewCompと呼ぶでしょう。私はTFormにTNewCompのインスタンスを作成し、設計時にプロパティエディタを使ってイベントスタブを特定のコードで埋めて、現在のイベントハンドラコードセットを使用するTNewcompの新しいインスタンスを作成できるようにしたいと思います。動的に作成されたコンポーネントのイベントハンドラをDelphi 6で自動的に割り当てる方法はありますか?

これを行うには、TNewCompのコンストラクタを呼び出してから、新しいインスタンスのイベントハンドラのそれぞれに、デザイン時に作成されたTNewCompインスタンスを含むフォームにある対応するイベントスタブコードを割り当てます。だから私は、私はどうなる各イベントハンドラのTNewFormと呼ばれるフォームにFNewCompという名前の変数に代入TNewCompのインスタンスを持っている場合:

FNewComp.onSomething = TNewform.onSomething 
(... repeat for each event handler belonging to TNewComp ...) 

これは正常に動作しますが、私が追加した場合には、面倒で悪化しています新しいイベントハンドラをTNewCompに追加するには、イベントハンドラの割り当てを行うためにnewTComp()関数を更新することを忘れないでください。新しいインスタンスを動的に作成するすべての固有のコンポーネントタイプについて、このプロセスをリンスして繰り返します。

おそらくプロパティ検査やその他のDelphi 6イントロスペクションテクニックを使用してこのプロセスを自動化する方法はありますか?

- roschler

+2

私はちょうどAlt + F12を使い、.dfmファイルで簡単にコピー/貼り付けをすると思います。私は、このメリットがそれ以上の特注の工具であるかどうかはわかりません。 –

+0

@David Hefferman - 実行時にインスタンスの数が不明で、すべてが実行時にTNewComp.Createを使用して作成されたときに、実行時に新しいインスタンスを作成するときにソリューションがどのように動作するかわかりません。 –

+0

あなたの問題は設計時だと思った。なぜあなたが現在やっていることをするのは難しいのか分かりません。あなたが考えているのは、イベントとハンドラを関連付けるためのいくつかのルールが必要です。あなたはどう思いますか?名前ベース? –

答えて

4

次のコードを使用しました。作成時にDestオーナーに注意してください。一番安全な方法は、後でNilを渡してコンポーネントを自分で解放することです。

implementation uses typinfo; 

procedure CopyComponent(Source, Dest: TComponent); 
var 
    Stream: TMemoryStream; 
    TypeData : PTypeData; 
    PropList: PPropList; 
    i, APropCount: integer; 
begin 
    Stream:=TMemoryStream.Create; 
    try 
    Stream.WriteComponent(Source); 
    Stream.Position:=0; 
    Stream.ReadComponent(Dest); 
    finally 
    Stream.Free; 
    end; 

    TypeData := GetTypeData(Source.ClassInfo); 
    if (TypeData <> nil) then 
    begin 
    GetMem(PropList, SizeOf(PPropInfo)*TypeData^.PropCount); 
    try 
     APropCount:=GetPropList(Source.ClassInfo, [tkMethod], PropList); 
     for i:=0 to APropCount-1 do 
     SetMethodProp(Dest, PropList[i], GetMethodProp(Source, PropList[i])) 
    finally 
     FreeMem(PropList); 
    end; 
    end; 
end; 
+0

ありがとう、私はそのコードを試してみましょう。私は、親を動的に作成されたコンポーネントに渡すことはほとんどありませんし、自分のライフタイムを自分で管理することを選択します。それ以外の場合は、後でFastMMとほぼ保証されたセッションで、二重に解放されたオブジェクトや早期に解放されたオブジェクトを指摘して捜索します。 –

2

1つのオプションは、ストリームに「適切に設定コンポーネント」を保存して、それがDelphiのIDE /ランタイムによって行われているかのように新しい、動的に作成されたコンポーネントにそのストレムをロードすることです。

もうひとつのオプションは、TypInfoユニットであるRTTIを使用することです。そこには機能GetPropListがあり、利用可能なイベント(TypeKind tkMethod)を照会できるようになり、GetMethodPropと​​を使用して、あるコンポーネントから他のコンポーネントへのイベントハンドラーをコピーできます。

1

私は、次のようにMakseeのソリューションを微調整:

function CopyComponent(Source: TComponent; Owner: TComponent = nil): TComponent; 
var 
    Stream: TMemoryStream; 
    TypeData : PTypeData; 
    PropList: PPropList; 
    i, APropCount: integer; 
begin 
    if not Assigned(Source) then 
     raise Exception.Create('(CopyComponent) The Source component is not assigned.'); 

    Result := TComponent.Create(Owner); 

    Stream := TMemoryStream.Create; 

    try 
     Stream.WriteComponent(Source); 
     Stream.Position := 0; 
     Stream.ReadComponent(Result); 
    finally 
     Stream.Free; 
    end; // try() 

    // Get the type data for the Source component. 
    TypeData := GetTypeData(Source.ClassInfo); 

    if (TypeData <> nil) then 
    begin 
     // Get the property information for the source component. 
     GetMem(PropList, SizeOf(PPropInfo) * TypeData^.PropCount); 

     try 
      // Get the properties count. 
      APropCount := GetPropList(Source.ClassInfo, [tkMethod], PropList); 

      // Assign the source property methods to the destination. 
      for i := 0 to APropCount - 1 do 
       SetMethodProp(Result, PropList[i], GetMethodProp(Source, PropList[i])) 

     finally 
      // Free the property information object. 
      FreeMem(PropList); 
     end; // try() 
    end; // if (TypeData <> nil) then 
end; 

新しいコンポーネントが、むしろ既存のコンポーネント参照(MakseeのバージョンでのDESTパラメータ)を渡すよりも、関数によって返されるようにするため。誰かがこの変形から生じる欠陥または問題を見ることができる場合は、コメントしてください。

関連する問題