0

我有一个具有一些属性的对象:

Obj.Big
Obj.Rotate
Obj.Paint
Obj.Lines

等等。它们都是布尔类型的属性。

在我的主程序中,我调用了另一个程序:

procedure TMainForm.Create(Sender:TObject);
begin
     SetParameter(BigCheckBox, Obj.Big);
     SetParameter(RotateCheckBox, Obj.Rotate);
     SetParameter(PaintCheckBox, Obj.Paint);
     SetParameter(LinesCheckBox, Obj.Lines);
end;

SetParameter程序是这样的:

procedure TMainForm.SetParameter(ACheckBox : TCheckBox; ABoolOption : Boolean);
begin
    if(ACheckBox.Checked) and (ACheckBox.Enabled) then begin
      ABoolOption := true;
    end
    else if(not ACheckBox.Checked) and (ACheckBox.Enabled) then begin
      ABoolOption := false;
    end;
end;

它接受复选框对象和传递对象的布尔属性的属性为ABoolOption. 我不能简单地做LinesCheckBox.Checked := Obj.Lines,因为当复选框被填满时我需要一个“什么都不做”的动作(它们都是三态的)。当我运行它时,这些对象的参数都没有改变。为什么是这样?

4

2 回答 2

5

你没有通过财产。您正在传递该属性的。IOW,您SetParameter正在接收ACheckBox, Trueor ACheckBox, False,因此您无需更改任何内容。更好的方法可能是将您的SetParameter过程更改为函数:

function TMainForm.SetBooleanValue(const ACheckBox: TCheckBox): Boolean;
begin
  Result := (ACheckBox.Checked) and (ACheckBox.Enabled);
end;

然后像这样使用它:

Obj.Big := SetBooleanValue(BigCheckbox);
Obj.Rotate := SetBooleanValue(RotateCheckBox);
Obj.Paint := SetBooleanValue(PaintCheckBox);
Obj.Lines := SetBooleanValue(LinesCheckBox);

如果您需要允许第三个选项,您应该在执行调用之前先检查它SetBooleanValue

if not ThirdCondition then
  Obj.Big := SetBooleanValue(BigCheckBox);
于 2013-06-18T19:03:09.813 回答
1

您的程序没有按照您的想法执行。您不是在传递属性本身,而是在传递属性的当前值。如果您想实际更新属性的值,您需要按照 Ken 的建议进行操作,或者改用 RTTI,例如:

uses
  ..., TypInfo;

procedure TMainForm.Create(Sender:TObject);
begin
  SetBooleanParameter(BigCheckBox, Obj, 'Big');
  SetBooleanParameter(RotateCheckBox, Obj, 'Rotate');
  SetBooleanParameter(PaintCheckBox, Obj, 'Paint');
  SetBooleanParameter(LinesCheckBox, Obj, 'Lines');
end;

procedure TMainForm.SetBooleanParameter(ACheckBox : TCheckBox; Obj: TObject; const PropName: String);
begin
  if ACheckBox.Enabled then begin
    // NOTE: this only works if the properties are declared as 'published'
    SetOrdProp(Obj, PropName, Ord(ACheckBox.Checked));
  end;
end;

或者,如果您使用的是 D2010+:

uses
  ..., Rtti;

procedure TMainForm.Create(Sender:TObject);
begin
  SetBooleanParameter(BigCheckBox, Obj, 'Big');
  SetBooleanParameter(RotateCheckBox, Obj, 'Rotate');
  SetBooleanParameter(PaintCheckBox, Obj, 'Paint');
  SetBooleanParameter(LinesCheckBox, Obj, 'Lines');
end;

procedure TMainForm.SetBooleanParameter(ACheckBox : TCheckBox; Obj: TObject; const PropName: String);
var
  Ctx: TRttiContext;
begin
  if ACheckBox.Enabled then
  begin
    // NOTE: this approach does not need the properties to be declared as 'published'
    Ctx.GetType(Obj.ClassType).GetProperty(PropName).SetValue(Obj, TValue.From<Boolean>(ACheckBox.Checked));
  end;
end;
于 2013-06-18T19:10:17.780 回答