动态按钮的OnClick事件?

Ray*_*ers 6 delphi events

在开始之前,我必须说明这个主题上没有其他堆栈溢出帖子对我有帮助

我有一个由btnApply调用的动态按钮

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

在全局范围内,声明了frmTable的var

btnApply: TButton;
Procedure btnApplyClick(Sender:TObject);
//other vars
Run Code Online (Sandbox Code Playgroud)

点击下btnSort下

//other code
btnApply:= TButton.create(frmSort);
//all its properties
BtnApply.onclick:= btnApplyClick;
//other code
Run Code Online (Sandbox Code Playgroud)

然后

Procedure btnApplyClick(Sender:TObject);
Begin
  //it's code it has to execute
End;
Run Code Online (Sandbox Code Playgroud)

我在"BtnApply.onclick:= btnApplyClick;"中收到错误消息 方法指针和常规过程之间的不兼容类型行

我该如何工作?

提前致谢

Ken*_*ite 14

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;
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因你不能使它成为一个表单方法(虽然我看不出这是一个可视化控件的情况),你可以使它成为任何对象的方法,如下所示:

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;
Run Code Online (Sandbox Code Playgroud)


Rem*_*eau 8

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

  1. 添加一个额外的显式参数来考虑Self指针:

    procedure btnApplyClick(Self: Pointer; Sender: TObject);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用TMethod记录将过程分配给按钮:

    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;
    
    Run Code Online (Sandbox Code Playgroud)

  • 这是你的意见.有一些有用的例子可以派上用场,比如将自定义上下文信息直接传递给事件处理程序而不必将其存储在其他地方,比如控件的`Tag`属性.使用与否,这是你的选择.在使用控制台应用程序测试事件驱动的代码而不为它们创建UI时,我一直使用这种方法. (3认同)