?
Solved

Function creation and function run during run-time. Is it possible?

Posted on 2003-03-10
14
Medium Priority
?
235 Views
Last Modified: 2010-05-18
Hi there,

I have a word called 'load' of type string and I want it to be a function
this word 'load' would change often of course.

ya know how ya would have

function TForm1.Load(file : string; fileavailable : boolean);
begin
    // begin code here..
end;

well I dont want that.... I want something like this

      Procedure TForm1.OnCreate(Sender : TObject);
      function TForm1.Load(file : string; fileavailable : boolean);
      function TForm1.Function(function : string; functionavailable : boolean);


Procedure TForm1.OnCreate(Sender : TObject);
begin
   Form1.Function(load,true);
end;

function TForm1.Function(function : string; functionavailable : boolean);
var
   functionstring : string;
begin
   functionstring := function;
   // now insert code here to initialise load function based on functionstring or even function.
   // im guessing it might be something like this

   TForm1.(string);  // which I know wouldn't work.
end;

function TForm1.Load(file : string; fileavailable : boolean);
begin
   file := 'loadme.txt'
end;

I just want the function to load based on what the string becomes.

0
Comment
Question by:Alpha_AI
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 3
  • +4
14 Comments
 

Author Comment

by:Alpha_AI
ID: 8107531
if you have any questions, please ask me.

0
 
LVL 6

Expert Comment

by:swift99
ID: 8108023
This doesn't make sense.  At first it sounds like you're trying to reinvent the DLL, but hten it sounds like you're trying to reinvent the compiler.  Please clarify.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 8108667
hello Alpha Al. . . . I can not understand what you want to do?? But from your last Line
"I just want the function to load based on what the string becomes." ???

If you can limit the "Input" string to a Set of Strings, like

'Load'
'Reset'
'Cancel'
'Next'
'Unload'

then you just compare the input string and execute the function for that string

if Edit1.Text = 'Load' then
Form1.Load else
if Edit1.Text = 'Reset' then
Form1.Reset;
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 27

Accepted Solution

by:
kretzschmar earned 200 total points
ID: 8109379
a sample

unit Unit1;

interface

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


type
  TForm1 = class(TForm)
    CheckBox1: TCheckBox;
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public

  published
    //must be published
    Procedure Load (FileName : String; Avail : Boolean);
    Procedure WhatEver(AString : String; ABool : Boolean);
    Procedure Call_Proc(AProc : String; AString : String; ABool : Boolean);
    { Public declarations }
  end;

  TProcInterFace = Procedure(s : String; b : Boolean) of Object;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Procedure TForm1.Load (FileName : String; Avail : Boolean);
begin
  ShowMessage('Load Called'+#10+'String:'+FileName);
end;

Procedure TForm1.WhatEver(AString : String; ABool : Boolean);
begin
  ShowMessage('WhatEver Called'+#10+'String:'+Astring);
end;

Procedure TForm1.Call_Proc(AProc : String; AString : String; ABool : Boolean);
var
  p : TProcInterFace;
begin
  try
    @p := MethodAddress(AProc);
    if @p = nil then
      raise exception.Create('Method not available');
  except
    raise;
  end;
  p(AString,ABool);
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  Call_Proc(Edit1.Text,Edit2.Text,checkBox1.Checked);
end;

end.


meikl ;-)
0
 
LVL 17

Assisted Solution

by:geobul
geobul earned 300 total points
ID: 8109473
Hi,

Here is an example how this could be done. In Edit1 enter the name of the procedure 'Load'. In Edit2 enter a parameter (filename for example). Then press the button. The second procedure Foo is executed without parameters in Edit2 (Sender is nil at the call). Foo can be defined as a procedure without parameters.

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    procedure Load(filename: string); // will be called by name
    procedure Foo(Sender: TObject); // will be called by name
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ExecuteRoutine(Instance: TObject; Name: string; Param: TObject); overload;
    procedure ExecuteRoutine(Instance: TObject; Name: string; Param: string); overload;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type
  TExecuteObject = procedure (Sender: TObject) of object;
  TExecuteString = procedure (param: string) of object;

procedure TForm1.ExecuteRoutine(Instance: TObject; Name: string; Param: TObject);
var
 Routine: TMethod;
 Execute: TExecuteObject;
begin
 Routine.Data := Pointer(Instance);
 Routine.Code := Instance.MethodAddress(Name);
 if Routine.Code = nil then Exit;
 Execute := TExecuteObject(Routine);
 Execute(Param);
end;

procedure TForm1.ExecuteRoutine(Instance: TObject; Name: string; Param: string);
var
 Routine: TMethod;
 Execute: TExecuteString;
begin
 Routine.Data := Pointer(Instance);
 Routine.Code := Instance.MethodAddress(Name);
 if Routine.Code = nil then Exit;
 Execute := TExecuteString(Routine);
 Execute(Param);
end;

procedure TForm1.Foo;
begin
  ShowMessage('foo');
end;

procedure TForm1.Load(filename: string);
begin
 ShowMessage('The filename is:'+filename);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ExecuteRoutine(Form1, Edit1.Text, Edit2.Text);
end;

Regards, Geo
0
 
LVL 17

Expert Comment

by:geobul
ID: 8109488
Hi meikl, you've said that already. I must have refreshed my browser :-)
0
 

Expert Comment

by:WhoPhlungPoo
ID: 8109512
Ok, I think I have a pretty good idea on what you are trying to do.  You are attempting to pass a string to a function that will call some other function based up on the string name you choose.  Provoded below is one way of doing this, it is NON-Case sensitive.  This function also assumes that we are always dealing with procedures and does not account for parameter passing.  If you want parameter passing you have to use another method that is about 10 times more complicated to implement.  Please note that in each procedure that is to be called using your procedure calling function, you must have the “With Form1” Statement.  Hope this does what you want…. Enjoy.

//example procedure
procedure TForm1.Load;
begin
  with Form1 do //Very important, without this you could
                //get access violation
    begin
      //place your code here
      label1.caption := 'Booya';
    end;
end;


function RunProcedure(ProcedureName : string):boolean;
  var
    ProcedureExists : boolean;
    MyProcedure     : TProcedure;
    p               : Pointer;

begin
  //Initialize our variables
  ProcedureExists := false;
  p := nil;

  //Get the address of our procedure
  p := Form1.MethodAddress(ProcedureName);

  if p <> nil then
    begin
      //point to our located procedure
      MyProcedure := TProcedure(p);
      //call the procedure
      MyProcedure;
      //set our result to true
      ProcedureExists := true;
    end;

  result :=  ProcedureExists;
end;
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 8109619
you go a slight different way, geo
-> via TMethod, not bad
0
 
LVL 3

Expert Comment

by:smurff
ID: 8110969
listening, and learning ;)
0
 
LVL 6

Expert Comment

by:swift99
ID: 8112614
WhoPhlungPoo :

Form1 is a global ... what if you instantiate more than one TForm1?

You only risk getting a memory exception if "self" is unassigned or NIL - i.e. a rather serious bug.  References to methods and properties of the self are treated as though within a "with self do ..." block.

Don't break encapsulation without serious thought as to the consequences, and then it is generally better for performance and reliability to refactor to maintain encapsulation.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 8112772
i agree with you, swift99,
but it may be for a scripting input
(the only thing, that makes sense for me)

meikl ;-)
0
 
LVL 6

Expert Comment

by:swift99
ID: 8112889
A scripting interpreter ... yes ... but that would not entail what amounts to self modifying code.

Embodied in a Datamodule rather than a form, I can see that having some real uses.
0
 

Author Comment

by:Alpha_AI
ID: 8115823
Ok its looks like someone may have worked it out.
I am not near my computer at mums so i'll have to try the code out then when I get back to mums.

0
 
LVL 17

Assisted Solution

by:geobul
geobul earned 300 total points
ID: 8117374
In my code example above:
procedure TForm1.Foo;
should be
procedure TForm1.Foo(Sender: TObject);

Regards, Geo
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses
Course of the Month13 days, 21 hours left to enroll

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question