窗体上一个按钮,在onclick事件里面写了代码,
然后我用GetMethodProp把onclick事件的方法地址保存起来,再用SetMethodProp将按钮的事件替换成我的方法 NewClick,然后我再NewClick内部调用我原先保存的原来的OnClick,但是在执行原来的OnClick的时候,发生了内存错误,似乎是本应有的一个self值变成了nil,有没有办法通过汇编,在调用原来的onclck之前将self值设置好不知道有谁处理过类似问题,指点一下?
然后我用GetMethodProp把onclick事件的方法地址保存起来,再用SetMethodProp将按钮的事件替换成我的方法 NewClick,然后我再NewClick内部调用我原先保存的原来的OnClick,但是在执行原来的OnClick的时候,发生了内存错误,似乎是本应有的一个self值变成了nil,有没有办法通过汇编,在调用原来的onclck之前将self值设置好不知道有谁处理过类似问题,指点一下?
没太看懂
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, TypInfo;type
TForm1 = class(TForm)
btn1: TButton;
btn2: TButton;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
private public end;var
Form1: TForm1;
oldMethod: TMethod;implementation{$R *.dfm}procedure NewClick;
begin
ShowMessage('NewClick()');
asm
pushad
mov edx, oldMethod.Data
call oldMethod.Code
popad
end;
end;procedure TForm1.btn1Click(Sender: TObject);
begin
ShowMessage('btn1Click()');
ShowMessage(Sender.ClassName);
end;procedure TForm1.btn2Click(Sender: TObject);
var
newMethod: TMethod;
begin
oldMethod := GetMethodProp(Btn1, 'OnClick');
oldMethod.Data := btn1; // Sender
newMethod.Code := @NewClick;
SetMethodProp(btn1, 'OnClick', newMethod);
end;end.
GetMethodProp 之后,TMethod.Data 和 TMethod.Code 都被传入一个相同的值,是什么?
当前对象的实例
procedure TForm1.btn2Click(Sender: TObject);
var
newMethod: TMethod;
begin
oldMethod := GetMethodProp(Btn1, 'OnClick');
ShowMessage(TObject(oldMethod.Data).ClassName); // TForm1
//oldMethod.Data := btn1; // Sender
newMethod.Code := @NewClick;
SetMethodProp(btn1, 'OnClick', newMethod);
end;
也就是Selfprocedure TForm1.btn2Click(Sender: TObject);
var
newMethod: TMethod;
begin
oldMethod := GetMethodProp(Btn1, 'OnClick');
if oldMethod.Data = Self then
ShowMessage('额,原来是窗体本身');
//oldMethod.Data := btn1; // Sender
newMethod.Code := @NewClick;
SetMethodProp(btn1, 'OnClick', newMethod);
end;
那几行汇编编译不过去:
call FOldMthod.Code
[dcc32 Error] Unit1.pas(51): E2116 Invalid combination of opcode and operands
asm
pushad
mov edx, oldMethod.Data
mov ebx, oldMethod.Code
call ebx
popad
end;