2012-02-24 8 views
4

私は、TComponent Loaded()メソッドのオーバーライドで重要なタスクを行ういくつかのカスタムVCLコンポーネントを用意しています。これは、設計時にフォーム/フレームに配置されたコンポーネントの場合のように、DelphiグローバルローダによってLoaded()メソッドが実行時に呼び出されないため、インスタンスを動的に作成する際に迷惑をかけます。クラスの宣言のpublicセクションに、ロードされたオーバーライドを配置する必要があります。コンポーネントのインスタンスを作成するコードであれば、呼び出すことができます。最後に、動的に作成されたインスタンスのためにLoaded()を呼び出すことを忘れないでください。微妙なバグがアプリケーションに入り込みます。Delphi 6で動的に作成されたVCLコンポーネントのインスタンスに対して、Loadedメソッドを明示的に呼び出す方法はありますか?

もっと良い解決法がありますか?

+2

プロパティがストリーミングされるまで待つ必要がない場合は、AfterConstructionをオーバーライドできます。 プロパティがストリーミングされるまで待つ必要がある場合は、現在のように手動で行う必要があります。それ以外の場合は、コンポーネントがランタイムコードでプロパティの割り当てを完了したことをコンポーネントが認識できないためです。 –

+3

私はあなたが「読み込まれた」目的を誤解していると思います。コンポーネント*が.dfm *からストリーミングされた直後に呼び出されます。それは実行時または設計時とは関係ありません。 (IOW、それは実行時にプロパティを設定することとは関係ありません。なぜなら、これは実行されるべきものではないからです。)デザイン時にフォーム上にドロップされたコントロール/フレームに対して働く理由は、ストリーミングプロセス中に.dfmの中に "ロードされている"ように。)私が想像できるどんな状況下でもあなたは決して*ロードされてはいけません。 –

+0

@Kenプロパティがストリーミングされた後に実行する必要のあるアクションには、他にどのようなメカニズムがありますか?私は、Robertが行うカスタマイズはLoadedから個別のメソッドに分割し、Loadedから呼び出す必要があることに同意します。 –

答えて

3

コードにLoadedを呼び出す必要がある場合は間違っています。そうした第三者コントロールに依存している場合は、その人のコントロールを修正します。方法は以下を参照してください。

仮説の例を作りましょう:5つのパブリッシュされたプロパティがあり、それが一度ロードされると複雑なカーブを生成したり、フラクタルを生成することができます。

デザイン時に、このカーブをロードするとすぐにプレビューしたいが、DFMストリーミング中にカーブを5回再計算しないようにする。各パラメータP1からP5(タイプDouble)はSetP1メソッドこれはChangedと呼ばれる保護されたメソッドを呼び出し、私のカーブを再構築します。代わりに、私はSetP1メソッドを返します、csDesigningまたはcsLoadingがコンポーネント状態にある場合、Loadedから一度Changedを呼び出します。明らかに、すべての変更を呼び出すために、すべての場合にプロパティセットメソッドのみを使用することはできません。だから、ロードされていなければ、高価な仕事の第一世代をやって、N回ではなく、正確に1回実行したいと言うことができます。ここで、Nはメソッドセットプロシージャを持つDFMプロパティの数です。 Changedという名前のメソッドが呼び出されます。

あなたの場合、実行時には、Loadedがまったく呼び出されることに頼るべきではありません。代わりに、あなたのプロパティセットメソッドがChangedを呼び出す必要があります。一度に複数のプロパティを変更する方法が必要な場合は、高価なものを1回だけ実行してから、TMyComponent.BeginUpdate/TMyComponent.EndUpdate型のメソッド呼び出しを実装し、余分な作業を避けてください。

上記のようなケースを除いて、Loadedから何かをするのは意味のない場所ではないと思います。これは、デザインタイムとDFMベースのクラスの使用に特有のものです。私は、適切に設計されたTComponentまたはTControlが、コードで作成され、そのプロパティが設定されるだけで、正しく初期化されることを期待します。

コードでそれを作成するときだから私の仮説的TMyFractalコンポーネントのために、私はそれが今まで使用DFM負荷を有する、またはロードされ呼び出さずにこれを行うだろう:私のTMyFractal.Change方法で

cs := TMyFractal.Create(Self); 
    cs.Parent := Self; {Parent to a form} 
    cs.Align := alClient; 
    cs.BeginUpdate; 
    cs.P1 := 1.03; // does NOT trigger Regenerate 
    cs.P2 := 2.3; 
    cs.P3 := 2.4; 
    cs.P4 := 2.5; 
    cs.EndUpdate; // triggers expensive Regenerate method . 
    cs.Show; 

    // later someone wants to tweak only one parameter and I don't want to make them 
    // call regenerate: 
    cs.P5 := 3.0; // Each param change regenerates the whole curve when not loading or in a beginupdate block. 

、私が呼び出します高価なRegenerateCurveメソッドは、実行時に、初期設定後に、そしてコンポーネントがDFMからストリーミングされたときに変更されるたびに、一度、各係数P1〜P4が変更されるたびにロードされます。上記のコードで行ったように、私のコントロールでbeginupdate/endupdateを実行してください。

関連する問題