Poweredby.gif (2060 bytes)

Hooking an event handler

This paper shows how you can 'hook'an event handler.
This demoprogramexample uses two forms. (Form1 and Form2). Form1 uses Form2.
Form2 however is not 'linked' to Form1, so we can say that we could use Form2 in all applications we would like.
(Form2 is an independent form)
We want to fill the textbox Edit1on Form1 with the value (of the text property) from Edit2 on Form2 by pressing
the button on Form2.

Here is the problem, because Form2 does not know the existing of Form1, how could it set the Edit1.Text on Form2 property ?

The answer is that we should hook an event on form2 to do the trick.
This event should be of type TNotifyEvent,
an event that should simply notify the component that an event has occurred.
Sounds like magic!
Before we go further let's see what components we have :

This example has two forms :

Well let's take a good look at the source code of the two units :

Unit1 :

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    btnHook: TButton;
    LabelStatus: TLabel;
    procedure btnSetTextClick(Sender: TObject);
    procedure btnHookClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    Procedure SomeThingChanged (Sender : TObject);
  end;

var
  Form1: TForm1;

implementation

uses Unit2; // Form1 uses Form2

{$R *.DFM}

procedure TForm1.btnSetTextClick(Sender: TObject);
begin
  Form2.Edit2.Text := Edit1.Text;
end;

procedure TForm1.SomeThingChanged(Sender: TObject);
begin
  //Read the text from the edit box
  Edit1.Text := Form2.Edit2.Text;
end;

procedure TForm1.btnHookClick(Sender: TObject);
begin
  //The OnSomethingChanged event must me be 'hooked' by 
  //assinging it to the method SomethingChanged (Form1)
  //Otherwise it is nil and is not assigned
  Form2.OnSomeThingChanged := SomeThingChanged;
  LabelStatus.Caption := 'Form1 and Form2 are now hooked !';
end;

end.

Unit 2 :

unit Unit2;

interface

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

type
  TForm2 = class(TForm)
    Edit2: TEdit;
    btnSetText: TButton;
    procedure btnSetTextClick(Sender: TObject);
  private
    { Private declarations }
    FOnSomethingChanged : TNotifyEvent;
  public
    { Public declarations }
    property OnSomethingChanged : TNotifyEvent read FOnSomeThingChanged 
       write FOnSomeThingChanged;
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

procedure TForm2.btnSetTextClick(Sender: TObject);
begin
  //Trigger the event if assigned then execute
  If Assigned(FOnSomeThingChanged) then
    FOnSomeThingChanged(Self) //execute
  else
    showMessage('Sorry forms are not hooked!')  
end;

end.

If the property OnSomethingChanged (the event)  in unit2 is assigned then it will execute anything that it is assigned to.
In this case the assingment is done by clicking on the btnHook button. This button assigns the property OnSomethingChanged to the method

SomethingChanged  on form1, which reads the value of edit2.
Form2 itself is not aware of what he is going on.

Magic ? No just good OOP. Techniques like this can make your programs much more maintaneable because by writing independent
units you can reuse the code as much as you want.

More information :
Related papers Dutch   : arrows.gif (215 bytes)OOP   arrows.gif (215 bytes)VCL
Related papers english : arrows.gif (215 bytes)OOP   arrows.gif (215 bytes)VCL



DownloadDownload here the source of this example