来自C++。Delphi窗体应用程序的dll < >我在Delphi 7和C++上编写了Windows窗体应用程序,使用MFC .d/p>编写的DLL。

来自C++。Delphi窗体应用程序的dll < >我在Delphi 7和C++上编写了Windows窗体应用程序,使用MFC .d/p>编写的DLL。,c++,delphi,dll,postmessage,C++,Delphi,Dll,Postmessage,目前,我正试图实现从.dll到主可执行文件的基本消息发布,以在progressbar上显示用户的计算过程,但遇到了几个问题 让我先描述一下我的方法。我在我的Delphi应用程序中注册简单消息,如: WM_MSG := RegisterWindowMessage('WM_MSG'); 并在库部件上执行相同的操作: UINT nMsgID = RegisterWindowMessage(_T("WM_MSG")); 这没问题:调试时,我可以在两侧看到相同的值 我的库函数如下所示(只是一个测试进度

目前,我正试图实现从.dll到主可执行文件的基本消息发布,以在progressbar上显示用户的计算过程,但遇到了几个问题

让我先描述一下我的方法。我在我的Delphi应用程序中注册简单消息,如:

WM_MSG := RegisterWindowMessage('WM_MSG');
并在库部件上执行相同的操作:

UINT nMsgID = RegisterWindowMessage(_T("WM_MSG"));
这没问题:调试时,我可以在两侧看到相同的值

我的库函数如下所示(只是一个测试进度条的虚拟示例):

来自可执行文件的C++函数调用:

procedure TMyFunctionDLL.Execute;
var
  i: Integer;
  tHWND: HWND;
begin
  tHWND := FindWindow(nil, 'mainF');
  i := Func;
end;
第一个问题是tHWNDhWnd变量值有莫名其妙的不同。经过一些研究,我发现了三种情况: 1.负或正巨大hWnd 2.零hWnd 3.未定义(“???”)

在所有情况下,变量hWnd都被标记为未使用,我不知道这意味着什么。最有趣的是,如果我用非常简单的Delphi形式(只使用一个单元)测试代码,它确实可以工作。这个简单的Delphi表单与我的实际C++数据代码工作得很好,其中实际数据是计算出来的。但是当我使用我的Delphi一般应用程序(很多单元,但仍然是一种形式)时,似乎消息事件的主要应用程序没有从C++ DLL中捕获任何事件。 因此,有两个问题: 1.为什么hWnd值总是不同的,为什么它们是“未使用的”? 2.如何强制我的主应用程序使用progressbar正常工作


我一直在用不同的方法来解决这个问题。如C++的“强”>应用程序。句柄或<强> Fr.1。他们中的任何一个都不起作用,甚至在传递过程中都没有提到参数值的变化(我想这应该是另外一个问题)。我也尝试过使用::FindWindow()::PostMessage()而不是FindWindow()PostMessage()(它们之间有什么区别?),这也没有帮助。我已经一整天都在努力改善现状,但不知道如何解决。请帮助我了解任何想法。

如果对FindWindow的相同调用返回不同的窗口,则必须有多个名为Form1的窗口。尝试为这些不同的窗口指定不同的名称,以便能够唯一地标识它们

未使用的问题有点不清楚。也许您的意思是编译器已经注意到分配给tHWND的值从未使用过,因此是毫无意义的


我最后要说的是,这个问题不精确,这可能是你问题的一部分。例如,您说所有变量都未使用,但我们不清楚您的意思。如果您更精确、更有条理,调试就会更成功。

如果对FindWindow的相同调用返回不同的窗口,则必须有多个名为Form1的窗口。尝试为这些不同的窗口指定不同的名称,以便能够唯一地标识它们

未使用的问题有点不清楚。也许您的意思是编译器已经注意到分配给tHWND的值从未使用过,因此是毫无意义的


我最后要说的是,这个问题不精确,这可能是你问题的一部分。例如,您说所有变量都未使用,但我们不清楚您的意思。如果您更精确、更有条理,调试就会更成功。

来自
FindWindow
的结果可以是零或非零。句柄值不在数字行上。它们只是不同的值,所以对它们应用不等式运算符是没有意义的。换句话说,句柄值可能看起来是负数,所以不要假设有效句柄总是大于零

如果窗口句柄的值不匹配,那么难怪其他任何东西都不起作用。您无法调试消息的功能,因为您甚至不确定是否将消息发送到了正确的窗口。首先集中精力解决这个问题

只能在万不得已的情况下使用
FindWindow
。当有多个窗口符合您的搜索条件时,它没有提供检测功能。它总是只返回一个结果。尽可能避免搜索。相反,确切地告诉发件人要将消息发送到哪个窗口。你说你试过了,但失败了,但我敦促你继续沿着这条路走下去。您遇到的问题可能是呼叫约定不匹配。确保DLL和主机应用程序都使用stdcall


一旦确定要将消息发送到正确的窗口,您就可以担心为什么消息不能正确操作进度条。我至少可以看到两个原因:

  • 当DLL函数运行时,称为DLL的主程序不运行。它正在等待DLL代码返回。这意味着您的主程序没有处理任何消息。DLL正在发布一堆消息,但它们尚未得到处理。在程序返回其消息循环之前,它们不会得到处理

  • Windows消息队列的默认大小为10000。您向队列中发送的消息数量是原来的10倍,并且在停止之前没有处理任何消息,因此,即使在您开始之前队列完全为空(这是不可能的,因为您可能通过键盘或鼠标输入触发此功能),您也只能收到十分之一的消息。当队列已满时,
    PostMessage
    将丢弃该消息。由于您随消息发送的值是一个介于0和100之间的整数,因此当其中只有101个包含有意义的信息时,发送100000个消息是毫无意义的


  • 来自
    FindWindow
    的结果可以是零或非零。句柄值不位于
    procedure TForm1.OnMessageEvent(var Msg: tagMSG; var Handled: Boolean);
    begin
      Handled := True;
      if Msg.message = WM_MSG then
        ProgressBar1.Position := Msg.wParam
      else Handled := False;
    end;
    
    procedure TMyFunctionDLL.Execute;
    var
      i: Integer;
      tHWND: HWND;
    begin
      tHWND := FindWindow(nil, 'mainF');
      i := Func;
    end;
    
    UINT nMsgID = RegisterWindowMessage(_T("WM_MSG")); 
    
    extern "C" __declspec(dllexport) int __stdcall MyFunction(HWND hWnd) {   
        if ((nMsgID != 0) && (hWnd != NULL)) {
            for (int i = 0; i < 100000; i++) { 
                int param = ceil(100 * (double) i / (double) 100000); 
                PostMessage(hWnd, nMsgID, param, 0); 
            } 
        }
        return 1; 
    } 
    
    unit Unit1;
    
    interface
    
    ...
    
    var
      DllWnd: HWND = 0;
    
    implementation
    
    var
      WM_MSG: UINT = 0;
    
    procedure TForm1.FormCreate(Sender: TObject); 
    begin 
      DllWnd := AllocateHWnd(DllWndProc);
    end; 
    
    procedure TForm1.FormDestroy(Sender: TObject); 
    begin 
      if DllWnd <> 0 then
      begin
        DeallocateHWnd(DllWnd);
        DllWnd := 0;
      end;
    end; 
    
    procedure TForm1.DllWndProc(var Message: TMessage); 
    begin 
      if (Message.Msg = WM_MSG) and (WM_MSG <> 0) then 
        ProgressBar1.Position := Message.WParam
      else
        Message.Result := DefWindowProc(DllWnd, Message.Msg, Message.WParam, Message.LParam); 
    end; 
    
    ...
    
    initialization
      WM_MSG := RegisterWindowMessage('WM_MSG');     
    
    end.
    
    uses
      Unit1;
    
    function DllFunc(Wnd: HWND): Integer; stdcall; external 'My.dll' name 'MyFunction'; 
    
    procedure TMyFunctionDLL.Execute;   
    var   
      i: Integer;   
    begin   
      i := DllFunc(DllWnd);   
    end;   
    
    function MyFunction (fHWND: HWND): Integer; cdecl; external 'My.dll'
    
    TMyFunction = function (fHWND: HWND): Integer;