Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RadioButtons save last checked instead of desired one when form displayed again

I have some TRadioButtons on Form2 and call Form2 from Form1 with this code:

procedure TForm1.btnCallForm2Click(Sender:TObject);
begin
  Form2.RadioButton2.Checked:= true;
  Form2.ShowModal;
end;

If user clicked btnCallForm2, Form2 will be displayed, then user clicks RadioButton3 and closes the form, and then reopen it by clicking btnCallForm2 again.

Now Form2 displayed again but RadioButton3 is checked instead of RadioButton2.

Q: What is this behavior, is it a bug? How to set checked my desired RadioButton instead of what is selected by the user in previous turn?

like image 926
SAMPro Avatar asked Dec 04 '19 13:12

SAMPro


1 Answers

This is not a bug. The reason that you have this "strange" behavior is that if the Form2 is not destroyed, then next time it becomes visible (e.g. ShowModal) it remembers which control had the focus.

In your case the last control in focus is the RadioButton3 (because you clicked on it to change the "checked" state). So even if you are changing the "checked" state back to RadioButton2, the focus will be restored to RadioButton3 when the form is next activated. To restore the focus, the control is sent a WM_SETFOCUS. Read the rest from documentation for default message processing for button controls:

WM_SETFOCUS   Draws a focus rectangle on the button getting the focus. For radio buttons and automatic radio buttons, the parent window is sent a BN_CLICKED notification code.

This BN_CLICK notification (WM_COMMAND message) sets the state of the radio button to checked.

The rationale behind this behavior can be found while navigating the radio buttons with the keyboard. When you press up/down arrow while on one of the radio buttons, the next radio button that receives the focus becomes checked.

This behavior only applies to radio buttons, e.g., try the same with another control (e.g. check box), that its state is not altered when it has focus. You will see that everything is working as expected

As kobik was suggesting, a fast and easy solution would be to set the ActiveControl to nil before showing the Form2

Form2.ActiveControl := nil;

or in the light of the documentation:

Form2.ActiveControl := Form2.RadioButton2;

or you could destoy and recreate the form as following:

Remove the Form2 from the AutoCreated Forms in Project->Options->Forms and create it manually in the ButtonClick event

procedure TForm1.btnCallForm2Click(Sender:TObject)
begin
  Form2 := TForm2.Create(nil);
  try
    Form2.RadioButton2.Checked:= true;
    Form2.ShowModal;
  finally
    FreeAndNil(Form2);
  end;
end;
like image 134
MaGiC Avatar answered Oct 28 '22 03:10

MaGiC