将消息传递到DLL的入口点

时间:2011-10-12 22:31:28

标签: delphi dll delphi-xe

我有一个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中创建的窗口似乎没有收到消息。你碰巧知道为什么吗?

如果这是一种不好的方法而你有不同的解决方案,请告诉我。

3 个答案:

答案 0 :(得分:2)

这是一种相当曲折的方法。你应该在DllMain函数中尽可能少地做。规范的解决方案是创建一个专用函数来执行初始化。安排主机应用程序在调用其他任何内容之前调用初始化函数。

您的版本失败的最可能原因是有很多具有该类名称的窗口。 AllocHwnd创建的每个窗口都有该类名。 FindWindow可能只是找错了。


另一方面,你在评论中提到注入了这个DLL!在这种情况下,您可以通过使用唯一的类名或使窗口具有唯一的标题来使您的方法工作,以便您可以找到它。

最后,对ProcessMessages的调用看起来是无偿的。

答案 1 :(得分:2)

你不应该为此使用DLLMain。只需导出您自己的init函数并手动调用它。

答案 2 :(得分:1)

首先确保注入的DLL确实创建了窗口句柄。 WinSight或Spy ++应该可以帮到你。一旦你知道窗口确实存在,请确保FindWindow找到你的窗口句柄,而不是另一个具有相同类名的窗口句柄。 IIRC,甚至Delphi IDE本身都使用这个类名创建窗口句柄。