Call procedures in changeable order

Could anyone please help me in the following problem?

There are four (or more) procedures which look like that:

procedure TForm1.Zero;
begin
  DoThis;
end;

procedure TForm1.One;
begin
  DoThat;
end;

procedure TForm1.Two;
begin
  DoSomething;
end;

procedure TForm1.Three;
begin
  DoAnother;
end;

How could the user execute some of them in a user-desired order during run-time?
That means the user selects to execute following procedures.

Two;
Zero;
Three; //in that order,

or in another running

One;
Two;

Variables involving in these procs are declared globally in the implementation section, so their scope covers all procs.

My idea is to save addresses of each proc in an array of pointers (how?), then follow array-items in the wished order, for example [2] [0] [3] or [1] [2], then call procedure that each pointer points to.

If this idea could work efficiently, please advice me (or any other idea could implement this question). I use D6.

Best regards

Nikif
nikifAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mlmccCommented:
Would they ever run a procedure more than once?

You could have the application first prompt the user for the order of execution saving the values in an array.  Then Loop through the array testing the values and calling the appropriate procedure

mlmcc
0
nikifAuthor Commented:
Every selected procedure will run just once.
The user decides which procedures will run in which order.
How could I get adresses?
How can I run a procedure by his pointer?

nikif
0
mlmccCommented:
Why do you need addresses/pointers?

A simple loop like

For I := 1 to 4 do
    If ProcedureName[I] = "ONE" then
        ProcedureOne
    Else If  ProcedureName[I] = "TWO" then
        ProcedureTwo
    Else If  ProcedureName[I] = "THREE" then
        ProcedureThree
    Else If  ProcedureName[I] = "FOUR" then
        ProcedureFour;

Open in new window

mlmcc
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

MerijnBSr. Software EngineerCommented:
mlmcc's solution is fine, keep in mind it's case sensitive though. If you don't want that either use uppercase() or lowercase() on both sides, or use SameText() :)
0
Duy PhamFreelance IT ConsultantCommented:
You don't really need to hold pointers of your procedures. Simply use procedure names and let's users to define the order of procedure calls with those names, and then using If statement to call appropriate procedures.

Sample pseudo code
procedure CallProcedure(procName: String);
begin
    if procName = 'Zero' then Zero;
    if procName = 'One' then One;
    if procName = 'Two' then Two;
    ...
end;

procedure ExecuteProceduresUsingOrderDefinedByUsers(arrOrder : Array[1..10] of String);
var i : Integer;
begin
    for i := 1 to 10 do
    begin
        CallProcedure(arrOrder[i]);
    end;
end;

Open in new window

0
Bruno BuesserCommented:
Use a TListBox and drag and drop for ordering the procedures. The user can simply move the procedures by mouse.
Store the procedure pointers into the list box by using a holder object since the procedures are object methods and need two pointers. It's not possible to just use the @ Operator and simply make a TObject(@proc) type cast.

Below the whole code in XE7 which you can also use in D6 with minor changes.
Set the DragMode of the ListBox1 to dmAutomatic.

unit MainForm;

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)
    ListBox1: TListBox;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure Button1Click(Sender: TObject);
    procedure ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
  private
    procedure Zero;
    procedure One;
    procedure Two;
    procedure Three;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


type
  TProc = procedure of object;

  TProcHolder = class
    Proc: TProc;
    constructor Create(AProc: TProc);
  end;

  constructor TProcHolder.Create(AProc: TProc);
  begin
    Proc:= AProc;
  end;

procedure TForm1.Zero;
begin
  ShowMessage('Zero');
end;

procedure TForm1.One;
begin
  ShowMessage('One');
end;

procedure TForm1.Two;
begin
  ShowMessage('Two');
end;

procedure TForm1.Three;
begin
  ShowMessage('Three');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to ListBox1.Items.Count - 1 do
    TProcHolder(ListBox1.Items.Objects[i]).Proc;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.AddObject('Zero', TProcHolder.Create(Zero));
  ListBox1.Items.AddObject('One', TProcHolder.Create(One));
  ListBox1.Items.AddObject('Two', TProcHolder.Create(Two));
  ListBox1.Items.AddObject('Three', TProcHolder.Create(Three));
end;

procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  SourceIndex: Integer;
begin
  SourceIndex:= ListBox1.ItemAtPos(Point(X,Y),True);
  ListBox1.Items.Exchange(ListBox1.ItemIndex,SourceIndex);
end;

procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept:= True;
end;

end.

Open in new window

0
nikifAuthor Commented:
Thank you all you looked into this question.
I should award 220 points to mlmcc for the simplicity of the solution and prompt reply. It was much simplier than I thought.
I give 180 points to Duy Pham who also described a similarly simple solution.
I kept 100 points for Bruno Buesser for the very strict reply and completeness of his solution, although I cannot still test it in XE7. I am in the prehistoric era of D6.
Kind regards
Nikif
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.