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;