MT5和trans2quik.dll - 页 5 123456789101112...18 新评论 prostotrader 2018.12.08 16:34 #41 我已经完全放弃了将MT5和Quick联系起来的想法,我只在Quick(DEE服务器+trans2quik.dll)上安顿下来。 我正在考虑实现这一方案。 选择器1不断地从DDE服务器获取数据,并将其 "存储 "在存储器中,并在相应的子程序中调用OnTick函数。 当调用GetStorageData时,DDE服务器应该被暂停,数据应该被存储在Storage中。 当Selector2调用回调时,DDE服务器和存储记录应被暂停,GetStorageData调用应被禁用。 即Selector2有高优先级,GetStorageData正常,Selector1低。 问题。 我怎样才能优雅地同步选择器1、选择器2和GetStorageData? 也许有这种同步的具体例子(我从未实现过这种东西)? Yuriy Asaulenko 2018.12.08 16:45 #42 prostotrader:放弃了连接MT5和Quick的想法,只在Quick上解决(DEE服务器+ trans2quik.dll)。 我正在考虑实现这一方案。1.非常正确的决定,只留下Quick。 2.通过DEE连接是一个非常有争议的解决方案。许多人说DDE是不稳定的,但我不知道。 在我看来,一个更好、更通用的解决方案,是Lua-DLL应用程序。我使用这个选项。当然,这要看主人的意思。 prostotrader 2018.12.08 16:54 #43 Yuriy Asaulenko:1.只保留快手的决定是正确的。 2.通过DDE通信是一个非常有争议的决定。许多人说,DDE是不稳定的,但是,我不知道。 在我看来,一个更好、更通用的解决方案,是Lua-DLL应用程序。我使用这个选项。当然,这要看主人的意思。我在很久以前为Quick写了一个DDE服务器--工作顺利,速度够快(不比Lua-DLL慢)。 而且完全没有必要为Lua和DDL数据接收器编写额外的代码。 添加 事实上,我已经写好 了图中所示的程序(而且可以运行),但遇到了一个同步问题。 Yuriy Asaulenko 2018.12.08 17:02 #44 prostotrader:我在很久以前为Quick写了一个DDE服务器--工作顺利,速度够快(不比Lua-DLL慢)。 而且根本不需要在Lua中编写额外的代码。由于我没有做过任何DDE,问题是--DDE是如何制作的?我认为有必要制作一个带有数据的表格,然后通过DDE运行它。 有一个与事件相混淆的问题。有些东西已经改变了,看起来整个表被传递给了DDE。还是我错了? 假设我错了。那么如何识别接收方的事件呢? 嫖 娼者。事实上,我已经写好 了图中所示的程序(并且可以运行),但我遇到了一个同步问题。 用什么? 在Lua中,这个问题通过从DLL到任意数据的回调来解决。 prostotrader 2018.12.08 17:14 #45 Yuriy Asaulenko:由于我没有和DDE打过交道,问题是DDE是如何制造的?看来你必须制作一个有数据的表格,然后通过DDE运行它。 有一个与事件相混淆的问题。有些东西已经改变了,看起来整个表被传递给了DDE。还是我错了? 假设我错了。那么如何识别接收方的事件呢?在Quick中,所需的表格被生成用于输出。 最后,我们用DDE服务器启动我们自己的应用程序,通过DDE输出这个表。 在第一次从Quick输出时,整个表被发送到DEE,然后只有表中的行被发送到DEE。 在其中发生变化。 在表格本身(它被完整地传送)中,有(例如在我的例子中)一个工具名称--这是标识符。 prostotrader 2018.12.08 17:18 #46 DDE服务器本身有几行字(我是用Pascal语言写的,但互联网上有很多其他语言的例子)。 unit DdeUnit; interface uses Winapi.Windows, System.Classes, System.Types, Vcl.Forms, Winapi.DdeMl, System.SysUtils, System.StrUtils, Vcl.Controls, Winapi.Messages, QTypes; const WM_DDE_ADDQUE = WM_USER + 2; var ServiceName: string = 'quikdde'; // DDE server name // procedure ClearTable(Table: TDataTable); overload; type TPokeAction = (paAccept, paPass, paReject); TDdePokeEvent = procedure(const Topic: string; var Action: TPokeAction) of object; TDdeDataEvent = procedure(const Topic: string; Cells: TRect; Data: TDataTable) of object; PDdeQueItem = ^TDdeQueItem; TDdeQueItem = packed record data: Pointer; size: integer; sTopic: String; sCells: String; end; TDdeServer = class(TWinControl) private Inst: Integer; ServiceHSz: HSz; TopicHSz: HSz; fOnPoke: TDdePokeEvent; fOnData: TDdeDataEvent; fDdeQue: TThreadList; protected function XLTDecodeV(data: pointer; datasize: integer): TDataTable; function DecodeCellAddr(CellAddr: string): TRect; procedure AddQue(var Message: TWMSysCommand); message WM_DDE_ADDQUE; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property OnPoke: TDdePokeEvent read fOnPoke write fOnPoke; property OnData: TDdeDataEvent read fOnData write fOnData; end; //--- Pointer functions ---- function addp(p: Pointer; increment: int64 = 1): Pointer; overload; function addp(p: Pointer; increment: pointer): Pointer; overload; function subp(p: Pointer; decrement: int64 = 1): Pointer; overload; function subp(p: Pointer; decrement: pointer): Pointer; overload; implementation uses main; function CallbackProc(CallType, Fmt: UINT; Conv: HConv; hsz1, hsz2: HSZ; Data: HDDEData; Data1, Data2: DWORD): HDDEData stdcall; var action: TPokeAction; sTopic: String; P: PDdeQueItem; Buff: array[0..255] of WideChar; begin result:= DDE_FNOTPROCESSED; //--- case CallType of XTYP_CONNECT: result:= 1; XTYP_POKE: begin DdeQueryString(QTrader.DdeServer.Inst, HSz1, @Buff, sizeof(Buff), CP_WINUNICODE); sTopic:= string(Buff); action:= paPass; if Assigned(QTrader.DdeServer.fOnPoke) then QTrader.DdeServer.fOnPoke(sTopic, action); //--- case action of paAccept: begin DdeQueryString(QTrader.DdeServer.Inst, HSz2, @Buff, sizeof(Buff), CP_WINUNICODE); New(P); P^.sTopic:= sTopic; P^.sCells:= string(Buff); P^.size:= DdeGetData(Data, nil, 0, 0); GetMem(P^.data, P^.size); DdeGetData(Data, P^.data, P^.size, 0); //--- with QTrader.DdeServer.fDdeQue.LockList do try add(P); finally QTrader.DdeServer.fDdeQue.UnlockList; end; if (QTrader.DdeServer.Handle <> 0) then PostMessage(QTrader.DdeServer.Handle, WM_DDE_ADDQUE, 0, 0); result:= DDE_FACK; end; paPass: result:= DDE_FACK; paReject: result:= DDE_FNOTPROCESSED; end; end; end; end; constructor TDdeServer.Create; begin inherited; fDdeQue := TThreadList.Create; Parent := TWinControl(AOwner); CreateHandle; Inst := 0; if (DdeInitialize(Inst, @CallbackProc, APPCLASS_STANDARD, 0) = DMLERR_NO_ERROR) then begin ServiceHSz := DdeCreateStringHandle(Inst, PWideChar(ServiceName), CP_WINUNICODE); if(DdeNameService(Inst, ServiceHSz, 0, DNS_REGISTER) = 0) then raise Exception.Create( 'Не удалось зарегистрировать имя DDE-сервиса ''' + ServiceName + '''' ); TopicHSz := DdeCreateStringHandle(Inst, PWideChar('Topic'), CP_WINUNICODE); end else raise Exception.Create( 'Не удалось выполнить инициализацию DDE' ); end; destructor TDdeServer.Destroy; begin DdeNameService(Inst, ServiceHsz, 0, DNS_UNREGISTER); fDdeQue.Free; DdeFreeStringHandle(Inst, ServiceHsz); DdeUninitialize(Inst); inherited; end; procedure TDdeServer.AddQue(var Message: TWMSysCommand); var vt: TDataTable; Cells: TRect; p: PDdeQueItem; i: integer; begin with fDdeQue.LockList do try p:= PDdeQueItem(Items[Count - 1]); Cells:= DecodeCellAddr(p^.sCells); vt:= XLTDecodeV(p^.data, p^.size); if (Assigned(QTrader.DdeServer.fOnData)) then QTrader.DdeServer.fOnData(p^.sTopic, Cells, vt); for i:= (Count - 1) downto 0 do begin p:= Items[i]; FreeMem(p^.data, p^.size); Delete(i); Dispose(p); end; finally fDdeQue.UnlockList; end; end; function TDdeServer.XLTDecodeV(data: pointer; datasize: integer): TDataTable; var i: integer; curr: pointer; BlockType: word; BlockSize: word; StringSize: byte; RealData: real; StringData: shortstring; DataNum: integer; begin curr:= addp(data, 4); result.RowCount := Word(curr^); curr:= addp(curr, 2); result.ColCount := Word(curr^); curr:= addp(curr, 2); //--- set array size --- SetLength(result.Cells, result.RowCount); //--- for i := 0 to result.RowCount - 1 do SetLength(result.Cells[i], result.ColCount); //--- data block -------- DataNum := 0; while(Integer(subp(curr, data)) < datasize) do begin BlockType:= Word(curr^); curr:= addp(curr, 2); BlockSize:= Word(curr^); curr:= addp(curr, 2); case BlockType of 1: begin while(BlockSize > 0) do begin RealData:= Real(curr^); curr:= addp(curr, 8); dec(BlockSize, 8); result.Cells[(DataNum div result.ColCount), (DataNum mod result.ColCount)]:= FloatToStr(RealData); inc(DataNum); end; end; 2: begin while(BlockSize > 0) do begin StringSize:= Byte(curr^); curr:= addp( curr ); StringData[0]:= AnsiChar(Chr(StringSize)); //--- for i:= 1 to StringSize do begin StringData[i]:= AnsiChar(Char(curr^)); curr:= addp(curr); end; result.Cells[(DataNum div result.ColCount), (Datanum mod result.ColCount)]:= string(StringData); inc(DataNum); dec(BlockSize, StringSize + 1); end; end; end; end; end; function TDdeServer.DecodeCellAddr( CellAddr: string ): TRect; var tmp1, tmp2: integer; begin CellAddr:= UpperCase(CellAddr); tmp1:= PosEx('R', CellAddr); tmp2:= PosEx('C', CellAddr, tmp1); try result.Top:= StrToInt(copy(CellAddr, tmp1 + 1, tmp2 - tmp1 - 1)) - 1; except exit; end; tmp1:= PosEx('R', CellAddr, tmp2); try Result.Left:= StrToInt(copy(CellAddr, tmp2 + 1, tmp1 - tmp2 - 1 - 1)) - 1; except exit; end; tmp2:= PosEx('C', CellAddr, tmp1); try result.Bottom:= StrToInt(copy(CellAddr, tmp1 + 1, tmp2 - tmp1 - 1)) - 1; result.Right:= StrToInt(copy(CellAddr, tmp2 + 1, Length(CellAddr) - tmp2)) - 1; except exit; end; end; function addp(P: Pointer; increment: int64 = 1): Pointer; overload; begin result:= Pointer(Int64(p) + increment); end; function addp(P: Pointer; increment: Pointer): Pointer; overload; begin result:= Pointer(Int64(p) + Int64(increment)); end; function subp(P: Pointer; decrement: int64 = 1): Pointer; overload; begin result:= Pointer(Int64(p) - decrement); end; function subp(P: Pointer; decrement: Pointer): Pointer; overload; begin result:= Pointer(Int64(p) - Int64(decrement)); end; end. prostotrader 2018.12.08 17:25 #47 通过工具名称创建一个子窗口(如MT 5)。 prostotrader 2018.12.08 17:27 #48 Yuriy Asaulenko:用什么? 我在图示主题中描述了这个问题 Yuriy Asaulenko 2018.12.08 17:48 #49 prostotrader:我在图示主题中描述了这个问题对不起,没有意识到。如果我理解正确的话。 我认为,解决方案是使用DBMS作为存储,例如MS SQL Server。这可能是一个部分解决方案。 第二种是使用中间的缓冲区--收集,如后进先出。嗯,还有分离线程。 那么就不需要停止任何事情,一切都简单地写入缓冲区。嗯,而且DBMS有多用户访问。 我适用这一切,但我和帕斯卡尔从6岁起就不是朋友。 PS 他们说你可以从Pascal中使用NET库。要作为存储使用,使用System.Data、System.Data。DataSet 和System.Data。数据表。我记得,在DataTable 中,多用户访问没有问题。 ZZY2 现在我正在尝试使用SQLite作为数据库,但还没有明确的结果。它当然不是一个DBMS,但在一个精简的形式下,多用户访问是可能的,而且有可能在内存中创建一个数据库。 System.Data Namespace douglaslMSdocs.microsoft.com Пространство имен обеспечивает доступ к классам, представляющим архитектуру ADO.NET. The namespace provides access to classes that represent the ADO.NET architecture. ADO.NET позволяет создавать… prostotrader 2018.12.08 18:25 #50 不,我只需要同步3个线程(基本上写一个同步器),但 我不知道如何。 123456789101112...18 新评论 原因: 取消 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
我已经完全放弃了将MT5和Quick联系起来的想法,我只在Quick(DEE服务器+trans2quik.dll)上安顿下来。
我正在考虑实现这一方案。
选择器1不断地从DDE服务器获取数据,并将其 "存储 "在存储器中,并在相应的子程序中调用OnTick函数。
当调用GetStorageData时,DDE服务器应该被暂停,数据应该被存储在Storage中。
当Selector2调用回调时,DDE服务器和存储记录应被暂停,GetStorageData调用应被禁用。
即Selector2有高优先级,GetStorageData正常,Selector1低。
问题。
我怎样才能优雅地同步选择器1、选择器2和GetStorageData?
也许有这种同步的具体例子(我从未实现过这种东西)?
放弃了连接MT5和Quick的想法,只在Quick上解决(DEE服务器+ trans2quik.dll)。
我正在考虑实现这一方案。
1.非常正确的决定,只留下Quick。
2.通过DEE连接是一个非常有争议的解决方案。许多人说DDE是不稳定的,但我不知道。
在我看来,一个更好、更通用的解决方案,是Lua-DLL应用程序。我使用这个选项。当然,这要看主人的意思。
1.只保留快手的决定是正确的。
2.通过DDE通信是一个非常有争议的决定。许多人说,DDE是不稳定的,但是,我不知道。
在我看来,一个更好、更通用的解决方案,是Lua-DLL应用程序。我使用这个选项。当然,这要看主人的意思。
我在很久以前为Quick写了一个DDE服务器--工作顺利,速度够快(不比Lua-DLL慢)。
而且完全没有必要为Lua和DDL数据接收器编写额外的代码。
添加
事实上,我已经写好 了图中所示的程序(而且可以运行),但遇到了一个同步问题。
我在很久以前为Quick写了一个DDE服务器--工作顺利,速度够快(不比Lua-DLL慢)。
而且根本不需要在Lua中编写额外的代码。
由于我没有做过任何DDE,问题是--DDE是如何制作的?我认为有必要制作一个带有数据的表格,然后通过DDE运行它。
有一个与事件相混淆的问题。有些东西已经改变了,看起来整个表被传递给了DDE。还是我错了?
假设我错了。那么如何识别接收方的事件呢?
事实上,我已经写好 了图中所示的程序(并且可以运行),但我遇到了一个同步问题。
用什么?
在Lua中,这个问题通过从DLL到任意数据的回调来解决。
由于我没有和DDE打过交道,问题是DDE是如何制造的?看来你必须制作一个有数据的表格,然后通过DDE运行它。
有一个与事件相混淆的问题。有些东西已经改变了,看起来整个表被传递给了DDE。还是我错了?
假设我错了。那么如何识别接收方的事件呢?
在Quick中,所需的表格被生成用于输出。
最后,我们用DDE服务器启动我们自己的应用程序,通过DDE输出这个表。
在第一次从Quick输出时,整个表被发送到DEE,然后只有表中的行被发送到DEE。
在其中发生变化。
在表格本身(它被完整地传送)中,有(例如在我的例子中)一个工具名称--这是标识符。
DDE服务器本身有几行字(我是用Pascal语言写的,但互联网上有很多其他语言的例子)。
通过工具名称创建一个子窗口(如MT 5)。
用什么?
我在图示主题中描述了这个问题
我在图示主题中描述了这个问题
对不起,没有意识到。如果我理解正确的话。
我认为,解决方案是使用DBMS作为存储,例如MS SQL Server。这可能是一个部分解决方案。
第二种是使用中间的缓冲区--收集,如后进先出。嗯,还有分离线程。
那么就不需要停止任何事情,一切都简单地写入缓冲区。嗯,而且DBMS有多用户访问。
我适用这一切,但我和帕斯卡尔从6岁起就不是朋友。
PS 他们说你可以从Pascal中使用NET库。要作为存储使用,使用System.Data、System.Data。DataSet 和System.Data。数据表。我记得,在DataTable 中,多用户访问没有问题。
ZZY2 现在我正在尝试使用SQLite作为数据库,但还没有明确的结果。它当然不是一个DBMS,但在一个精简的形式下,多用户访问是可能的,而且有可能在内存中创建一个数据库。
不,我只需要同步3个线程(基本上写一个同步器),但
我不知道如何。