Delphi Pages Forums  

Go Back   Delphi Pages Forums > Delphi Forum > General

Lost Password?

Closed Thread
 
Thread Tools Display Modes
  #1  
Old 07-29-2015, 06:59 AM
Badger Badger is offline
Member
 
Join Date: Aug 2013
Location: Sheffield, Tasmania (Aust)
Posts: 76
Default Radio Buttons

I'm using a password to protect some Radio Buttons but when the user fails the password test the radio button remains changed.

To overcome this I've tried all sorts of code combinations before the exit line but they all go into an endless loop because changing the state by code is classed as clicking.

There's bound to be an easy answer .- I just can't find it.

This is the (much simplified) code. The radio buttons are on a panel for a reason. I've tried it with a radio group - the same thing happens.

Code:
 
unit Unit1;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
type
  TForm1 = class(TForm)
    Panel1: TPanel;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
var
  Password:Boolean;
procedure TForm1.RadioButton1Click(Sender: TObject);
begin
  password:=false;
  if password=false then
  begin
    Radiobutton1.checked:=false;  //to get buttons back to
    Radiobutton2.checked:=true;   //original condition
    exit;
  end;
end;
procedure TForm1.RadioButton2Click(Sender: TObject);
begin
   password:=false;
  if password=false then
  begin
    Radiobutton2.checked:=false;
    Radiobutton1.checked:=true;
    exit;
  end;
end;
end.
Badger
  #2  
Old 07-29-2015, 11:18 AM
Badger Badger is offline
Member
 
Join Date: Aug 2013
Location: Sheffield, Tasmania (Aust)
Posts: 76
Default

Thought I'd solved my own problem! Switched the boolean password before and after resetting the buttons. But it still goes round in circles.

if password=false then
begin
password=True;
Radiobutton1.checked:=false; //to get buttons back to
Radiobutton2.checked:=true; //original condition
password=false;
exit;
end;

Last edited by Badger; 07-29-2015 at 11:45 AM. Reason: Cottected previous post
  #3  
Old 07-29-2015, 02:10 PM
rojam rojam is offline
Senior Member
 
Join Date: Jun 2015
Posts: 198
Default

Not sure how you intend to use "password", as coded, the if statement will always evaluate to true
Code:
password:=false;
if password=false then
Also, you declare password as a global variable. Never use global variables. If you need a variable that retains its value beyond a local variable, then add it to the form's private or public section.
Code:
  TForm1 = class(TForm)
    Panel1: TPanel;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
  private
    password: Boolean;//makes it available to this unit only
  public
    { Public declarations }
  end;
if you need to avoid the infinite loop of radiobutton Onclick, then simply disconnect the event handler in the code before making changes to the radiobutton.
Code:
procedure RadioButton1Click(Sender: TObject);
begin
  RadioButton1.OnClick := nil;
  try
    RadioButton2.OnClick := nil;
    try
      //do your changes to rb1 and rb2
    finally
      RadioButton2.OnClick := RadioButton2Click;
    end;
  finally
    RadioButton1.OnClick := RadioButton2Click;
  end;
end;

procedure RadioButton2Click(Sender: TObject);
begin
  RadioButton1.OnClick := nil;
  try
    RadioButton2.OnClick := nil;
    try
      //do your changes to rb1 and rb2
    finally
      RadioButton2.OnClick := RadioButton2Click;
    end;
  finally
    RadioButton1.OnClick := RadioButton2Click;
  end;
end;
or you could have a variable that regulates if you execute the code like so
Code:
  TForm1 = class(TForm)
    Panel1: TPanel;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    procedure FormCreate(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
  private
    makingRBChanges: Boolean;
  public
    { Public declarations }
  end;

...
procedure TForm1.FormCreate(Sender: TObject);
begin
   ...
   MakingRBChanges := False;//ensure it's initialized
end;

procedure RadioButton1Click(Sender: TObject);
begin
  if Not MakingRBChanges then
  begin
    MakingRBChanges := True;
    try
      //do your changes to rb1 and rb2
    finally
      MakingRBChanges := False;
    end;
  end;
end;

procedure RadioButton2Click(Sender: TObject);
begin
  if Not MakingRBChanges then
  begin
    MakingRBChanges := True;
    try
      //do your changes to rb1 and rb2
    finally
      MakingRBChanges := False;
    end;
  end;
end;
Notice also, I've wrapped the code in try/finally blocks, that's to ensure that after disconnecting them/setting control variable, the event handlers get reconnected/control variable is reset even if an error occurred.

Last edited by rojam; 07-29-2015 at 07:31 PM.
  #4  
Old 07-29-2015, 10:53 PM
Badger Badger is offline
Member
 
Join Date: Aug 2013
Location: Sheffield, Tasmania (Aust)
Posts: 76
Default

Thanks for the assistance. Was not aware of the RadioButton1.OnClick := nil; capability. (So much to learn - So little time!)

Re the points you mention, I wrote the code specifically to demonstrate the problem rather than try to lift it from the much larger unit. All your points are very pertinent. I would question one though - I understood that by putting the password variable after the implementation line it would be local to the unit. Is this not so?

Badger
  #5  
Old 07-30-2015, 02:32 AM
rojam rojam is offline
Senior Member
 
Join Date: Jun 2015
Posts: 198
Default

Quote:
I understood that by putting the password variable after the implementation line it would be local to the unit. Is this not so?
No, by putting it there, you are in fact making it a global variable, and any other unit that has that unit in its "Uses" clause will have that variable in scope.
Also, as an aside, Delphi puts one variable there by default.
Code:
var
  Form1: TForm1;
It does this for each form in your application. If you create your secondary forms dynamically, and remove those secondary forms from the autocreate list, you can actually safely remove those global variables also (You will only need it for your application's main form).

Furthermore, I would suggest you NEVER actually use the "FormX" variable in your code.

Last edited by rojam; 07-30-2015 at 02:34 AM.
  #6  
Old 07-30-2015, 03:24 AM
Badger Badger is offline
Member
 
Join Date: Aug 2013
Location: Sheffield, Tasmania (Aust)
Posts: 76
Default

OK, I stand corrected. Thanks for your help.
Closed Thread

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump


All times are GMT. The time now is 07:27 PM.


Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2019, vBulletin Solutions, Inc.