1
votes

Im relatively new to Pascal and, though i have a fair understanding of the language, there's still some stuff i cant figure out how to implement. I've ran into this problem and, after trying for like hours on my own and looking for similar cases on the internet, i have not found anything. I hope this question is a fair one because, honestly, i dont know how to figure this out.

Here's the thing.

I have an application which dynamically creates TextBoxes (TextEdits in this case) and adds them to a panel for displaying. Thing is, i need to execute some procedures on the newly created elements. I added a new procedure in my app (this is for explaining purposes only):

procedure Demo_Procedure(i: integer, a: String);

Then i proceeded to "develop" my procedure underneath the "implementation" part of the Form.

procedure Demo_Procedure(i: integer, a: String);
begin
      ShowMessage(a, '  ' ,i);
end;

Now, for my dynamically created elements im trying to set the "OnKeyDow" event to run my new procedure (this is what i dont A- know if its possible to do or B- how to do it)

NewlyButton.OnClick:= Demo_Procedure(5, 'Hi');

Im getting different errors depending on how i call up my procedure. For example:

If i do it like this: Demo_Procedures(5, 'Hi'), it says:

Error: Incompatible types: got "untyped" expected "procedure variable type of procedure(TObject,var Word,TShiftState) of object;Register>"

Now, researching around i found out that some people that put an '@' before calling the method, the only difference is that this time instead of saying "untyped" it says that it got "procedure variable type of procedure(AnsiString,LongInt) of object" and that it was expecting the same as before (procedure(TObject,var> Word,Tshift...etc)

Can anyone help me out here? I really am lost so any help would be greatly appreciated. Thanks in advance :)

1
You can only assign a 'method', a procedure of an 'object'. See methods. - Sertac Akyuz
In Object Pascal there is no built-in language construct available which would allow simple creation of lambda functions which in turn might be used as 1st class citizens together with other ... of object functions. The thing you are trying to grasp is probably GoF Command pattern - xmojmr

1 Answers

3
votes

There are errors in your code:

procedure Demo_Procedure(i: integer, a: String); // Wrong
procedure Demo_Procedure(i: integer; a: String); // Right, use semicolon as parameters delimiter

ShowMessage(a, '  ' ,i); // Wrong, ShowMessage takes only one string parameter
ShowMessage(Format('%s  %d', [a, i])); // Right, %s means string value and %d means decimal value, see help about Format function

Events is a procedural variables so they have its own types. For example, OnKeyDown event have a type

TKeyEvent = procedure(Sender: TObject; var Key: Word; Shift: TShiftState) of Object;

where of Object means that your event handler must be a class method. So, you can not assign to the event any procedure but only class method with parameters provided in the type declaration.

Here is the simple code:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
    Classes, SysUtils, Forms, Controls, Dialogs, StdCtrls;

type

    { TForm1 }

    TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    private
    public
        { public declarations }
    end;

var
    Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
    e: TEdit;
begin
    e := TEdit.Create(Self); // Create new TEdit control
    e.Parent := Self; // Place control onto the form 
    e.Left := 10; // Set control coordinates
    e.Top := 10;
    e.OnKeyDown := @EditKeyDown; // Assign event handler
end;

procedure TForm1.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
    ShowMessage(Format('Key code is %d', [Key]));
end;

end.