高档礼品包装盒:绝对没有办法把普通的procedure赋给一个类实例的事件指针吗

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 17:26:43
绝对没有办法把普通的procedure赋给一个类实例的事件指针吗 比如,我一个普通的全局过程Gproc。
想给一个动态创建的按钮赋onclick,
我非常想类似这样
onclick:=Gproc;
可是当然不行,因为类型不同,它们各自的空间大小也不同,普通的proc没有类指针。不能
给Tnotifyevent类型赋值。我知道一个类方法可以做到。但我现在的目的想让它执行Gproc
的代码,在不另创建任何类实例的情况下,如何调用呢。


直接像你上面这样onclick := Gproc;肯定不行,原因如你所说!
但对于onclick这种过程指针类型,就我所知好像只能赋于同它兼容的过程指针类型,而如
你所述很想直接利用Gproc这个普通全局过程,所以,只好这样做了:
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure MyOnClick(Sender : TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure Gproc;
begin
  //你的代码
end;

{ TForm1 }

procedure TForm1.MyOnClick(Sender: TObject);
begin
  Gproc;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Button2.OnClick := MyOnClick;
end;
[8D]我只能想到这一层,期盼更好的解决方案!

可以,只要他们穿入的参数类型一样就可以了,


1.Forms单元中有一个MakeObjectInstance过程,通过一个巧妙的方法在普通过程与类方法
之间转换,你可参考看看。
2.使用class procedure,不需要创建类实例:
type
  TMyClass = class
    class procedure Gproc(Sender: Object);
  end;
然后可以赋值 Button1.OnClick := TMyClass.Gproc;

3.通过分析Classes单元,一番摸索终于找到一个方法,使用RTTI来解决:
implementation

uses
  TypInfo;

// 类方法隐藏了第一个参数为对象的 Self (放在EAX中传递)
// 故第一个参数为 Self: TObject
// 第二个参数对应 TNotifyEvent 的参数
procedure Gproc(Self: TObject; Sender: TObject);
begin
  ShowMessage('Test');
end;

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  M: TMethod;  // 方法记录
begin
  M.Code := @Gproc; // 指向方法(这里是全局过程)地址
  M.Data := nil; // 指向类实例(该值对应着 Gproc 调用时的 Self 参数值,可为任意值,这里传nil)
  SetMethodProp(Button1, 'OnClick', M); // 调用 RTTI 过程,动态设置事件
end;

试试看:)


补充,也可不用 SetMothodProp ,直接用
  Button1.OnClick := TNotifyEvent(M);
来代替,这样uses TypInfo;也可以省了。

这是一个有价值的讨论,现在dfw这样的好问题不多了,收藏。

收藏

真行

没有必要这么麻烦把,只要参数的类型一致,就可以进行普通的procedure赋给一个类实例的事件指针

请张兄具体给出一个例子,好让大家学习一下!

TO Archerfl:
我写了一个界面类似QQ的控件,就是用的和你一样的办法,只要procedure参数一样,
就可以进行事件赋值。

答案基本差不多了,如果你想深入的话,我先说个大概:
创建动态控件的winproc,当收到click之类的消息时,执行你那个全局过程;

原理就是自己处理消息循环而已

张无忌说的没错,
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TDoIt=procedure(arg1:integer;arg2:string);
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    FDoIt: TDoIt;
  public
    procedure DoIt;
    property OnDoIt:TDoIt read FDoIt write FDoIt;
  end;
  procedure doIt1(arg1:integer;arg2:string);
var
  Form1: TForm1;

implementation

procedure doIt1(arg1:integer;arg2:string);
begin
  ShowMessage(inttostr(arg1)+arg2);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
form1.OnDoIt:=@doit1;
end;

procedure TForm1.DoIt;
begin
if Assigned(FDoIt) then
   FDoIt(1,'hello');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
DoIt;
end;

end.


》》1.Forms单元中有一个MakeObjectInstance过程,通过一个巧妙的方法在普通过程与类方法之间转换

我只用过MakeObjectInstance把类的方法(不是类方法)转化成普通过程,没有做过相反的过程,
yygw:请举个例子好吗? 另外你用RTTI来解决给了我很大的启发,