onclick是TNotifyEvent类型; type TNotifyEvent = procedure(Sender: TObject) of object; 就是说他是一个过程,而且是有一个TObject的参数,并且包含在一个对象里~~ 关于类的方法: (不是类方法,这里指object pascal中的静态方法,相当于C++的成员函数) 1: 带有隐含参数 self 2: 方法是方法,数据是数据。 3:Delphi的方法是一个结构 type TMethod = record Code: Pointer; //方法的入口地址 Data: Pointer; //类实例指针(Self参数) end; 我们调用类的方法,其实分为2个部分, 1:调用方法的代码,通过类来获得方法入口地址。 2:访问对象的数据(也可能不访问),通过类的方法的那个隐含参数Self来访问。 我做了一个测试: TMyObject = class private FName: string; public procedure ChangeName(AName: string); procedure ShowPrivate; end; procedure TMyObject.ChangeName(AName: string); begin FName := AName; //修改私有变量 ShowMessage('My name is to be changed to ' + AName); end; procedure TMyObject.ShowPrivate; begin ShowMessage('My name is ' + FName); end; procedure TForm1.Button1Click(Sender: TObject); type TCallFun = procedure(AName: string) of object; var E: TMyObject; M: TMethod; begin E := TMyObject.Create; M.Code := @TMyObject.ChangeName; //这里设置要访问的方法的入口地址 M.Data := @Pointer(E)^; //设置Self参数,即类实例指针 @Pointer(E)^与Pointer(E)一样的 TCallFun(M)('Xbl'); E.ShowPrivate; //My name is Xbl E.Free; end;
delphi里的普通函数指针pointer 为4个字节,但是对象的方法指针是8个字节,由对象指针self(4字节)和函数指针(4字节)组合而成. 将普通的函数指针变成对象的方法指针就不是难事了. 下面是简单的例子代码. procedure Button2Click(Sender: TObject); //这里是一个普通的函数 implementation {$R *.DFM} procedure Button2Click(Sender: TObject); begin ShowMessage('1'); end; procedure TForm1.Button1Click(Sender: TObject); var Method: TMethod; begin Method.Code := @Button2Click; //取得Button2Click函数指针 Method.Data := nil; //也可以是self Button2.OnClick := TNotifyEvent(Method); end;
How to execute a method (procedure/function) by name Category: Pascal Here's a simple trick to execute a Delphi object's method by name: ~~~~~~~~~~~~~~~~~~~~~~~~~ type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject) ; procedure CallMeByName(Sender: TObject) ; private procedure ExecMethod(OnObject: TObject; MethodName: string) ; end; var Form1: TForm1; type TExec = procedure of object; procedure TForm1.ExecMethod(OnObject: TObject; MethodName: string) ; var Routine: TMethod; Exec: TExec; begin Routine.Data := Pointer(OnObject) ; Routine.Code := OnObject.MethodAddress(MethodName) ; if NOT Assigned(Routine.Code) then Exit; Exec := TExec(Routine) ; Exec; end; procedure TForm1.CallMeByName(Sender: TObject) ; begin ShowMessage('Hello Delphi!') ; end; procedure TForm1.Button1Click(Sender: TObject) ; begin ExecMethod(Form1, 'CallMeByName') ; end;