【发布时间】:2010-09-27 18:19:32
【问题描述】:
我在 DLL 中嵌入了一个表单,可以调用 DLL 并显示表单并将 DLL 中的各种函数返回到主应用程序,但是我不知道如何让 DLL 触发主应用程序中的事件形式。
例如,在主应用程序中,我有一个数据集,我想在 DLL 中的表单上有一个按钮来转到数据集中的某个记录,但看不到这是如何完成的。
谁能给我举个例子或给我一些关于如何做到这一点的指示?
【问题讨论】:
我在 DLL 中嵌入了一个表单,可以调用 DLL 并显示表单并将 DLL 中的各种函数返回到主应用程序,但是我不知道如何让 DLL 触发主应用程序中的事件形式。
例如,在主应用程序中,我有一个数据集,我想在 DLL 中的表单上有一个按钮来转到数据集中的某个记录,但看不到这是如何完成的。
谁能给我举个例子或给我一些关于如何做到这一点的指示?
【问题讨论】:
如果 DLL 需要调用宿主应用程序中的行为,则宿主应向 DLL 提供 回调函数,该 DLL 存储并在适当时调用。
您的 DLL 导出一个函数,告诉它显示表单,对吗?向该函数添加几个参数,以便 EXE 提供指向回调函数的指针。回调函数应至少接受一个参数,其类型应为Pointer。调用者(EXE)将使用该参数作为上下文参数,以某种方式提醒它为什么DLL调用EXE的函数。您的 DLL 将存储函数指针和上下文指针,当 DLL 需要告诉 EXE 某些内容时,它将调用该函数并将上下文值传回。 DLL 不会对上下文值做任何事情;它只是存储并逐字传递给 EXE 的东西。
DLL 的界面如下所示:
type
TDllCallback = function(Context: Pointer): DWord; stdcall;
function DisplayForm(Parent: HWnd; Callback: TDllCallback; Context: Pointer): DWord; stdcall; external Dll;
EXE 会这样定义一个回调函数:
function CallbackFunction(Context: Pointer): DWord; stdcall;
begin
TMainForm(Context).DoSomething;
Result := 0;
end;
它会像这样调用 DLL 函数:
procedure TMainForm.DoDllTaskClick(Sender: TObject);
begin
DisplayForm(Handle, CallbackFunction, Pointer(Self));
end;
注意CallbackFunction 的签名如何匹配前面定义的TDllcallback 类型。它们都使用 stdcall 调用约定,并且它们都是独立函数,而不是方法。避免使用方法,因为方法指针是 Delphi 特有的,如果可能的话,您不应该要求您的 DLL 仅由 Delphi 主机使用。
【讨论】:
is 运算符的代码很好,只要您在来自同一模块的对象上使用它。不仅仅是is 不应该跨越模块边界。最终,每个模块都应该被编写成好像没有其他模块知道什么是 Delphi 数据类型——不要共享任何类的对象。假设项目中的其他所有内容都是用 C 编写的。
因为 DLL 的代码在主应用程序的同一地址空间中执行,所以有很多通信方式。
【讨论】: