settimer(handle,0,8000,@TForm1.Test);TForm1.Test;
begin
showmessage('ok');
Button1.capition:='OK';
end;现在问题是,showmessage是没问题的,但是下一句没什么效果,解决后立即给分。
begin
showmessage('ok');
Button1.capition:='OK';
end;现在问题是,showmessage是没问题的,但是下一句没什么效果,解决后立即给分。
begin
showmessage('ok');
Form1.Button1.caption:='OK';
end;procedure TForm1.Button1Click(Sender: TObject);
begin
settimer(handle,0,8000,@Test);
end;
而Delphi默认的register方式,前三个参数通过EAX、EDX、ECX传递,其余参数通过栈传递。可能正是因为它是回调函数的原因吧!
其次,调用类方法(Procedure of Object),不是直接Call函数的地址,还需要将对象的指针压栈,由于本例当中Test被当成一个过程,而不是一个类方法来调用,从而并没有把对象的self(C++当中称为this)指针压栈,自然只调用了一个全局过程ShowMessage,而Button1.Caption := 'Ok',这个Button1,并不被指针到任何类对象当中,更不可能是Form1当中的实例。
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime // current system time
);
//如果不用stdcall压栈方式,前三个参数(通过寄存器传递)将丢失,丢失后的后果,僵哥已讲了
VOID CALLBACK TimerProc(HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
);
CALLBACK在VC中定义为__stdcall
这是回调函数的原型,你们用个无参数(一个有Self指针的)的就搞定了,确实太强大了
http://rabbitfox.blog.sohu.com/47419399.html不过要说明:因为没有接受过正统的学校教育,有可能我说来说去的一大通,仅仅是验证了我没看过的教科书上的某一句话而已。请千万别笑话。
回调函数的话由系统调用,则是采用Stdcall的方式。
如同三楼所说!不要使用类方法作为回调函数。如果一定要按照你的方法来写这个Test过程的话,那么有一点需要注意的就是
Delphi的类方法TMethod的构造为
TMethod = record
Code, Data: Pointer;
end;
在Delphi的对象中,所有的方法的Data域都是Self
当你写
TForm1.Test;
begin
showmessage('ok');
Button1.capition:='OK';
end;
该方法本身则隐含着一个Self的参数指针指向类本身,所以我们直接写
Button1.Caption := 'Ok';这样的语句可以很正常的使用,其实他也就是通过传递的隐含Self指针定位了
Button1对象了,也就是 Self.Button1.Caption := 'OK';所以可以在该类中使用。而你的SetTimer的回调函数也是该类方法 Test
由于回调函数由系统产生触发!其本身并不存在着Delphi所特有的TMethod这样的对象方法类型
所以当回调触发该函数的时候,进入到
Test过程,由于此时由系统触发,所以Test中并不会存在一个隐含的指针 self对象来指向类本身
从而 在这里你要直接通过Self来引用类中的其他成员都不能做到。
想想,其实也就是一个关于类地址而已
所以将Self指针明确的换成 form1则可解决拉。代码如下:
TForm1.Test;
begin
showmessage('ok');
Form1.Button1.capition:='OK';//需要明确出类地址位置
end;
http://www.samool.com/delphibbs/298/2985209.htm
VOID CALLBACK TimerProc(HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
);
API回调时
push dwTime;
push idEvent;
push uMsg;
push hwnd;
call Test;
{
push ebp; 保护现场原先的EBP指针
mov ebp, esp ; 设置新的EBP指针,指向栈顶
//mov eax, [ebp+0C] ; 调用参数uMsg//没有使用
//...
//mov eax, [ebp+08] ; 调用参数hwnd//没有使用
//...
mov eax, (ptr)[@'ok'];
call showmessage;
pop ebp; 恢复现场的ebp指针
//现在的形式
ret; 返回
//正确的应该是这样的吧
ret 16 ; 返回(相当于ret; add esp,16)//四个参数弹栈
}
我对汇编不是太清楚,不知道理解对不对,如果是这样的,那堆栈不就被破坏了么?
那个系统子程序(调用方)是如何对回调函数Test(被调方)进行参数传递的?这个....我还没有深入到这一步。大家共同研究下去!(握手)很明确,你要表达的是:调用方负责参数传递,被调方也确实收到了参数;但无论几个参数,被调方总是要根据压栈情况进行出栈处理吧?很清楚这是你的意思。但由于我不知前面讲的那个系统子程序是如何做的,所以....^_^继续努力!