组件代码中可以使用回调函数吗?(100分)

  • 主题发起人 主题发起人 pidi
  • 开始时间 开始时间
P

pidi

Unregistered / Unconfirmed
GUEST, unregistred user!
组件代码中可以使用回调函数吗?若可以,应该注意些什么?
我原来的回调函数代码不在组件中,程序正常,可是用组件封装后,调试时,显示回调函数的参数不可访问,不知何故?
[:(][:(][:(][red][/red]
 
能不能把代码贴出来?
我只在DLL中用过回调
 
给个邮箱可以么
我的qq 26136463
 

"在调函数是这样一种函数,它们不是由应用程序或DLL本身调用的,而是由Windows调用的,
有些Windows的API也需要传递一个回调函数,实际上api是从系统Dll中输出的例程,从本质
上讲,当我们把一个函数的地址传递给Api时,实际上是把这个函数传递给DLL"
 
是由win32 DLL或其他.dll调用。我现在是将回调函数的实现在组件代码中实现出现问题
 
很遗憾,这个问题我一直没解决:现在我贴出部分代码,请各位帮我分析一下
PFTStatus = ^TFTStatus;
TFTStatus = record
code: DWORD;
param1: DWORD;
param2: DWORD;
end;

type
TAp = function(pStatus: PFTSTATUS):integer of object; cdecl;
var
p: TAp;
begin
p :=self.getRegisterAction;
move(p,g_FtUILink.getAction, sizeof(TAp));//g_FtUILink是调用回调函数的函数的参数,是一个结构数组,getaction(回调函数是其中的一个)。
rc := FT_setupUIlink(g_FtContext, g_FtUILink);//是用来调用回调函数getRegisterAction的(结构还包括其他的一些回调函数)。
。。。
end;//以上rc的返回均正确。

下面是回调函数项
function TFPSensorXPD.getRegisterAction(pStatus:PFTSTATUS):integer;cdecl;
begin
if pStatus=nil then exit;
if g_bIsTimeToDie then begin //If program wants to exit, then indicate that to toolkit
Result := FT_ID_CANCEL;
exit;
end;
case pStatus^.code of//当程序访问到此处时,出现访问冲突,另外光标处显示pStatus^.code不可访问
FT_READY_TO_FILL_BUF:
。。。。 ;

end;

上面程序在没封装之前均调用正确。
 
能不能把cdecl换成stdcall呀;
 
这个我已经试过了,还是不行
 
TAp = function(pStatus: PFTSTATUS):integer[red] of object[/red]; cdecl;

如果是供DLL或者Win调用, 那么你不能这样声明, 这样声明后, 它隐含传入一个
类的实例参数(Self), 当调用者无法传入这个参数时, 除非你根本没有用到任何
与实例相关的属性和方法, 否则调用一定会失败.

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure Hello(const Msg: String);

public
{ Public declarations }
end;

THelloCallback = procedure(const Msg: String) of object;

THello = class(TObject)
private
FCallback : THelloCallback;
public
procedure Hello(const Msg: String);

property HelloCallback : THellocallback write FCallback;
end;

procedure HelloProc(dummy: Integer; const Msg: String);

var
Form1: TForm1;

implementation

{$R *.dfm}
procedure HelloProc(dummy: Integer; const Msg: String);
begin
ShowMessage(Msg);
end;

procedure THello.Hello(const Msg: String);
begin
if Assigned(FCallback) then FCallBack(Msg);
end;

procedure TForm1.Hello(const Msg: String);
begin
ShowMessage('Hello, world');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
H : THello;
M : TMethod;
begin
H := THello.Create;
try
H.HelloCallback := Hello;
H.Hello('hahaha');

M.Code := @HelloProc;
M.Data := nil;
H.HelloCallBack := THelloCallback(M);
H.Hello('hahaha');
finally
H.Free;
end;
end;

end.
 
但是调用的函数(是动态连接库中的函数)规定了此回调函数的形式呀
 
谢谢,我再仔细看看你的例程
 
tseug还是不行,我不太清楚你说的
”除非你根本没有用到任何
与实例相关的属性和方法, 否则调用一定会失败“在我问题中的意思,请再指点一二
我的qq 26136463
 
这段话你先不用管它, 其实我的例子是想说明下面的问题:
1 你的TAP类型是一个方法, 所以你的P指针, 指向的是TMethod结构, 真正的
函数入口在TMethod(P).Code中, TMethod(P).Data保存的是类的实例.
2 如果你想像调用普通过程(函数)那样调用方法,必须保证这个方法中不涉及
任何和实例有关的东西,而且,必须传递个虚假的参数(Self). 参考例子中的
procedure HelloProc(dummy: Integer; const Msg: String);
这里的dummy, 就是为平衡参数栈用的,具体的值无所谓。

参考下面的,在一个外部的过程中调用一个方法,没有用到任何类的实例

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure HelloMethod(const Msg: String);

public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure Hello(HelloMethod: TMethod);
var
P : procedure(dummy: integer; const Msg: String);
begin
P := TMethod(HelloMethod).Code;
P(0, 'Hello, world!');
end;

procedure TForm1.HelloMethod(const Msg: String);
begin
ShowMessage(Msg);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
P : procedure(const Msg: String) of object;
begin
P := HelloMethod;
Hello(TMethod(P));
end;

end.


 
谢谢tseug. 你的确切中了要害。现在编译已通过,只是又出现新的问题,我不知是不是因为上述的改动而引起。
function getRegisterAction(pStatus:PFTSTATUS):integer;cdecl;
begin
case pStatus^.code of
FT_READY_TO_FILL_BUF:
PostMessage(g_hwnd, WM_URU_NOTIFY, MESSAGE_READY_TO_FILL_BUF,0);
FT_BUF_FILLED:
PostMessage(g_hwnd, WM_URU_NOTIFY,MESSAGE_IMAGE_RECEIVED, 0);
。。。。。
end;//g_hwnd我声明成HWND或者application.handle,消息函数还是收不到消息
此回调函数包含了消息传递过程postmessage,执行时也没出现异常,但是消息处理(接收)函数就是收不到消息。
const
WM_URU_NOTIFY=WM_USER+302;
MESSAGE_READY_TO_FILL_BUF=10;
MESSAGE_IMAGE_RECEIVED=11;
...
//消息处理函数
procedure TFPSensorXPD.WMURU(var Message: TMessage);
begin
case message.WParam of
MESSAGE_READY_TO_FILL_BUF:
showmessage('message ready to fill buf');
MESSAGE_IMAGE_RECEIVED:
showmessage('message image receivek');
....
end;
本来是很简单的代码,到了组件中就问题多多了,还望指点

 
有没有跟踪一下, 看看红字的地方是否执行了?

case pStatus^.code of
FT_READY_TO_FILL_BUF:
[red] PostMessage(g_hwnd, WM_URU_NOTIFY, MESSAGE_READY_TO_FILL_BUF,0); [/red]
FT_BUF_FILLED:
[red] PostMessage(g_hwnd, WM_URU_NOTIFY,MESSAGE_IMAGE_RECEIVED, 0);[/red]
 
非常感谢各位,如tseug所说
要在组件创建时加
FWindowHandle := AllocateHWnd(WndProc);
 
后退
顶部