在 Delphi 2K9 中运行时禁用和启用组件。 奇怪的问题

发布于 2024-07-28 22:24:37 字数 1282 浏览 5 评论 0原文

这是代码:

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 不,无意冒犯,伙计,没关系。 我很高兴收到如此愿意且有帮助的帖子。 再次感谢。

Here is code:

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;

I think no more explanations are needed.
The ShowMessage correctly shows name of each component, but nothing is added in StringLists. Why?


UPDATE: As question has gone pretty wild, I did confirm answer, which a bit helped me.

I understand that I did write things pretty unclear, but I am very limited, because these code lines is part of commercial project, and my hobby and heart thing. The main problem was found already 6h ago, but Rob just wanted to extend this whole question :D No, no offense, mate, it's OK. I am happy to receive so willing and helpful posts. Thanks again.

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

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

发布评论

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

评论(3

我的影子我的梦 2024-08-04 22:24:37

您怎么知道列表中没有添加任何内容? 您可以在此代码中创建它们,并且对它们的唯一引用位于局部变量中。 当该函数返回时,对象将被泄漏,因此您实际上从未在任何地方使用这些列表。

您说过您有“模块化测试”的代码。 由于该代码不在这里,我必须假设该代码不是该函数的一部分。 但是,如果您有应该检查列表内容的外部代码,那么列表就不能只是局部变量。 没有其他代码可以访问它们。 您需要返回这些列表或接受来自外部的列表,然后填写。 下面是后者的示例:

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 参数的所有代码都可以简化为单个语句。 这是因为启用已启用的控件和禁用已禁用的控件都是无操作。

另外,NameTComponent 的公共属性。 在读取该属性之前,您不需要类型转换为 TControl,但由于您在其他地方经常进行类型转换,因此引入一个新变量来保存类型转换的 < code>TControl 值,这可以使您的代码更易于阅读。 更容易阅读的代码是更容易理解的代码,这使得调试更容易。

How do you know that nothing is added to the lists? You create them in this code and the only references to them are in local variables. The objects are leaked when this function returns, so you never actually use the lists anywhere.

You've said you have code for "modular testing." Since that code isn't here, I must assume the code is not part of this function. But if you have external code that's supposed to check the contents of the lists, then the lists can't be just local variables. No other code can access them. You need to either return those lists or accept lists from outside that you then fill. Here's an example of the latter:

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;

The caller of this function will need to provide a TStrings descendant for each list. They could be TStringList, or they could be other descendants, such as TMemo.Lines, so you can directly observe their contents in your program. (They can't be just TStrings, though, since that's an abstract class.)


As you can see, I made some other changes to your code. All your code using the Reenable parameter can be simplified to a single statement. That's because enabling a control that's already enabled, and disabling a control that's already disabled, are no-ops.

Also, Name is a public property of TComponent. You don't need to type-cast to TControl before reading that property, but since you're type-casting so often elsewhere, it made sense to introduce a new variable to hold the type-casted TControl value, and that can make your code easier to read. Easier-to-read code is easier-to-understand code, and that makes it easier to debug.

格子衫的從容 2024-08-04 22:24:37

强调这很大程度上基于 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;

不清楚字符串列表的用途,因为当执行离开此过程的范围时,它们的内容会丢失。 如果您想返回它们,您应该在调用代码中创建并释放它们。

Emphasizing that this is largely based on Rob's excellent suggestions, it looks as though you could simplify the code to:

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;

Not clear what the stringlists were for, since their contents were lost when execution left the scope of this procedure. If you want to return them, you should create and free them in the calling code.

∝单色的世界 2024-08-04 22:24:37

看起来确实应该有效。 在这种情况下,调试器可能比我们在这里能提供更多帮助。

尝试将有问题的行分成多行,如下所示:

  if TControl(AComponent).Enabled then
    CompListEna.Add(TControl(AComponent).Name)
  else CompListDis.Add(TControl(AComponent).Name);

在打开“使用调试 DCU”选项的情况下重新构建,并在 if 语句上放置一个断点。 然后使用 F7 跟踪逻辑并查看发生了什么。

That sure looks like it ought to work. This is the sort of thing that the debugger can probably help with more than we can here.

Try breaking the problematic line down into multiple lines, like so:

  if TControl(AComponent).Enabled then
    CompListEna.Add(TControl(AComponent).Name)
  else CompListDis.Add(TControl(AComponent).Name);

Rebuild with the "Use Debug DCUs" option on, and place a breakpoint on the if statement. Then use F7 to trace your way through the logic and see what's going on.

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