5

コードを機能させるにはどうすればよいですか? :)私はこの質問を定式化しようとしましたが、何度か失敗した後、私の「説明」を読むよりもコードを見た方が早く問題を見つけることができると思います. ありがとうございました。

setCtrlState([ memo1, edit1, button1], False);

_

procedure setCtrlState(objs: array of TObject; bState: boolean = True);
var
  obj: TObject;
  ct: TClass;
begin
  for obj in objs do
  begin
    ct := obj.ClassType;


    if (ct = TMemo) or (ct = TEdit) then
      ct( obj ).ReadOnly := not bState;        // error here :(

    if ct = TButton then
      ct( obj ).Enabled:= bState;        // and here :(

  end;
end;
4

5 に答える 5

7

オブジェクトを何らかのクラスに明示的にキャストする必要があります。これはうまくいくはずです:

 procedure setCtrlState(objs: array of TObject; bState: boolean = True);
 var
   obj: TObject;
   ct: TClass;
 begin
  for obj in objs do
  begin
    ct := obj.ClassType;

    if ct = TMemo then
      TMemo(obj).ReadOnly := not bState
    else if ct = TEdit then
      TEdit(obj).ReadOnly := not bState
    else if ct = TButton then
      TButton(obj).Enabled := bState;
  end;
end;

これは " " 演算子を使用して短縮できますis- ct 変数は必要ありません:

 procedure setCtrlState(objs: array of TObject; bState: boolean = True);
 var
   obj: TObject;
 begin
   for obj in objs do
   begin
     if obj is TMemo then
       TMemo(obj).ReadOnly := not bState
     else if obj is TEdit then
       TEdit(obj).ReadOnly := not bState
     else if obj is TButton then
       TButton(obj).Enabled := bState;
   end;
 end;
于 2009-07-04T22:59:46.157 に答える
5

明示的なキャストの代わりに RTTI を使用する方が簡単です。つまり、次のようになります。

uses
  TypInfo;

setCtrlState([ memo1, edit1, button1], False);

procedure setCtrlState(objs: array of TObject; bState: boolean = True);
var
  obj: TObject;
  PropInfo: PPropInfo;
begin
  for obj in objs do
  begin
    PropInfo := GetPropInfo(obj, 'ReadOnly');
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, not bState);

    PropInfo := GetPropInfo(obj, 'Enabled');
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, bState);
  end;
end;
于 2009-07-08T01:02:14.833 に答える
4

オブジェクトにプロパティを設定する前に、ct オブジェクトを TMemo/TEdit/TButton にキャストする必要があります。

ct は TButton/etc ではなく TClass のままであるため、エラーが発生している行でエラーが発生しています。TButton にキャストすると、enabled を true に設定できます。

Delphi でのキャストについて読むことをお勧めします。個人的には、ClassType を使用する代わりに as/is 演算子を使用することもお勧めします。その場合、コードはより単純になり、はるかに理解しやすくなります。


個人的には、次のように書きます。

procedure setCtrlState(objs: array of TObject; bState: boolean = True);
var
  obj: TObject;
begin
  for obj in objs do
  begin
    // I believe these could be merged by using an ancestor of TMemo+TEdit (TControl?)
    // but I don't have a good delphi reference handy
    if (obj is TMemo) then
        TMemo(obj).ReadOnly := not bState;

    if (obj is TEdit) then
        TEdit(obj).ReadOnly := not bState;

    if (obj is TButton) then
        TButton(obj).Enabled := bState;
  end;
end;
于 2009-07-04T22:38:52.033 に答える
3

TMemoとTEditはどちらも共通の親クラスの子孫であり、ReadOnlyプロパティを持っているため、別々にキャストする必要はありません。

procedure TForm1.FormCreate(Sender: TObject);

  procedure P(const Obj: TComponent);
  begin
    if Obj is TCustomEdit then
      TCustomEdit(Obj).ReadOnly := True;
  end;

begin
  P(Memo1);
  P(Edit1);
end;
于 2009-07-05T13:21:36.533 に答える
2

パフォーマンスへのわずかな影響を気にせず、公開されたプロパティへの変更を制限する場合は、さまざまなユニットの参照と明示的なキャストを避けることができます。Delphi に含まれている TypInfo ユニットを見てください。

于 2009-07-06T10:17:10.807 に答える