Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3532
  • Last Modified:

How to assign a procedure to a TButton.OnClick event


I know that if I declare a method to a form, like:
    procedure ButtonCancelClick(Sender: TObject);

I can assign that to the button:
  btnCancel.OnClick := ButtonCancelClick;

But in this case, I don't have a form previously created.  I mean, I created a Form at run time, and I'm adding some buttons and I want to add some events to the clicks of the buttons.
So, without the procedure being in a form, I get the error:

Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'

0
fischermx
Asked:
fischermx
  • 3
  • 3
  • 2
  • +4
2 Solutions
 
gazzzzzzerCommented:
Make sure that the ButtonCancelClick procedure has the correct signature.

procedure TForm1.SomeOtherProcedure()
begin
    btnCancel.OnClick := ButtonCancelClick;
end;


procedure TForm1.ButtonCancelClick(Sender : TObject);
begin
  
end;

Open in new window

0
 
fischermxAuthor Commented:
gazzzzer:

I don't have "TForm1".

So I can't write it as :
procedure TForm1.ButtonCancelClick(Sender : TObject);

Mine is plain:
procedure ButtonCancelClick(Sender : TObject);
0
 
ThommyCommented:
Perhaps this might help you...

Delphi: How to assign dynamically an event handler without overwriting the existing event handler?
http://stackoverflow.com/questions/4501623/delphi-how-to-assign-dynamically-an-event-handler-without-overwriting-the-existi
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
Ephraim WangoyaCommented:
Very interesting question. You can create a class to hold the procedures you will be assigning to your button click.

Something of this kind

 
type
  TCustomProcedures = class(TObject)
  public
    class procedure Test1(Sender: TObject);
    class procedure Test2(Sender: TObject);
  end;

class procedure TCustomProcedures.Test1(Sender: TObject);
begin
  ShowMessage('Test 1');
end;

class procedure TCustomProcedures.Test2(Sender: TObject);
begin
  ShowMessage('Test 2');
end;

Open in new window


In your code you can assign the procedure the usual way

 
Button1.OnClick := TCustomProcedures.Test1;
  Button2.OnClick := TCustomProcedures.Test2;

Open in new window

0
 
jimyXCommented:
I have created a demo for how to create form with button and assign an event for the button OnClick:
demo.zip
0
 
systanCommented:
Here;
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    CheckBox1: TCheckBox;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage('Button test');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
[b]Button1.OnClick := Button1Click;
CheckBox1.OnClick := CheckBox1Click;[/b]
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
showmessage('CheckBox test');
end;

end.

Open in new window

0
 
systanCommented:
0
 
Geert GruwezOracle dbaCommented:
you need to show your code for creating the form on the fly
to attach a event you need to create a procedure "of object"

you can attach an event use the form from which create the dynamic form:
 
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure OnClickbtnTest1(Sender: TObject);
    procedure OnClickbtnTest2(Sender: TObject);

  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var frm: TForm;
  b: TButton;
begin
  frm := TForm.Create(Self);
  try
    frm.Caption := 'Test click';
    b := TButton.Create(frm);
    b.Parent := frm;
    b.Caption := 'Test1';
    b.Name := 'btnTest1';
    b.Left := 100;
    b.Top := 20;
    b.OnClick := OnClickbtnTest1;
    b := TButton.Create(frm);
    b.Parent := frm;
    b.Caption := 'Test2';
    b.Name := 'btnTest2';
    b.Left := 200;
    b.Top := 20;
    b.OnClick := OnClickbtnTest2;
    frm.ShowModal;
  finally
    frm.Free;
  end;
end;

procedure TForm1.OnClickbtnTest1(Sender: TObject);
begin
  ShowMessage(TButton(Sender).Name + ' Clicked in form with caption "' + TForm(TButton(Sender).Owner).Caption + '"');
end;

procedure TForm1.OnClickbtnTest2(Sender: TObject);
begin
  ShowMessage(TButton(Sender).Name + ' Clicked in form with caption "' + TForm(TButton(Sender).Owner).Caption + '"');
end;


end.

Open in new window

0
 
Geert GruwezOracle dbaCommented:
>jimyX , in your sample in 35562990
you are nesting 1 form reference in the other
this is not a good practice ...  

>fischermx
you can not attach a non-object procedure to an event:
this is a non-object procedure:

procedure Button1Click;
begin
end;

this is a "of object" procedure (also known as a method)
procedure TClass.Button1Click;
begin
end;

you need to create a class (and instance for your procedure)
> so you can do this:

 
procedure NormalProcButton1Click;
begin
end;

// this is a "of object" procedure (also known as a method)
procedure TMyClass.MethodProcButton1Click;
begin
  NormalProcButtonClick;
end;


procedure TForm1.CreateSubForm;
var frm: TForm;
  b: TButton;
begin
  MyClass := TMyClass.Create;
  try
    frm := TForm.Create(Self);
    try
      frm.Caption := 'Test click';
      b := TButton.Create(frm);
      b.Parent := frm;
      b.Caption := 'Test1';
      b.Name := 'btnTest1';
      b.Left := 100;
      b.Top := 20;
      b.OnClick := MyClass.MethodProcButton1Click;

      // etc

    finally
      frm.Free;
    end;
  finally
    MyClass.Free;
  end;
end;

Open in new window

0
 
Geert GruwezOracle dbaCommented:
if you are creating your own component
then override the Click method instead
(or the DoShow or the DoCreate or ...) (look for dynamic in the delphi source codes)
and then call the inherited (or first call inherited) depends on behaviour you want

This will leave the event empty for other people to use in the form designer

assume you want do something (like add a 'A' in the caption)

type
  TMyButton = class(TButton)
  public
    procedure Click; override;
  end;

procedure TMyButton.Click;
begin
  Self.Caption := 'A' + Self.Caption;
  inherited Click;
end;

0
 
fischermxAuthor Commented:
I wasn't creating a custom button.

It was a creating a form on the fly with buttons on the fly with events on the fly.

The solution I used was from Ewangoya.



0
 
fischermxAuthor Commented:
Thank you!
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 3
  • 3
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now