【问题标题】:MQL5 - Launching a form embedded in a DLLMQL5 - 启动嵌入在 DLL 中的表单
【发布时间】:2018-07-28 21:03:56
【问题描述】:

在 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.

我尝试了几种不同的方法来创建表单(nil,parented),但没有任何区别。如果我使用 ShowModal 而不是 Show 表单会正确显示,但 MT5 GUI 会被阻止。

没有产生异常,两个函数都正确返回……只是表单本身不会显示。如果有人能对可能发生的事情以及任何可能的解决方法有所了解,将不胜感激。

【问题讨论】:

    标签: delphi dll mql5


    【解决方案1】:

    这就是问题所在:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      • 2011-08-22
      • 2018-06-03
      • 2012-03-29
      • 2013-09-05
      • 2011-06-05
      相关资源
      最近更新 更多