MQL5-启动嵌入DLL的表单

时间:2018-07-28 21:03:56

标签: delphi dll mql5

在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当然被阻止了。

不会生成任何异常,并且两个函数都将正确返回...只是表单本身不会显示。如果有人可以阐明可能发生的情况以及任何可能的解决方法,将不胜感激。

1 个答案:

答案 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()-函数。

相关问题