"Cannot change Visible in OnShow or OnHide" 错误

"Cannot change Visible in OnShow or OnHide" error

更新:
这个问题升级为 new/related 问题,幸运的是@RemyLebeau here.

解决了这个问题

因此,与其阅读下文,不如直接前往 Major flaw - Radio buttons are not correctly set while the form is invisible

谢谢雷米


我有两种形式。当我点击一个 radiobtn 时,我想隐藏一个表单并显示第二个。

隐藏 Form1 并显示 Form2:

procedure TForm1.RadioButton2Click(Sender: TObject);
begin
 Form2.Visible:= TRUE;
 Form1.Visible:= FALSE;
end;

在 Form2 中我按一个按钮 'return' 到 Form1:

procedure TForm2.Button1Click(Sender: TObject);
begin
 Form1.RadioButton1.Checked:= TRUE;
 Form1.Visible:= TRUE;  <--- this will 'magically' put the RadioButton1 back to false
end;

但是,当我尝试使 Form1 可见时出现此错误:

Project Tester.exe raised exception class EInvalidOperation with message 'Cannot change Visible in OnShow or OnHide'

在 RadioButton2Click 中放置一个断点我发现 RadioButton1 在 Form1.Visible:= TRUE 期间被神奇地重新检查(更准确地说是在 TCustomForm.SetVisible 期间)。

为什么在 SetVisible 期间检查 RadioButton2 'magically'?


unit Unit1;

INTERFACE

USES
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, System.Actions, Vcl.ActnList, Vcl.StdCtrls;

TYPE
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    procedure RadioButton2Click(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
  private
  public
  end;

VAR
  Form1: TForm1;

IMPLEMENTATION {$R *.dfm}

USES Unit2;



procedure TForm1.RadioButton1Click(Sender: TObject);
begin
 Caption:= '1';
end;

procedure TForm1.RadioButton2Click(Sender: TObject);
begin
 Caption:= '2';
 Form2.Visible:= TRUE;
 Form1.Visible:= FALSE;
end;

end.

-

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
  public
  end;

VAR
  Form2: TForm2;

IMPLEMENTATION {$R *.dfm}
USES Unit1;


procedure TForm2.Button1Click(Sender: TObject);
begin
 Form1.RadioButton1.Checked:= TRUE;
 Form1.Visible:= TRUE;
end;

end.

从一种形式直接引用另一种形式的字段是糟糕的设计,我强烈建议您改变这一点。但无论如何,我制作了两种形式:第一种带有两个单选按钮,第二种带有按钮。处理程序:

{ For both radiobuttons }
procedure TForm1.RadioButtonClick(Sender: TObject);
begin
  Form1.Visible := RadioButton1.Checked;
  Form2.Visible := RadioButton2.Checked;
end;

{ For button }
procedure TForm2.Button1Click(Sender: TObject);
begin
  Form1.RadioButton1.Checked := true;
end;

效果很好,没有任何评论。 Delphi 10.1 柏林。

解决方法(不是最终修复)是在 GUI (form1) 可见后对其进行更改!


更新!
该错误与 TabOrder 属性 有关! Details