2017-08-31 9 views
1

以下のコードを使用して、実行時に作成されたコンポーネントにRTTIのDelphi 10.2 Tokyoを使用してプロパティを設定しています。この例のプロパティはTypeLine、私はそれに直接アクセスできるからです。SetPropValue()およびRTTI with Delphiを使用してコンポーネントプロパティを変更する東京

Componente_ccは、任意のクラスをインスタンス化することができる変数、それはTLabelなり、TButtonTEdit ...または任意の他のです。私は、サブプロパティがあった場合しかし、私は、このようなStrokeとして、行う方法を理解していなかった、それはKindを持ってTLine.

Var 
    Componente_cc: TControl; 

    procedure TfrmPrincipal.AlteraPropriedades; 
    begin 
     if IsPublishedProp(Componente_cc, 'LineType') then 
      SetPropValue(Componente_cc, 'LineType', 'Diagonal'); 
    end; 

であるとして、それをインスタンス化しています以下の場合、ColorCapDash、他の中。 SetPropValue()関数を使用してこれらのプロパティの値を変更する方法。私は、より良い理解のためのサンプルコードを簡略化しましたが、私のシステムの一般的な文脈では、RTTIを使用する必要があります。もちろん、コードによってプロパティを直接変更するのは簡単ですが、RTTIが必要です。

答えて

5

これは、コントロールのTextSettings.FontプロパティにRTTIでアクセスしているother RTTI issueに似ています。同じことは、ネストされた各サブプロパティについて

など、Stroke.Colorのように、任意のネストされた財産のために適用され、必要に応じて、希望するサブオブジェクトに到達するまで、あなたがして、繰り返し、に含むオブジェクトを取得する必要がありますを取得/設定することができます。

ので、この場合には、あなたは、あなたは、そのオブジェクトのプロパティを設定するためにSetPropValue()を使用することができ、Strokeプロパティオブジェクトを取得するためにGetObjectProp()を使用する必要があります。たとえば、次のように

uses 
    ..., TypInfo; 

var 
    Componente_cc: TControl; 

procedure TfrmPrincipal.AlteraPropriedades; 
var 
    Stroke: TObject; 
begin 
    if IsPublishedProp(Componente_cc, 'Stroke') then 
    begin 
    Stroke := GetObjectProp(Componente_cc, 'Stroke'); 
    if Stroke <> nil then 
     SetPropValue(Stroke, 'Color', ...); 
    end; 
end; 

または、指定されたプロパティの二重のRTTIの検索を避けるために:

より強力な Enhanced RTTIは、Delphi 2010で導入されたことをメモ(このRTTIはちょうど公表に限定されるものではない
uses 
    ..., TypInfo; 

var 
    Componente_cc: TControl; 

procedure TfrmPrincipal.AlteraPropriedades; 
var 
    PropInfo: PPropInfo; 
    Stroke: TObject; 
begin 
    PropInfo := GetPropInfo(Componente_cc, 'Stroke', [tkClass]); 
    if PropInfo <> nil then 
    begin 
    Stroke := GetObjectProp(Componente_cc, PropInfo); 
    if Stroke <> nil then 
     SetPropValue(Stroke, 'Color', ...); 
    end; 
end; 

例えば古いスタイルRTTIがあるなどのプロパティ、)、:

uses 
    ..., System.Rtti; 

var 
    Componente_cc: TControl; 

procedure TfrmPrincipal.AlteraPropriedades; 
var 
    Ctx: TRttiContext; 
    Prop: TRttiProperty; 
    Stroke: TObject; 
begin 
    Ctx := TRttiContext.Create; 

    Prop := Ctx.GetType(Componente_cc.ClassType).GetProperty('Stroke'); 
    if (Prop <> nil) and (Prop.PropertyType.TypeKind = tkClass) {and (Prop.Visibility = mvPublished)} then 
    begin 
    Stroke := Prop.GetValue(Componente_cc).AsObject; 
    if Stroke <> nil then 
    begin 
     Prop := Ctx.GetType(Stroke.ClassType).GetProperty('Color'); 
     if (Prop <> nil) {and (Prop.Visibility = mvPublished)} then 
     Prop.SetValue(Stroke, ...); 
    end; 
    end; 
end; 

はしかし、それはあなたがより高いレベルのOへのアクセス権を持っていたら、直接サブプロパティにだけアクセスすることをお勧めします例えばbject、:

uses 
    ..., TypInfo; 

var 
    Componente_cc: TControl; 

procedure TfrmPrincipal.AlteraPropriedades; 
var 
    PropInfo: PPropInfo; 
    Stroke: TStrokeBrush; 
begin 
    PropInfo := GetPropInfo(Componente_cc, 'Stroke', [tkClass]); 
    if PropInfo <> nil then 
    begin 
    Stroke := GetObjectProp(Componente_cc, PropInfo, TStrokeBrush) as TStrokeBrush; 
    if Stroke <> nil then 
     Stroke.Color := ...; // <-- no RTTI needed! 
    end; 
end; 

または:

uses 
    ..., System.Rtti; 

var 
    Componente_cc: TControl; 

procedure TfrmPrincipal.AlteraPropriedades; 
var 
    Ctx: TRttiContext; 
    Prop: TRttiProperty; 
    Stroke: TStrokeBrush; 
begin 
    Ctx := TRttiContext.Create; 

    Prop := Ctx.GetType(Componente_cc.ClassType).GetProperty('Stroke'); 
    if (Prop <> nil) and (Prop.PropertyType.TypeKind = tkClass) {and (Prop.Visibility = mvPublished)} then 
    begin 
    Stroke := Prop.GetValue(Componente_cc).AsObject as TStrokeBrush; 
    if Stroke <> nil then 
     Stroke.Color := ...; // <-- no RTTI needed! 
    end; 
end; 
+0

こんにちは@Remy、あなたは2010年以来、より堅牢なRTTIがあると言うとき、あなたの第二の例を参照しますか?プロパティに直接アクセスしますか? – Anderson

+0

RTTIを使用しているのは、唯一の解決策だからです。私の問題は、問題のソフトウェアがIDEに似ていて、コントロールが追加され、プロパティが変更されたり、サイズが変更されたりするためです。フォームは実行時にはどのクラスでも構いません。すべてのタイプのコンポーネントを追加するための単一の関数、プロパティを取得する別の関数、プロパティを設定する別の関数を実行しようとしています。そのため、TControl型のオブジェクトを作成しました。クラス、問題はTControlではすべてのプロパティに直接アクセスできないため、RTTIを使用していました。 – Anderson

+0

@Anderson:プロパティに直接アクセスすることはRTTIとはまったく関係がありません。これは通常のオブジェクト指向プログラミングです。 'PPropInfo'の使用は新しいものではなく、常に利用可能です。 'System.TypInfo'ユニットによって実装された古いスタイルのRTTIは、' System.Rtti'ユニットによって実装された拡張RTTI(http://docwiki.embarcadero.com/RADStudio/en/Working_with_RTTI_Index)に置き換えられました。 –

関連する問題