来自C++。Delphi窗体应用程序的dll < >我在Delphi 7和C++上编写了Windows窗体应用程序,使用MFC .d/p>编写的DLL。
目前,我正试图实现从.dll到主可执行文件的基本消息发布,以在progressbar上显示用户的计算过程,但遇到了几个问题 让我先描述一下我的方法。我在我的Delphi应用程序中注册简单消息,如:来自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")); 这没问题:调试时,我可以在两侧看到相同的值 我的库函数如下所示(只是一个测试进度
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;
第一个问题是tHWND和hWnd变量值有莫名其妙的不同。经过一些研究,我发现了三种情况:
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
一旦确定要将消息发送到正确的窗口,您就可以担心为什么消息不能正确操作进度条。我至少可以看到两个原因:
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;