0

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.
Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • I see other reporting this error in Delphi IDE: https://stackoverflow.com/questions/161187/error-cannot-change-visible-in-onshow-or-onhide-in-delphi-ide – Gabriel Nov 23 '17 at 10:19
  • 1
    Can we have a [mcve]? – David Heffernan Nov 23 '17 at 10:27
  • 2
    Off site links are no good. We need a [mcve] here on site. – David Heffernan Nov 23 '17 at 10:34
  • @DavidHeffernan - code pasted in – Gabriel Nov 23 '17 at 10:38
  • Thanks. I guess that the problem is that the radio button checking is postponed while the form is hidden. My guess is that you will need to perform the showing and hiding before clicking the radio buttons. And you may well need to suppress the radio button event handlers while you do that. But in any case, I think you would probably benefit from better GUI design. – David Heffernan Nov 23 '17 at 10:43
  • 1
    FWIW I could not try in XE7, but in 10.1 Berlin it worked as expected, and even hiding Form2 when button1 is clicked on Form2 (which you don't show) worked fine. – Dsm Nov 23 '17 at 10:49
  • @DavidHeffernan - I agree that the design was bad. I changed that yesterday but I returned to the probem to see why it appears. Initially I thought it is related to TAction. All tose radiobuttons were connected to actions. ----------- Related to postponing: I put a breakpoint after RadioBox1.checked:= true, and the Inspector says it is checked! So... I don't think it is a "postpone" problem. – Gabriel Nov 23 '17 at 10:54
  • @Dsm - So, there are two reports that my code works in Delphi 10. Which confirms it is a bug in Delphi XE7 (and below). Thanks. There are quite a fee similar reports out there, some in Delphi IDE itself. – Gabriel Nov 23 '17 at 10:57
  • Have you tried posting yourself a custom message and doing your twiddling in that? – MartynA Nov 23 '17 at 11:26
  • @MartynA - Yes. I tried that but not difference. Anyway, there is a much simple workaround. See my answer. – Gabriel Nov 23 '17 at 12:08
  • And you tried `HandleNeeded`, with the original order? – MartynA Nov 23 '17 at 12:43
  • @MartynA - nope. How that will help? I though a form always have a Handle even if the form is invisible. – Gabriel Nov 23 '17 at 12:53
  • Well, my understanding it that a form and its components don't get handles until the form is actually shown. So HandleNeeded exists to create one if it is needed beforehand. – MartynA Nov 23 '17 at 12:56
  • @MartynA - Yes, but that is at 'creation'. I think once it was create it won't loose the handle. I quote the manual: "Do not refer to the Handle property during component creation or streaming". They explicitly say "during component creation". – Gabriel Nov 23 '17 at 13:35
  • I was formulating an answer, then realized that you are not complaining about the error, but that the RadioButton2 is re-checked (your title might be misleading a bit). I figured out how (WM_COMMAND message addressed to the button), but not why. – nil Nov 23 '17 at 16:54
  • "it won't loose the handle" You are aware that VCL window handles are frequently recreated during the lifetime of a form or component. You shouldn't assume that a component will retain the same handle. See e.g. https://stackoverflow.com/questions/37614161/why-tform-handle-is-a-getter-instead-of-a-field – MartynA Nov 23 '17 at 17:27
  • @nil - post your answer. we see where it takes us. "you are not complaining about the error" - well.... there are two errors in my question. solving just one of them is still a step forward :) – Gabriel Nov 23 '17 at 20:23
  • @MartynA - I just called HandleNeeded in TForm2.Button1Click. It doesn't help :( – Gabriel Nov 24 '17 at 16:17
  • @MartynA - HandleAllocated returns TRUE anyway. – Gabriel Nov 24 '17 at 16:19
  • The question linked in the UPDATE no longer exists (removed due to moderation). – RobinP Oct 29 '20 at 14:06

2 Answers2

1

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

Gabriel
  • 20,797
  • 27
  • 159
  • 293
-2

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.

Sanders the Softwarer
  • 2,478
  • 1
  • 13
  • 28
  • And so what? Now Form2 visible when and only when RadioButton2 is checked.What else do you want? – Sanders the Softwarer Nov 23 '17 at 10:29
  • Maybe yes, maybe no. I cannot download your example and check it. It can be different typos or something make same effect. – Sanders the Softwarer Nov 23 '17 at 10:31
  • @Alaun: Stop insisting that people go somewhere to download a file. A .dfm is text, and can be copied and pasted directly into your question. Nobody should have to leave this site in order to get information. If you can't include it here in your question, it doesn't exist. See the [help] guidelines, especially [ask] and [mcve] (as has been mentioned several times before). – Ken White Nov 24 '17 at 23:40
  • @SanderstheSoftwarer-Hi. Your code is different than mine. Maybe this is why your code is working. – Gabriel Nov 25 '17 at 12:36
  • 1
    @Alaun: You're assuming I voted. You know the saying about *ass-u-m-ing*, right? And *revenge* would mean *paying you back*, and I have nothing to take revenge for. Casting wild accusations without any facts isn't going to work out well for you here. And my comment to this post about an MCVE was in response to the (now-deleted) commend you left about our needing to DOWNLOAD your file to see the problem. Don't lie and act all innocent now that you've been called out for it. – Ken White Nov 25 '17 at 13:47
  • @KenWhite- Why do you defend Sanders? He is a big boy. He can take care of himself. He won't download anything if he doesn't want to. No gun pointed as his head. If you think I was bullying him or was unrespectful to him, alert a moderator. – Gabriel Nov 25 '17 at 14:00
  • @KenWhite - I won't dignify you with an answer anymore. Do complain to a moderator if you think I did something unjust to Sanders. This bickering is childish. Sanders, I apologies for all this noise on your post. – Gabriel Nov 25 '17 at 14:35