处理表单时访问冲突

Xaw*_*cki 0 delphi

我有程序在TForm上显示/隐藏一个元素,如:

procedure ShowHideControl(const ParentForm: TForm; const ControlName: String; ShowControl: Boolean);
var
  i: Integer;
begin
  for i := 0 to pred(ParentForm.ComponentCount) do
  begin
    if (ParentForm.Components[i].Name = ControlName) then
    begin
      if ShowControl then
        TControl(ParentForm.Components[i]).Show
      else
        TControl(ParentForm.Components[i]).Hide;

      Break;
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

然后我尝试使用它像:

procedure TForm1.Button6Click(Sender: TObject);
begin
  ShowHideEveryControl(TForm(TForm1), 'Button4', True);
end;
Run Code Online (Sandbox Code Playgroud)

为什么我在Button6点击时会出现访问冲突?

对我来说一切都很好...... Button4作为一个孩子存在:)

Dav*_*nan 5

这个演员是错的:

TForm(TForm1)
Run Code Online (Sandbox Code Playgroud)

您告诉编译器忽略TForm1不是TForm实例的事实,并要求它假装它是实例.在您实际尝试将其用作实例之前,这很好,然后发生错误.

你需要将一个真实的实例传递给TForm后代.你可以像这样写:

ShowHideEveryThing(Self, 'Button4', True);
Run Code Online (Sandbox Code Playgroud)

如果您不清楚这一点,您的过程参数是类型TForm.这意味着您需要提供一个或者派生的类的实例TForm.我再说一遍,你必须提供一个实例.但是你提供的TForm1是哪一.


然后下一个问题来到这里:

if (ParentForm.Components[i].Name = FormName) then
begin
  if ShowForm then
    TForm(ParentForm.Components[i]).Show
  else
    TForm(ParentForm.Components[i]).Hide;

  Break;
end;
Run Code Online (Sandbox Code Playgroud)

你再次使用了错误的演员.当编译器告诉您某个特定对象没有方法时,您必须听它.将编译器关闭并伪装成一种类型的对象实际上是不同类型的对象并不好.您的按钮绝对不是表单,因此请勿尝试将其转换为表单TForm.

很难知道你在这里想要做什么.当你写:

ShowHideEveryThing(Self, 'Button4', True);
Run Code Online (Sandbox Code Playgroud)

在我看来,写作更加明智:

Button4.Show;
Run Code Online (Sandbox Code Playgroud)

使用表示为文本的名称来引用控件并不是一个好主意.使用引用变量引用它们更安全,更清晰.这样你就让编译器完成它的工作并检查程序的类型安全性.


您的函数中使用的名称是可疑的:

procedure ShowHideEveryThing(const ParentForm: TForm; const FormName: String; 
  ShowForm: Boolean);
Run Code Online (Sandbox Code Playgroud)

我们来看看它们:

  • ShowHideEveryThing:但您声称该函数应显示/隐藏一个元素.这并不符合一切的使用.
  • FormName:您实际传递组件名称,然后查找ParentForm具有该名称的组件所拥有的组件.这似乎FormName是错误的.
  • ShowForm:再次,您想控制表单或单个元素的可见性吗?

显然,你需要退后一步,明确这个功能的意图.


顺便说一句,你通常不需要写:

if b then
  Control.Show
else
  Control.Hide;
Run Code Online (Sandbox Code Playgroud)

相反,你可以写:

Control.Visible := b;
Run Code Online (Sandbox Code Playgroud)

我给你的第一条建议就是停止施法,直到你理解它为止.一旦你理解正确,尽可能设计你的代码,这样你就不需要施放.如果你真的需要施放,请确保你的施法是有效的,理想情况是通过对as操作员使用经过检查的施法.或者至少首先与is运营商进行测试.

您的代码显示了经典错误的所有标志.编译器对应于您编写的代码.您已从某处了解到可以使用转换来抑制这些编译器错误,现在您可以广泛应用此技术作为编译程序的方法.问题是编译器总是知道它在说什么.当它反对时,听它.如果您发现自己使用演员表来抑制编译器错误,请退后一步,仔细考虑您正在做什么.编译器是你的朋友.