使用他的 ClassType 来转换 TObject?

发布于 2024-07-26 07:50:51 字数 562 浏览 3 评论 0原文

我怎样才能让我的代码工作? :) 我试图提出这个问题,但经过几次失败的尝试后,我认为你们通过查看代码会比阅读我的“解释”更快地发现问题。 谢谢。

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;

how can i make my code to work ? :) i`ve tried to formulate this question but after several failed attempts i think you guys will spot the problem faster looking at the code than reading my 'explanations'. thank you.

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

楠木可依 2024-08-02 07:50:51

您必须将对象显式转换为某个类。
这应该可以工作:

 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;

You must explicitly cast object to some class.
This should work:

 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;

This can be shortened using "is" operator - no need for ct variable:

 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;
热鲨 2024-08-02 07:50:51

使用 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;

It would be easier to use RTTI instead of explicit casting, ie:

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;
撑一把青伞 2024-08-02 07:50:51

您需要先将 ct 对象转换为 TMemo/TEdit/TButton,然后才能设置该对象的属性。

您收到错误的行正在出错,因为 ct 仍然是 TClass,而不是 TButton/等。 如果您转换为 TButton,那么您将能够将启用设置为 true。

我建议阅读在 Delphi 中进行转换。 就我个人而言,我建议也使用 as/is 运算符而不是使用 ClassType。 在这种情况下,代码会更简单,也更容易理解。


就我个人而言,我会这样写:

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;

You need to cast the ct object to a TMemo/TEdit/TButton before you can set properties on the object.

The line where you're getting errors are erroring because ct is still a TClass, not a TButton/etc. If you cast to a TButton, then you'll be able to set enabled to true.

I recommend reading up on casting in Delphi. Personally, I would recommend using the as/is operators instead of using ClassType, as well. The code will be simpler in that case, and much more understandable.


Personally, I would write this more like:

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;
女皇必胜 2024-08-02 07:50:51

无需分别转换为 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;

There is no need to cast to TMemo and TEdit separately, as they are both descendants from common parent class, which have ReadOnly property:

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;
瀟灑尐姊 2024-08-02 07:50:51

如果您不介意性能受到一点影响并限制对已发布属性的更改,则可以避免引用各种单位和显式转换。 看一下 Delphi 中包含的 TypInfo 单元。

You can avoid referencing various units and the explicit casting if you do not mind a small performance hit and limit the changes to published properties. Have a look at the TypInfo unit included with Delphi.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文