1

I've downloaded Delphi XE7 and having some problems with accessing another Units... I need to call procedures from another units, so I'll give a very basic illustration, simple program... This is code from main Unit1 with form and button1:

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls, Unit2;
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('Hello');
end;

end.

And this is the code from Unit2:

unit Unit2;
interface
implementation
uses Unit1;
end.

Now, how is it possible to make procedure Button1Click like in Unit2 to showmessage let's say HelloFromUnit2 when button1 on form1 is clicked? Unit2 is codeUnit without anything..

Gem
  • 516
  • 1
  • 8
  • 19
  • What is stopping you doing this? – David Heffernan Nov 24 '14 at 06:34
  • [How can I access a delphi control from outside the form's unit?](http://stackoverflow.com/questions/4428691/how-can-i-access-a-delphi-control-from-outside-the-forms-unit) – bummi Nov 24 '14 at 07:39
  • 2
    I notice also that you tagged the question *unit-testing*. I wonder what the relevance of that is. I can see that you have an understanding of Delphi units, `uses` etc. So I have no idea why you cannot do the simple task expressed in your question. Something tells me that your real problem is much deeper. – David Heffernan Nov 24 '14 at 08:24

3 Answers3

2

Use the build in procedure for calling the Click handler

Leave form 1 the way it is:

unit Unit2;

interface

implementation

uses 
  Unit1;

procedure Click;
begin
  if Assigned(Form1) then
    Form1.Button1.Click;
end;

end.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Jens Borrisholt
  • 6,174
  • 1
  • 33
  • 67
1

Add a procedure declaration to the public section of TForm1, like this

type
 TForm1 = class(TForm)
           Button1: TButton;
           procedure Button1Click(Sender: TObject);
          private
          public
           Procedure SayHello;   
          end;
...
procedure TForm1.SayHello;
begin
 ShowMessage('Hello');
end;

end.

Then in Unit2 you would call this procedure. You would have to ensure that Form2 has already been instantiated - or create a new instance for your call.

Do not use this mechanism for event handlers!

No'am Newman
  • 6,395
  • 5
  • 38
  • 50
  • Why make you own procedure? Why not just use the build in one? – Jens Borrisholt Nov 24 '14 at 05:07
  • @JensBorrisholt: Because as it stands, tform1.button1click is not exposed publicly. Your answer doesn't call the eventhandler but rather a method of a component on the form, which looks even worse. What if form2 only requires part of the event handler code? – No'am Newman Nov 24 '14 at 05:57
  • "tform1.button1click is not exposed publicly" Not sure I follow. The top section of TForm1's declaration, containing Button1 and this click handler is implicitly a published section (and has to be for streaming to work) so is accessible from units which use Unit1. Perhaps I have misunderstood your point? – MartynA Nov 24 '14 at 09:01
  • @MartynA: It seems I'm wrong about the public part. – No'am Newman Nov 24 '14 at 09:07
  • Yes, I've succeed creating functions that i could call from another units, but didn't with the event handlers... I was trying to split code by Units (better organisation) but i guess that's "bad coding" for event handlers. So events of components should stay on units that are "owned" by forms which contain component? – Gem Nov 24 '14 at 10:08
  • @MarkoC: You will see remarks scattered around the Delphi forum of StackExchange that code in an event handler should only be called by the component to which the handler belongs. If the code is required in two places, then the recommendation is to create a separate procedure containing the code, then call this procedure both from the event handler and wherever else it is needed. – No'am Newman Nov 25 '14 at 05:25
1

The header of your post doesn't match the question in the text

"Call Button1Click in Form1/Unit1 from Unit2" vs. "Now, how is it possible to make procedure Button1Click like in Unit2 to showmessage let's say HelloFromUnit2 when button1 on form1 is clicked?"

I answer the question in the text (as I understand it). If this is not what you intended, you might want to rephrase the question in the text.

Add, to Form1.Button1Click, a call to a new procedure in unit2

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage('Hello');
  SayHelloFromUnit2;  // <---- add this
end;

In unit2 add the following to the interface section:

procedure SayHelloFromUnit2;

and to the implementation section

uses Vcl.Dialogs;

procedure SayHelloFromUnit2;
begin
  ShowMessage('Hello from unit2');
end;
Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54