Link to home
Start Free TrialLog in
Avatar of reddarin
reddarin

asked on

Unsatisfied forward or external declaration: '<Procedurename>'

I can't help but feel like this is a world class dumb question but...

I recently moved to Delphi from VB and I can't for the life of me figure out how to add procedures or functions that are visible throughout the unit. What I mean by that is that I'd like to add a procedure to the click event of a component by selecting it from the dropdown box on the Object Inspector.

I'm using Delphi 4.0 Standard no service packs.

Here is a brand new project with one button on the form:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

end.

Here is a procedure that I'd like to be able to select from the dropdown box:

procedure GodThisIsKillingMe;
begin
showmessage('What a dummy');
end;

Darin


Avatar of simoraikov
simoraikov

put this in the private (or public doesn't matter) section of TForm1 class
procedure GodThisIsKillingMe;
The easiest thing to do, is go to the DropDown box, and simply DoubleClick there.
Then you'll AUTOMATICALLY get this procedure written for you (I mean, the outline of it).

The best option, is to use 'Actions' (A cool new delphi 4 feature). You simply make a list of actions (Like that Procedure of yours). Then you 'attach' the action to the button of yours (Each component (Well, most of them) has an action property).
It's very simple, and it's great because you ALWAYS need several UI elements making the same action (The main menu, and a button, and a pop-up menu...).
It's nice.

Bye,
        Ron.
Avatar of reddarin

ASKER

That gave me the same error.

Just to be sure I am doing as you instructed, here is the adjusted code:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
  private
    { Private declarations }

  public
  procedure GodThisIsKillingMe;

    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
procedure GodThisIsKillingMe;
begin
showmessage('What a dummy');
end;


end.

sorry

procedure GodThisIsKillingMe(Sender: TObject);


No, that did not change the error message.
shadow,

That doesn't really address the problem I am having. I know that I can create the procedure by double clicking.

For instance, I have a generic procedure that will perform a some formatting on the text in a text box. I have 5 text boxes. For each text box, I want to assign the OnClick event to this generic procedure. Currently, I have to go ahead and create 5 individual OnClick events for the text boxes that have one line calling the generic procedure. Very sloppy and it doesn't change the code of the generic procedure since I still have to find out who is calling it.

Darin
Shadow:

You are right about the Action List and it will work, but it is not what I am looking for. How was it done before Delphi 4?
Lets see if I understand your question. In many of my programs I have a list of textboxes that all share the same OnChange event. The easy way to do this is select the first text box and then go to the obeject inspector and double click the onchange event. Insert the code that needs to happen. Then click on the rest of the text boxes and go back to the object inspector. Now in the blank Onclick event press the drop down arrow and select the onclick event that you just wrote.

Is this what you are trying to do?
Do you want to use 1 procedure for all the text boxes?
Just write it to work for one text box, and then add her name in object inspektor for the other 4 boxes in the onClick event
Do you want to use 1 procedure for all the text boxes?
Just write it to work for one text box, and then add her name in object inspektor for the other 4 boxes in the onClick event
revdmv, faster than me...
Reddarin,

It's normal that this doesn't work, because GodThisIsKilling is a method of the object named Form1

So you should make it :

procedure Form1.GodThisIsKillingMe;

Zif.
Hi reddarin, some hints for you:

(1) As simoraikov pointed out, such functions/procedures MUST be part of an object. That means they must be declared in a part of your form (e.g. in "private") and lateron the function declarition must look like this: "procedure/function ->TFORM1.<-blabla".
Let me explain you the reason for this: Such functions that are part of an object ("type TSampleProc = procedure ->of object<-") do have an additional hidden self parameter. It's the same as in C++.

procedure TForm1.FormCreate(Sender: TObject);
begin
  caption:='blabla';
end;

var Form1, Form2 : TForm1;

So now how should Delphi know which caption (Form1.caption or Form2.caption) it has to change?

In reality the function looks like this:

procedure TForm1.FormCreate(->Self: TForm1;<- Sender: TObject);
begin
  ->Self.<-caption:='blabla';
end;

But this Self parameter is hidden. If you declare such a function:

procedure test;

It has no parameter. If you declare such a function:

   ...
   private
     procedure test;
     ...

procedure TForm1.test;

It has one hidden "self" parameter, so that Delphi knows which object it has to look at.

Everything clear with that?

(2) All the event handlers in the object inspector do have different parameter sets. And of course the parameters must be correct. So the object inspector lists in the dropdown combobox only function that have exactly the correct parameters.

Type "OnClick" in your Delphi editor and press F1. Then you should see this:

property OnClick: TNotifyEvent;

Then click on TNotifyEvent. Now you should see this:

type TNotifyEvent = procedure (Sender: TObject) of object;

So if you now want to declare a function that the object inspector lists, you need to declare the function in an object (because of the "of object"), so that Delphi has its hidden self parameter - and you need to declare the correct parameters.

So simoraikov was right with his second answer, too. The only thing we was not right with, is that you need to put this declaration directly under the class section, not in the private section:

type TForm1 = class(TForm)
                ..
                procedure YourNewEventHandler(Sender: TObject);
              private
                ...

Regards, Madshi.

P.S: Wow, did I really write such a long comment?    :-)
Where should I make it like that?
Madshi, seems we were working on the same question, only I was not so 'speakly'.
procedure Form1.GodThisIsKillingMe;
 begin
   showmessage('What a dummy');
  end;

Zif.
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
   private
    { Private declarations }

  public
  procedure GodThisIsKillingMe;

    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
procedure TForm1.GodThisIsKillingMe;
begin
showmessage('good answer zif');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 GodThisIsKillingMe;
end;

end.
Hi Zif, no prob...   :-)
But I don't quite understand what you're doing here!? That won't work with "procedure Form1.blabla"! I've never seen something like this...   :-)

Hi Barry, won't show up in the object inspector combobox, either...   :-)

But revdmv has the fastest solution, I think. reddarin, you should use his suggestion, you can even rename the event handler for all 4 textboxes in the object inspector...
yep revdmv is fatest solution.
Spell it out for me boys - I am dumb as a stick :)

And, I realize that I have really asked two questions that were unrelated - 1) the object inspector howto AND 2) correctly declaring a function/procedure and placing it in the public/private area.

inthe: You have succinctly answered the first question so I have created a new question for you for 50 points. Thanks. [https://www.experts-exchange.com/bin/EQ.10175571]

Madshi:

I believe with the comments you have added and the example that inthe posted, I have a working solution to my question. I will investigate the TNotifyEvent.

Of course, the solution of pointing all the onclick events to one onclick event will work but it is not what I am trying to accomplish. As far as easy goes, it is not my aim. In the past when I have written code like that, I found it very difficult to maintain. That is not to say that I want to do whatever I am doing in the most difficult manner possible. It just doesn’t strike me a very polished approach.


So…

Since madshi has given me the clue for adding procedures to the Object Inspector dropdown, I’d like to award the points to him.

Darin
Ooops. I meant 'inthe answered the second question'.
ASKER CERTIFIED SOLUTION
Avatar of Madshi
Madshi

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ooiitch, I'm striked by a lightning bold.... now Madshi is comming closer :-) grin. I'll have to search some time multiplier to stay in front.
don't look at me... my brains are again steaming...
Haha! I think you should better try to hack into the EE system to increase your points instead of trying to invent a time multiplier. Would be much easier, I think...   :-)
Well, I do appreciate the help given by all of the experts.

Zif you definitely have some breathing space before madshi overcomes you :)


P.S: Well, if my "point speed" motivates you to visit EE more often again, it's only good for the questioners. So I'll not stop collecting points...  :-)
mmmmm, hacking E-E, not a bad idea.... but I wouldn't cheat my points... I would only reduce Madshi's :-))))

reddarin, I had more some months back :-)
:-))
Wow what a long discussion (Guess I shouldn't fall asleep so soon...).
Anyway, just a note about the actions : THey ARE great, and Who cares what they used before delphi 4? Just be glad they invented this feature. I usually implemented an 'action' list of myself, on another unit, and called the functions from the form's unit (It's always best to seperate the form unit from the actual algorithms/functions you have, IMO).

cheers!
Shadow, I don't mean to be insulting, but that line about 'just be glad' kinda gets my goat. Have you ever used VB? If I wanted to be protected from the complexities of programming, I'd have stuck with that language.