0

コンポーネントを開発していますが、設計時にプロパティ セットを考慮するようにできません。

以下はコンポーネントの抜粋です。

TRVEditFrame = class(TFrame)
...
    private
     { Private declarations }
        FRVEditor:TCustomRichView;
    public
     { Public declarations }
        constructor Create(AOwner: TComponent); override;
    protected
        function GetRVEditor:TCustomRichView;
        procedure SetRVEditor(Editor:TCustomRichView);
    published
        property RVEditor:TCustomRichView read GetRVEditor write SetRVEditor;
    end;
...

constructor TRVEditFrame.Create(AOwner: TComponent);
begin
    inherited Create(AOwner);
    SetRVEditor(FRVEditor);
...
end;


function TRVEditFrame.GetRVEditor:TCustomRichView;
begin
    Result:=FRVEditor;
end;


procedure TRVEditFrame.SetRVEditor(Editor:TCustomRichView);
begin
    if Assigned(Editor) then begin
        FRVEditor:=Editor;
    end;
end;

コンポーネントを登録してフォームに配置し、デザイン時に FRVEditor を設定できます。

問題は、アプリケーションを実行すると、Editor=nil のため SetRVEditor() 内のコードが実行されないことです。

設計時に FRVEditor を設定できたのに、実行時に =nil になるのはなぜですか? どうすればこれを修正できますか?


説明が長すぎるのでここにコメントを追加します

@ケネス、返信ありがとう

  • TCustomRichView は、ハイパーテキスト ドキュメントを管理する 3 番目のコンポーネント セットの一部であり、さらに 4 つの特殊化された子孫があります。そのとおりです。TCustomRichView は実際のアプリケーションでは使用しないでください。
  • TRVEditFrame は、私が開発しているコンポーネントです。

私のコンポーネントの背後にあるアイデアは、4 つの TCustomRichView の子孫のそれぞれを管理するために、メニュー、ショートカット、ポップアップ メニューなどを備えた 1 つの単一フレーム (したがって、コンポーネント TFrame の選択) を作成することです。

これこそまさに、私が TCustomRichView を使用する理由です。コンポーネント フレームに 4 つの子孫を「スロット」に入れることができます。これは、TTAble および TQuery と接続できる TDatasource と同じ原則です (これらは同じ祖先を持ちます)。

設計時に設定した TCustomRichView の子孫に VCL が RVEditor をリンクしない理由は、たとえば TForm のように、TFrame に OnCreate イベントがないためだと思います。

これまでのところ、TRVEditFrame をホストする TForm.OnCreate で TRVEditFrame.SetRVEditor を手動で呼び出すことで問題を解決できましたが、これを行うためのより良い方法があるかどうか疑問に思っていたので、ここでアドバイスを求めました。

TFrame の OnCreate イベントも作成できることはわかっています。そこに TRVEditFrame.SetRVEditor を配置することもできますが、もっと良い方法があるかどうか疑問に思っていました。

コメントの最後の部分については、登録手順については承知していますが、コンポーネントが開発中であることを考慮してください。コンポーネントを開発するときは、IDE にコンポーネントをインストールすることはありません。なぜなら、テスト用のものを「公式」のものの外に置いておきたいからです。私はこの方法を使用し、コンポーネントの準備ができたらすぐに、あなたが言及した手順で登録します。同じコンポーネントに他の機能を実装したい場合は、テスト機能に取り組み、同時に IDE にある「公式」機能を使い続けることができます。

4

2 に答える 2

0

私の提案は、プロパティを手動で設定する代わりに、Notification メソッドを使用して、フレーム コンポーネントがカスタム エディターを参照するようにデザインを変更することです。したがって、フレームクラスを次のように変更します

TRVEditFrame = class(TFrame)
...
private
 { Private declarations }
    FRVEditor: TCustomRichView;
protected
  procedure Notification(aComponent: TComponent; aOperation: TOperation); override;
public
 { Public declarations }
    constructor Create(AOwner: TComponent); override;
public
    property RVEditor:TCustomRichView read FRVEditor;
end;

Notification メソッドの実装は、フレームをカスタム エディターに接続/切断する魔法を行います。

procedure TRVEditFrame.Notification(aComponent: TComponent;
                                    aOperation: TOperation);
begin
  inherited;
  if aComponent is TCustomRichView then
    if aOperation=opRemove then begin
      if aComponent=FRVEditor then
        FRVEditor := nil;
    end else
      FRVEditor := TCustomRichView(aComponent);
end;

エディターがフレームに設定/リセットされるときに特別な処理が必要かどうかはわかりません。そのため、このコードは特に何もせず、適切なタイミングで FRVEditor データ メンバーにコンポーネントまたは nil を割り当てるだけです。

于 2013-07-23T17:39:37.033 に答える
0

子コンポーネントを作成する必要があります。

constructor TRVEditFrame.Create(AOwner: TComponent);
begin
    inherited; // Create(AOwner);
    FRVEditor := TRichView.Create(self);
end;

DFM ストリーミング エンジンは、作成済みのクラスのプロパティをロードする場合がありますが、次の 2 つの理由により、クラスを作成することはできません。

1) DFM は、作成されたコンポーネントで行われた特別な調整を認識できません。たとえば、コンストラクターのパラメーター (存在する場合)、使用するコンストラクター (多数のコンストラクター)、アタッチする niotifications とイベント ハンドラーなどです。

2) DFM は、プロパティのタイプを認識できません。たとえば、私はTStringsoroperty を公開しました - どのクラスのオブジェクトを作成する必要がありますか? TStrings? TStringList? TRichEditStringList? THashedStringList? それらはすべて継承されTStringsているため、DFM には適切な選択ですが、作成するコンポーネントには適していません。

したがって、DFM ストリーミング サブシステムはオブジェクトのプロパティの保存と読み込みを担当しますが、それらのオブジェクトの作成は純粋にユーザーの責任です。


RVEditIDE デザイナーがどのようにフォームを作成し、プロパティではなく変数を作成するかを学ぶことで、手抜きをすることもできると思います。

TRVEditFrame = class(TFrame)
...
    public
     { Public declarations }
        constructor Create(AOwner: TComponent); override;
    published
        var RVEditor:TCustomRichView; // just like users' forms are created by IDE
    end;

TFrame次に、コンストラクターがこの変数のコンテンツを作成してくれることを願っています。しかし、この設計は壊れやすいものです。なぜなら、外側のコードは愚かな間違いによってMyEditFrame.RVEditor := ...、メモリ リークや、エディタとフレームの間のすべての接続の予期しない障害を引き起こす可能性があるからです。

于 2013-07-23T08:19:12.843 に答える