将消息传递到 DLL 的入口点
我有一个 DLL,它在其入口点执行一些代码,即
procedure MainDLL(Reason: Integer);
begin
{ ... Code here ... }
end;
begin
DLLProc := @MainDLL;
end.
现在,我想从外部应用程序将一些值传递到 DLL 的入口点。我尝试在 DLL 内创建一个隐藏窗口,如下所示:
const
WM_JAJCO = WM_USER + 1024;
type
TWnd = class(TObject)
class procedure DLLWndProc(var Msg: TMessage);
end;
{ ... }
class procedure TWnd.DLLWndProc(var Msg: TMessage);
var
Tmp: DWORD;
begin
if (Msg.Msg = WM_JAJCO) then
begin
PNewHandle := Msg.LParam;
CreateThread(nil, 0, @Starter, nil, 0, Tmp);
Msg.Result := 0;
end else
Msg.Result := DefWindowProc(MyHnd, Msg.Msg, Msg.WParam, Msg.LParam);
end;
// in the entry point
MyHnd := AllocateHWND(TWnd.DLLWndProc);
然后,在调用者应用程序中初始化 DLL 后,我使用:
SendMessage(FindWindow('TPUtilWindow', nil), WM_USER + 1024, 0, wi.WndHandle);
Application.ProcessMessages();
但在 DLL 内创建的窗口似乎没有收到消息。你知道为什么吗?
如果这是一个不好的方法并且您有不同的解决方案,请告诉我。
I have a DLL which exectues some code at its entry point, i.e.
procedure MainDLL(Reason: Integer);
begin
{ ... Code here ... }
end;
begin
DLLProc := @MainDLL;
end.
Now, I would like to pass some values to the DLL's entry point from an external application. I have tried creating a hidden window inside the DLL, like that:
const
WM_JAJCO = WM_USER + 1024;
type
TWnd = class(TObject)
class procedure DLLWndProc(var Msg: TMessage);
end;
{ ... }
class procedure TWnd.DLLWndProc(var Msg: TMessage);
var
Tmp: DWORD;
begin
if (Msg.Msg = WM_JAJCO) then
begin
PNewHandle := Msg.LParam;
CreateThread(nil, 0, @Starter, nil, 0, Tmp);
Msg.Result := 0;
end else
Msg.Result := DefWindowProc(MyHnd, Msg.Msg, Msg.WParam, Msg.LParam);
end;
// in the entry point
MyHnd := AllocateHWND(TWnd.DLLWndProc);
Then, after I initialize the DLL in the caller application, I use:
SendMessage(FindWindow('TPUtilWindow', nil), WM_USER + 1024, 0, wi.WndHandle);
Application.ProcessMessages();
But the window created inside the DLL does not seem to receive the message. Do you happen to know why?
If that's a bad method and you have a different solution, please let me know.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您不应该为此使用 DLLMain。只需导出您自己的 init 函数并手动调用即可。
You shouldn't be using DLLMain for this. Just export your own init function and call it manually.
这是一个比较曲折的做法。您应该在 DllMain 函数中尽可能少地执行操作。规范的解决方案是创建一个专用函数来执行初始化。安排主机应用程序在调用其他任何内容之前调用初始化函数。
您的版本失败的最可能原因是有很多具有该类名称的窗口。 AllocHwnd 创建的每个窗口都有该类名。 FindWindow 可能只是找到了错误的窗口。
另一方面,您在传递注释时提到该 DLL 已被注入!在这种情况下,您可以通过使用唯一的类名或为窗口指定唯一的标题以便您可以找到它来使您的方法正常工作。
最后,对 ProcessMessages 的调用看起来是无偿的。
That's a rather tortuous approach. You are supposed to do as little as possible in the DllMain function. The canonical solution is to create a dedicated function to perform initialization. Arrange for the host app to call the initialization function before calling anything else.
The most likely reason your version fails is that there are a lot of windows with that class name. Every window created by AllocHwnd has that class name. FindWindow probably just finds the wrong one.
On the other hand, you mention in passing in a comment that this DLL is injected! In that case you can make your method work by using a unique class name or giving the window a unique title so that you can find it.
Finally the call to ProcessMessages looks to be gratuitous.
首先确保注入的 DLL 确实创建了您的窗口句柄。 WinSight 或 Spy++ 应该可以帮助您。一旦您知道该窗口确实存在,请确保 FindWindow 找到您的窗口句柄,而不是具有相同类名的另一个窗口句柄。 IIRC,甚至 Delphi IDE 本身也使用这个类名创建窗口句柄。
First make sure that the injected DLL really does create your window handle. WinSight or Spy++ should help you there. Once you know the window really does exist make sure FindWindow find your window handle and not another one with the same class name. IIRC, even the Delphi IDE itself creates window handles using this class name.