这是代码:
procedure DisableContrlOL(const cArray : array of string; ReEnable : boolean = False);
// can be called from VKP / RAW / Generation clicks
var
AComponent: TComponent;
CompListDis, CompListEna : TStringList;
begin
CompListDis := TStringList.Create;
CompListEna := TStringList.Create;
for i := Low(cArray) to High(cArray) do begin
AComponent := FindComponent(cArray[i]);
if Assigned(AComponent) then
if (AComponent is TControl) then begin
if TControl(AComponent).Enabled then
CompListEna.Add(TControl(AComponent).Name)
else
CompListDis.Add(TControl(AComponent).Name);
ShowMessage(TControl(AComponent).Name);
if ReEnable then begin // if reenabling needed, then all whi
if not TControl(AComponent).Enabled then
TControl(AComponent).Enabled := True;
end else if (TControl(AComponent).Enabled) then
TControl(AComponent).Enabled := False;
end;
end;
end;
我认为不需要再解释了。 ShowMessage正确显示每个组件的名称,但在StringLists中没有添加任何内容。为什么呢?
更新:随着问题变得非常疯狂,我确实回答了问题,这对我有所帮助。
我明白我确实写的东西很不清楚,但我非常有限,因为这些代码行是商业项目的一部分,也是我的爱好和心脏的事情。主要问题在6小时前就已经发现了,但Rob只是想扩展这个问题:D不,没有冒犯,交配,没关系。我很高兴收到如此自愿和乐于助人的帖子。再次感谢。
答案 0 :(得分:4)
你怎么知道列表中没有添加任何内容?您可以在此代码中创建它们,并且对它们的唯一引用是在局部变量中。当此函数返回时,对象会泄露,因此您永远不会在任何地方实际使用这些列表。
你说你有“模块化测试”的代码。由于该代码不在这里,我必须假设代码不是此函数的一部分。但是如果你有外部代码应该检查列表的内容,那么列表不能只是局部变量。没有其他代码可以访问它们。您需要返回这些列表或接受外部填写的列表。以下是后者的一个例子:
procedure DisableContrlOL(const cArray: array of string;
Reenable: Boolean
CompListDis, CompListEna: TStrings);
// can be called from VKP / RAW / Generation clicks
var
AComponent: TComponent;
AControl: TControl;
i: Integer;
begin
for i := Low(cArray) to High(cArray) do begin
AComponent := FindComponent(cArray[i]);
if not Assigned(AComponent) or not (AComponent is TControl) then
continue;
AControl := TControl(AComponent);
if AControl.Enabled then
CompListEna.Add(AControl.Name)
else
CompListDis.Add(AControl.Name);
ShowMessage(AControl.Name);
AControl.Enabled := Reenable;
end;
end;
此函数的调用者需要为每个列表提供TStrings
后代。它们可以是TStringList
,也可以是其他后代,例如TMemo.Lines
,因此您可以直接在程序中观察其内容。 (但它们不能只是TStrings
,因为那是一个抽象类。)
正如您所看到的,我对您的代码进行了一些其他更改。使用Reenable
参数的所有代码都可以简化为单个语句。这是因为启用已启用的控件,并禁用已禁用的控件,这是无操作。
此外,Name
是TComponent
的公共属性。在读取该属性之前,您不需要对TControl
进行类型转换,但由于您经常在其他地方进行类型转换,因此引入一个新变量来保存类型转换{{1} }值,这可以使您的代码更容易阅读。易于阅读的代码是易于理解的代码,使调试更容易。
答案 1 :(得分:2)
强调这主要基于Rob的优秀建议,看起来您可以将代码简化为:
procedure DisableContrlOL(const cArray : array of string;
ReEnable : boolean = False);
var
AComponent: TComponent;
begin
for i := Low(cArray) to High(cArray) do
begin
AComponent := FindComponent(cArray[i]);
if Assigned(AComponent) then
if (AComponent is TControl) then
begin
ShowMessage(TControl(AComponent).Name);
TControl(AComponent).Enabled := ReEnable;
end;
end;
end;
不清楚字符串列表的用途,因为当执行离开此过程的范围时,它们的内容会丢失。如果要返回它们,则应在调用代码中创建并释放它们。
答案 2 :(得分:0)
这看起来确实应该有效。这是调试器可以提供的功能,而不仅仅是我们可以提供帮助。
尝试将有问题的行分解为多行,如下所示:
if TControl(AComponent).Enabled then
CompListEna.Add(TControl(AComponent).Name)
else CompListDis.Add(TControl(AComponent).Name);
使用“使用调试DCU”选项重建,并在 if 语句上放置断点。然后使用F7跟踪逻辑,看看发生了什么。