如何让我的代码工作? :)我试图制定这个问题,但经过几次失败的尝试后,我认为你们会更快地发现问题,而不是阅读我的“解释”。谢谢。
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;
答案 0 :(得分: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;
答案 1 :(得分: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;
答案 2 :(得分:4)
在设置对象的属性之前,需要将ct对象强制转换为TMemo / TEdit / TButton。
您遇到错误的行是错误的,因为ct仍然是TClass,而不是TButton /等。如果你转换为TButton,那么你将能够将enabled设置为true。
我建议您阅读casting in 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;
答案 3 :(得分: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;
答案 4 :(得分:2)
如果您不介意小的性能影响并限制对已发布属性的更改,则可以避免引用各种单位和显式强制转换。看看Delphi附带的TypInfo单元。