1

I have two components created dynamically, a button (btnEnter) and an edit (edtID)- where the user will enter their user ID. What I want is for the program to verify whether the user has entered a valid ID when they have clicked the button.

The code I have:

1)When the objects are created

    with btnEnter do
    {edit properties such as caption, etc}
    OnClick := ValidateID;

2)The procedure is declared as follows:

    procedure ValidateID (Sender : TObject);

What I would like to do is pass the text in the edit through the procedure as a parameter, so that the procedure will be able to manipulate the text and determine whether it is valid or not.

So what I tried, but didn't work was:

    procedure ValidateID (Sender : TObject; sID : string);

    with btnEnter do
    OnClick := ValidateID(edtID.Text);

Would really appreciate if someone could help me with this. Thanks

  • The assignment (OnClick := ) does not fire the event, even if you could have an arbitrary event signature it wouldn't help you. I guess you have to hard-code code in the click handler. – Sertac Akyuz Jun 30 '15 at 19:09
  • The assignment is just a callback. The event is triggered an the callback is called. You have to respect the type signature (_procedure(Sender: TObject)_). I don't see why you couldn't test the edit value in _ValidateID_. They are in the same context, you can access it's value so what is the problem? – Sotirca Mihaita George Jun 30 '15 at 19:21

2 Answers2

2

The TButton.OnClick event is of type TNotifyEvent which has a signature:

  TNotifyEvent = procedure(Sender: TObject) of object;

Thus, you can not assign a procedure with a different signature to TButton.OnClick.

You need to declare the ValidateID procedure as a method of the form class and then, since the TEdit is on the same form, it is in the same scope as your validation method, and you can simply access EditID.Text in your ValidateID method.

Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
1

This code works.

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    button: TButton;
    edit: TEdit;
    procedure ValidateID(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);
begin
  edit := TEdit.Create(self);
  button := TButton.Create(self);
  button.Parent := Form1;
  edit.Parent := Form1;
  edit.Left := 1;
  edit.Top := 1;
  button.Left := 1;
  button.Top := 50;
  button.OnClick := ValidateID;
end;

procedure TForm1.ValidateID(Sender: TObject);
begin
  ShowMessage(edit.Text)
end;

end.
asd-tm
  • 3,381
  • 2
  • 24
  • 41
  • 2
    Great. Now *explain* what it is about that code that makes it work. Don't make everyone study the code to find the important parts. – Rob Kennedy Jun 30 '15 at 20:04
  • 1
    There is no `FreeOnRelease()` method in VCL controls. Use `Free()` instead. Which in this example is redundant, since the `TForm1` is assigned as their `Owner` and will take care of freeing them automatically. – Remy Lebeau Jun 30 '15 at 20:11
  • 2
    If the form would be shown twice or more times, your code would raise AV the second time it is shown. The default `Action: TCloseAction` is `caHide` which means that the form is not destroyed (just made not visible) and subsquently not created when called up again. Thus the freed TEdit and TButton are not recreated, and AV follows when they are accessed. – Tom Brunberg Jun 30 '15 at 20:37