Search code examples
delphidelphi-xe7

"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.

Solution

  • 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