Setting the OnClick procedure of a Delphi button at runtime

半腔热情 提交于 2019-12-01 13:07:40

问题


I have a program in which I need to update a database table with information entered into edit boxes, with a button at the end to do the updating. However, the form is created at runtime and all the elements including the button are also created in the same way. I figured a way to allow the database arguments would be to define a procedure to update the database such as:

procedure UpdateDatabase(Field1,Field2,Field3:string);
begin
//update database here...
end;

Then assign the OnClick event of my button to this procedure with the parameters pre filled like:

Button1.OnClick := UpdateDatabase(Edit1.text,Edit2.Text,Edit3.Text);

However the types are incompatible as it requires a different data type. I also noticed that parameters can't usually be passed into a OnClick function. Is there actually a way of achieving what I have proposed?

This is my current create button code:

function buttonCreate(onClickEvent: TProcedure; 
  left: integer; top: integer; width: integer; height: integer; 
  anchors: TAnchors; caption: string; parent: TWinControl; form: TForm;): TButton;
var
  theButton: TButton;
begin
  theButton := TButton.Create(form);
  theButton.width := width;
  theButton.height := height;
  theButton.left := left;
  theButton.top := top;
  theButton.parent := parent;
  theButton.anchors := anchors;
  //theButton.OnClick := onClickEvent;
  theButton.Caption := caption;
  result := theButton;
end;

Any and all help appreciated!


回答1:


Event handlers must be declared exactly how the event type is defined. An OnClick event is declared as a TNotifyEvent which takes parameters (Sender: TObject). You cannot break that rule.

In your case, you can wrap your own procedure inside of the event handler, like so...

procedure TForm1.Button1Click(Sender: TObject);
begin
  UpdateDatabase(Edit1.text,Edit2.Text,Edit3.Text);
end;

Note that TNotifyEvent is a procedure "of object", which means your event handler must be declared inside of an object. In your case, the event handler should be declared inside your form (not in a global location).




回答2:


Have you thought about descending a control from TButton with the edit controls as field members?

Here's an example that hopefully you can glean some ideas from.

  TButtonHack = class(TButton)
    fEdit1,
    fEdit2,
    fEdit3: TEdit;
  procedure Click; override;
  public
  constructor Create(AOwner: TComponent; AParent: TWinControl; Edit1, Edit2, Edit3: TEdit); Reintroduce;
end;

Constructor TButtonHack.Create(AOwner: TComponent; AParent: TWinControl;  Edit1, Edit2, Edit3: TEdit);
begin
  inherited Create(AOwner);
  Parent := AParent;
  Left := 100;
  Top := 100;
  Width := 100;
  Height := 20;
  Caption := 'ButtonHack';
  fEdit1 := Edit1;
  fEdit2 := Edit2;
  fEdit3 := Edit3;
end;

procedure TButtonHack.Click;
begin
  Inherited Click;
  Showmessage(fEdit1.text+','+ fEdit2.text+','+fEdit3.text);
end;

To test, drop a button, and three TEdits on a form.

procedure TForm1.Button1Click(Sender: TObject);
var
  ButtonHack: TButtonHack;
begin
  ButtonHack := TButtonHack.Create(Form1, Form1, Edit1, Edit2, Edit3);
end;

Whether you create the edits ahead of time or from within the TButtonHack is up to you. I've simplified it as much as possible just as an example.



来源:https://stackoverflow.com/questions/28265513/setting-the-onclick-procedure-of-a-delphi-button-at-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!