1
\$\begingroup\$

I am trying to learn callbacks in Delphi (7). Could not find a complete simple tutorial, so I puzzled together a few bits here and there. This is my first attempt, of course trivial.

My form contains a button and a label. For the test, I make a loop in the onClick code, and every time do a callback function.

picture of simple form with 1 button and a label

The code is below. It works, but I am in doubt if it's "correct" to have application.processmessages where I have it. And, if I define / apply the callback functionality correctly.

// ----------- demo to test Callbacks
// https://stackoverflow.com/questions/11314641/method-pointer-and-regular-procedure-incompatible
//

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;


type

  TCallBackFunction = procedure(sig: integer) of object;

  TForm1 = class(TForm)
    lblProgress: TLabel;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
    procedure tcb (sig: integer);
  public
    { Public declarations }
    procedure dowithcallback(const something: integer; thefunction: TCallBackFunction);
  end;

var
  Form1: TForm1;
  testvar : integer;


implementation

{$R *.dfm}

// test procedure used for callback argument
//
procedure TForm1.tcb(sig: integer);
begin
   testvar := sig;
   lblProgress.Caption := inttostr(testvar);
   application.ProcessMessages ;
end;


//  The procedure that defines the callback function
//
procedure TForm1.dowithcallback(
        const something: integer;
        thefunction: TCallBackFunction);
begin
     if assigned(thefunction) then
       begin
         thefunction(something)
       end;
end;

//
// button click
//
procedure TForm1.btn1Click(Sender: TObject);
var
  i : integer;
begin
  testvar := 0;
  for i := 1 to 10 do
     begin
        dowithcallback(i, tcb);
        sleep(500);
     end;

end;

end.

Any feedback welcomed!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How to Ask for examples, and revise the title accordingly. \$\endgroup\$
    – Mast
    Commented Sep 27, 2022 at 20:42

1 Answer 1

2
\$\begingroup\$

This question belongs to StackOverflow but not StackExchange. The title is also misleading, as you're asking about the call to application.ProcessMessages but not the callback function. Regarding your question, my opinion is that you should avoid putting UI code in the function and put them together with Sleep.

The other concern is the use of testvar. This global variable seems completely unnecessary in your code. It also makes the code thread-unsafe. Why did you use it? If you really need it, declare it as a member of TForm1 and not a global variable. It's still not thread-safe but better. Using global variables is against the principle of OOP and very bug-prone.

One last thing, as a benefit of separating codes from UI handling, both tcb and dowithcallback can now be declared as regular functions and not class functions. They run faster.

type
  TCallBackFunction = function(sig: integer): string;

function tcb(sig: integer): string;
begin
  Result := inttostr(sig);
end;

function dowithcallback(
        const something: integer;
        thefunction: TCallBackFunction): string;
begin
  if assigned(thefunction)
    then Result := thefunction(something)
    // else Result := '';   
    // the else part is not needed because Result is defaulted to ''
end;

procedure TForm1.btn1Click(Sender: TObject);
var
  i : integer;
begin
  for i := 1 to 10 do
     begin
        lblProgress.Caption := dowithcallback(i, tcb);
        application.ProcessMessages ;
        sleep(500);
     end;
end;
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.