在MetaTrader 4 / MQL4中,我能够显示非模式形式(即带有字符串网格的简单窗口),并使用DLL接口将数据从指示器传递给该形式。现在已经做了一段时间了,效果很好。
试图在MetaTrader 5 / MQL5中完成相同的操作,但遇到一些麻烦。表单显示,但立即进入无响应状态(应用程序无响应)。
我确实在不同的64位平台(eSignal 12)上使用相同的64位DLL进行了测试,并且表格加载正常。
我正在使用Delphi XE5 Update 2构建DLL。 MT4为32位,MT5为64位。 MT5版本是1881年。我创建了一个非常简单的MQL5脚本和Delphi DLL对其进行测试:
MQL5
#import "TestForm.dll"
int showAForm(int hwnd);
int closeAForm();
#import
void OnStart()
{
//---
int hwnd=ChartGetInteger(0,CHART_WINDOW_HANDLE,0);
showAForm(hwnd);
Sleep(5000);
closeAForm();
//---
}
德尔福
library TestForm;
uses
System.SysUtils,
System.Classes,
Windows,
Vcl.Forms, Vcl.Dialogs;
{$R *.res}
var
myForm: TForm;
function showAForm(handle: HWND): integer; stdCall;
var
myHandle: HWND;
begin
myHandle := FindWindow('MetaQuotes::MetaTrader::5.00', nil);
showMessage(IntToStr(myHandle));
try
myForm := TForm.Create(nil);
// myForm:=TForm.CreateParented(myHandle);
// Windows.SetParent(myForm.Handle, myHandle);
myForm.Show;
result := 1;
except
result := -2;
end;
end;
function closeAForm(): integer; stdCall;
begin
myForm.Close();
FreeAndNil(myForm);
result := 1;
end;
exports
showAForm,
closeAForm;
begin
IsMultiThread := true;
end.
我尝试了几种不同的创建表单的方法(无,父母),但这没有什么区别。如果我使用ShowModal而不是Show表单可以正确显示,但是MT5 GUI当然被阻止了。
不会生成任何异常,并且两个函数都将正确返回...只是表单本身不会显示。如果有人可以阐明可能发生的情况以及任何可能的解决方法,将不胜感激。
答案 0 :(得分:0)
这是问题所在
showAForm(hwnd);
Sleep(5000);
closeAForm();
您的Sleep(5000);
将GUI线程阻塞了整整5秒钟。
因此,您创建表单showAForm()
,阻塞GUI线程5秒钟,然后关闭表单closeAForm()
。
Delphi表单需要有效的消息泵才能正常工作,
但是Sleep(5000);
会阻塞线程,并且不允许消息泵运行。
在Delphi应用程序中,例如“ mydelphiapp.exe”,Application.ProcessMessage函数处理一条消息,并且在Application.Run过程中,有类似以下代码:
repeat
try
HandleMessage;
except
HandleException(Self);
end;
until Terminated;
要解决该问题,您需要在Delphi中进行构建,它是Sleep()
的消息抽取替代品:
procedure MessagePumpingSleep(ADelay:Longword); stdcall;
var
T1, T2, dT : Longword;
begin
T1 := GetTickCount;
repeat
Application.ProcessMessages;
Sleep(1); // this will stop this procedure from consuming 100% CPU.
T2 := GetTickCount;
dT := T2 - T1;
until dT >= ADelay;
end;
exports MessagePumpingSleep;
然后调用MessagePumpingSleep(5000)
而不是Sleep(5000);
显然,要能够调用MessagePumpingSleep(5000)
,您需要在MQL5中编写适当的导入代码,以从Delphi DLL中导入MessagePumpingSleep()
-函数。