IceCold
IceCold

Reputation: 21154

"Cannot change Visible in OnShow or OnHide" error

Update:
This question escalated to a new/related question which was fortunately solved by @RemyLebeau here.

So, instead of reading below, you should go directly to Major flaw - Radio buttons are not correctly set while the form is invisible

Thanks Remy


I have two form. When I click a radiobtn, I want to hide one form and show the second one.

Hide Form1 and show Form2:

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

In Form2 I press a button to 'return' to Form1:

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

However, I get this error when I try to make Form1 visible:

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

Putting a breakpoint in RadioButton2Click I find out that RadioButton1 was magically rechecked during Form1.Visible:= TRUE (during TCustomForm.SetVisible more exactly).

Why is the RadioButton2 'magically' checked during SetVisible?


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.

Upvotes: 0

Views: 6603

Answers (2)

IceCold
IceCold

Reputation: 21154

The workaround (not the final fix) is to do the changes to the GUI (form1) AFTER you make it visible!


Update!
The bug is related to the TabOrder property! Details

Upvotes: 1

Sanders the Softwarer
Sanders the Softwarer

Reputation: 2496

Direct references from one form to fields of another is bad design and I highly advice you to change this. But anyway, I made two forms: first with two radiobutton, second with a button. Handlers:

{ 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;

It works fine, without any remark. Delphi 10.1 Berlin.

Upvotes: -2

Related Questions