Delphi 动态按钮的OnClick事件?

Delphi 动态按钮的OnClick事件?,delphi,events,Delphi,Events,在我开始之前,我必须声明,还没有其他关于这个主题的堆栈溢出帖子对我有所帮助 我有一个动态按钮,叫做Btnaply 它是通过静态表单frmTable上的静态按钮bSensor的单击事件在动态表单frmSort上动态创建的 在全局范围下声明了frmTable的var btnApply: TButton; Procedure btnApplyClick(Sender:TObject); //other vars 在B传感器下单击 //other code btnApply:= TButton.cre

在我开始之前,我必须声明,还没有其他关于这个主题的堆栈溢出帖子对我有所帮助

我有一个动态按钮,叫做Btnaply

它是通过静态表单frmTable上的静态按钮bSensor的单击事件在动态表单frmSort上动态创建的

在全局范围下声明了frmTable的var

btnApply: TButton;
Procedure btnApplyClick(Sender:TObject);
//other vars
在B传感器下单击

//other code
btnApply:= TButton.create(frmSort);
//all its properties
BtnApply.onclick:= btnApplyClick;
//other code
后来

Procedure btnApplyClick(Sender:TObject);
Begin
  //it's code it has to execute
End;
我在“BtnApply.onclick:=btnApplyClick;”处收到一条错误消息 方法指针和常规过程之间的不兼容类型行

我该怎么做


提前感谢

您的
btnApplyClick
需要是对象的方法。由于按钮必须位于表单上才能发挥作用,因此将其作为表单本身的一种方法:

type
  TfrmSort = class(TForm)
    // UI controls listed here
  public
    procedure btnApplyClick(Sender: TObject);
  end;

implementation

procedure TfrmSort.btnApplyClick(Sender: TObject);
begin
  (Sender as TButton).Caption := 'You clicked me';
end;

procedure TfrmSort.FormCreate(Sender: TObject);
var
  Btn: TButton;
begin
  Btn := TButton.Create(Self);
  Btn.Parent := Self;
  Btn.Top := 100;
  Btn.Left := 100;
  Btn.OnClick := btnApplyClick;
end;
如果出于某种原因,您不能将其作为表单方法(尽管我不知道视觉控件的情况如何),您可以将其作为任何对象的方法,如下所示:

implementation

// You must use StdCtrls in order to have the types available if
// it's not already in your uses clause
type
  TDummyButtonClickObj = class
    class procedure ButtonClickHandler(Sender: TObject);
  end;

{ TDummyButtonClickObj }

class procedure TDummyButtonClickObj.ButtonClickHandler(Sender: TObject);
begin
  (Sender as TButton).Caption := 'You clicked me.';
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  with TButton.Create(Self) do
  begin
    Parent := Self;
    Top := 100;
    Left := 100;
    Caption := 'Click here';
    OnClick := TDummyButtonClickObj.ButtonClickHandler;
  end;
end;

正如其他人所说,事件处理程序应该是类的成员。这正是这次活动所期待的。但是,也可以使用非成员过程作为事件处理程序。它只需要几个额外的步骤来设置

  • Self
    指针添加一个额外的显式参数:

    procedure btnApplyClick(Self: Pointer; Sender: TObject);
    
  • 使用
    t方法
    记录将程序分配给按钮:

    var
      btnApply: TButton;
      M: TMethod;
      //other vars
    
    Procedure btnApplyClick(Self: Pointer; Sender: TObject);
    
    ...
    
    btnApply := TButton.create(frmSort);
    //all its properties
    M.Code := @btnApplyClick;
    M.Data := nil; // can be anything you want passed to the Self parameter
    BtnApply.onclick := TNotifyEvent(M);
    //other code
    
    ...
    
    procedure btnApplyClick(Self: Pointer; Sender: TObject);
    Begin
      // code to execute
    End;
    

  • 我明白您的第一点,但不幸的是,我的frmSort并没有像frmTable那样声明为类型,而是声明为frmSort:TForm以及var中的btnappy:TButton。我是一个没有经验的程序员,所以我也不知道类。我可以绕过类型frmSort=class(TForm)吗?或者这是唯一一种使用非成员过程作为事件处理程序的方法。它只需要几个额外的步骤来设置。添加一个额外的显式参数来解释
    Self
    指针:
    过程btnApplyClick(Self:pointer;Sender:TObject)
    然后使用
    TMethod
    记录将程序分配给按钮:
    var M:TMethod;M.代码:=@btnApplyClick;M.数据:=零;BtnApply.onclick:=TNotifyEvent(M)肯的答案有效,但我也会试试这个。谢谢,我根本不推荐这个。如果您需要在没有实例的情况下执行此操作,则最好使用类方法来避免此类欺骗。这是您的观点。在一些有用的情况下,这会很方便,比如将自定义上下文信息直接传递到事件处理程序中,而不必将其存储在其他位置,比如控件的
    标记
    属性中。使用与否,这是你的选择。在使用控制台应用程序测试事件驱动代码时,我一直使用这种方法,而不为它们创建UI。