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

2
  • 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. Commented Jun 30, 2015 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? Commented Jun 30, 2015 at 19:21

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

3 Comments

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.