Compare commits

...

36 Commits

Author SHA1 Message Date
DW 515a12ab15 Added function ChangeAccount 2017-08-12 01:31:36 +03:00
DW 10e267d031 Fixed bug in function iBarShift 2017-07-20 17:55:29 +03:00
DW abcd489367 Started version 1.0.37 2017-06-21 17:41:10 +03:00
DW d630e61e3c Issue #52: Updated functions OrderSend to use request stucture 2017-05-11 17:26:46 +03:00
DW 280bab7faf Started version 1.0.36 2017-05-11 10:44:30 +03:00
DW 26d270422b Revert version mtapi (MT4) to 1.0.35 2017-05-06 23:34:30 +03:00
DW 9cd2e3b18f Updated test application: added button on function UnlockTicks 2017-05-05 15:51:34 +03:00
DW 50013c0c29 Added command to UnlockTick in backtesting mode that will be locked on each candle. It allows to perform big tasks and send commands to MT4 in time of candle. 2017-05-05 14:16:15 +03:00
DW ca49d23017 Started version 1.0.36 2017-05-05 14:01:29 +03:00
DW 0346836d35 Issue #51: Add support localhost (127.0.0.1) host name 2017-05-05 13:57:43 +03:00
DW 2cc41df01a MtApi (MT4) version 1.0.34. Fixed issue #45 in MtApi.ex4 2017-02-22 17:17:00 +02:00
DW f05ade2cbf Set AppendToFile to True in LogConfigurator 2017-01-12 16:47:41 +02:00
DW d34524d77f Issue #44: Fixed MT5Connector project for using MtAdapter 2017-01-08 14:47:08 +02:00
DW d06cc67a5d MtApi MT5: started version 1.0.12 2017-01-08 14:45:03 +02:00
DW 5b76bf0547 Merge master fixed conflict. 2017-01-05 21:36:55 +02:00
DW 1c269f7339 Issue #32: Added function ObjectName into test client 2017-01-05 02:14:13 +02:00
DW 21fb790d8c Issue #32: Fixed small bugs in EA MtApi.mq4 2017-01-05 01:02:55 +02:00
DW 7c9a0aa8cc Issue #32: Implement object functions in EA MtApi.mq4 2017-01-03 21:29:41 +02:00
DW 18ddf3df1c Issue #32: Added c# implementations of most object functions in MtApi client 2016-12-30 17:16:48 +02:00
DW a8832b79ba Issue #32: Added function ObjectCreate in MtApi (MT4) 2016-12-27 17:41:11 +02:00
vdemydiuk 39146d68b2 Starting work on Object Functions 2016-12-26 17:49:06 +02:00
DW 5b03f01e9b Clear unnecessary witespaces in MtApi.mq4 2016-12-21 14:26:37 +02:00
vdemydiuk 8f5a1c8222 Refactored MtApi.mq4 2016-12-21 12:01:15 +02:00
vdemydiuk f5f13a13cc Issue #32: Added function ChartRedraw 2016-12-12 17:29:52 +02:00
vdemydiuk 9ef970cf1e Refactoring TestApiUiClient (Account Information tab) 2016-11-30 10:57:33 +02:00
vdemydiuk b5878ccb62 Refactoring TestApiUiClient (Check Status tab) 2016-11-29 19:08:53 +02:00
DW 4a7bb6f2cb MtApi (MT5) ver. 1.0.11.1 HotFix 2016-11-29 10:20:55 +02:00
vdemydiuk 5abfeebc90 Issue #32: Added function ChartId 2016-11-28 16:03:40 +02:00
vdemydiuk e333164552 Issue #32: Added ExecutorHandle property to determine which expert will be used for execution command 2016-11-28 14:45:33 +02:00
vdemydiuk 9a6968f618 Refactoring MtApi 2016-11-26 19:27:09 +02:00
DW d63a53b8a9 MtApi (MT4) version 1.0.32.1 (HotFix) 2016-11-25 16:06:11 +02:00
DW 7e821fcade Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-25 15:50:56 +02:00
DW 88e2d22abe Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-23 13:09:47 +02:00
DW fcfd741e5b Issue #37: Used ConcurrencyMode.Multiple for server and client side to avoid deadlocks and freezes of MtApiService 2016-11-23 10:51:50 +02:00
DW c722511c03 Refactored MtApiService (ver. 1.0.24): Added ExpertHandle to MtQuote and MtEvent. Added event QuoteUpdate to MtApiClient. 2016-11-18 15:47:55 +02:00
DW 39599436ab Started version 1.0.33 of MtApi MT4 2016-11-18 12:13:00 +02:00
54 changed files with 3067 additions and 1485 deletions
+24 -24
View File
@@ -107,7 +107,7 @@ int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid,
try try
{ {
MT5Handler^ mtHander = gcnew MT5Handler(); MT5Handler^ mtHander = gcnew MT5Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHander); MtAdapter::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHander);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -123,7 +123,7 @@ int _stdcall deinitExpert(int expertHandle, wchar_t* err)
{ {
try try
{ {
MtServerInstance::GetInstance()->DeinitExpert(expertHandle); MtAdapter::GetInstance()->DeinitExpert(expertHandle);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -139,7 +139,7 @@ int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double a
{ {
try try
{ {
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask); MtAdapter::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -155,7 +155,7 @@ int _stdcall sendIntResponse(int expertHandle, int response)
{ {
try try
{ {
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -169,7 +169,7 @@ int _stdcall sendLongResponse(int expertHandle, __int64 response)
{ {
try try
{ {
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -183,7 +183,7 @@ int _stdcall sendULongResponse(int expertHandle, unsigned __int64 response)
{ {
try try
{ {
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -199,7 +199,7 @@ int _stdcall sendBooleanResponse(int expertHandle, int response)
{ {
bool value = (response != 0) ? true : false; bool value = (response != 0) ? true : false;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -213,7 +213,7 @@ int _stdcall sendDoubleResponse(int expertHandle, double response)
{ {
try try
{ {
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -227,7 +227,7 @@ int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
{ {
try try
{ {
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response))); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -241,7 +241,7 @@ int _stdcall sendVoidResponse(int expertHandle)
{ {
try try
{ {
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr); MtAdapter::GetInstance()->SendResponse(expertHandle, nullptr);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -262,7 +262,7 @@ int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
list[i] = values[i]; list[i] = values[i];
} }
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -283,7 +283,7 @@ int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
list[i] = values[i]; list[i] = values[i];
} }
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -304,7 +304,7 @@ int _stdcall sendLongArrayResponse(int expertHandle, __int64* values, int size)
list[i] = values[i]; list[i] = values[i];
} }
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -335,7 +335,7 @@ int _stdcall sendMqlRatesArrayResponse(int expertHandle, CMqlRates values[], int
list[i] = rates; list[i] = rates;
} }
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -357,7 +357,7 @@ int _stdcall sendMqlTickResponse(int expertHandle, CMqlTick* response, int size)
mtResponse->last = response->last; mtResponse->last = response->last;
mtResponse->volume = response->volume; mtResponse->volume = response->volume;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -384,7 +384,7 @@ int _stdcall sendMqlBookInfoArrayResponse(int expertHandle, CMqlBookInfo values[
list[i] = info; list[i] = info;
} }
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list)); MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -400,7 +400,7 @@ int _stdcall getCommandType(int expertHandle, int* res)
{ {
try try
{ {
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle); *res = MtAdapter::GetInstance()->GetCommandType(expertHandle);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -414,7 +414,7 @@ int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
{ {
try try
{ {
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); *res = (int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -428,7 +428,7 @@ int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
{ {
try try
{ {
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); *res = (double)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -442,7 +442,7 @@ int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
{ {
try try
{ {
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex)); convertSystemString(res, (String^)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -456,7 +456,7 @@ int _stdcall getULongValue(int expertHandle, int paramIndex, unsigned __int64* r
{ {
try try
{ {
*res = (unsigned long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); *res = (unsigned long)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -470,7 +470,7 @@ int _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res)
{ {
try try
{ {
*res = (long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); *res = (long)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
@@ -484,7 +484,7 @@ int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res)
{ {
try try
{ {
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); bool val = (bool)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = val == true ? 1 : 0; *res = val == true ? 1 : 0;
} }
catch (Exception^ e) catch (Exception^ e)
@@ -499,7 +499,7 @@ int _stdcall getUIntValue(int expertHandle, int paramIndex, unsigned int* res)
{ {
try try
{ {
*res = (unsigned int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); *res = (unsigned int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
} }
catch (Exception^ e) catch (Exception^ e)
{ {
+2 -3
View File
@@ -1,8 +1,7 @@
namespace MTApiService namespace MTApiService
{ {
public interface ICommandManager internal interface ICommandManager
{ {
void EnqueueCommandTask(MtCommandTask task); MtCommandTask SendCommand(MtCommand task);
MtCommandTask DequeueCommandTask();
} }
} }
+9
View File
@@ -0,0 +1,9 @@
namespace MTApiService
{
internal interface ITaskExecutor
{
void Execute(MtCommandTask task);
int Handle { get; }
}
}
+1 -5
View File
@@ -29,7 +29,7 @@ namespace MTApiService
var roller = new RollingFileAppender var roller = new RollingFileAppender
{ {
AppendToFile = false, AppendToFile = true,
File = $@"{System.IO.Path.GetTempPath()}{profileName}\Logs\{filename}", File = $@"{System.IO.Path.GetTempPath()}{profileName}\Logs\{filename}",
Layout = patternLayout, Layout = patternLayout,
PreserveLogFileNameExtension = true, PreserveLogFileNameExtension = true,
@@ -41,10 +41,6 @@ namespace MTApiService
roller.ActivateOptions(); roller.ActivateOptions();
hierarchy.Root.AddAppender(roller); hierarchy.Root.AddAppender(roller);
var memory = new MemoryAppender();
memory.ActivateOptions();
hierarchy.Root.AddAppender(memory);
#if (DEBUG) #if (DEBUG)
hierarchy.Root.Level = Level.Debug; hierarchy.Root.Level = Level.Debug;
#else #else
+3 -2
View File
@@ -62,6 +62,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="ICommandManager.cs" /> <Compile Include="ICommandManager.cs" />
<Compile Include="IMetaTraderHandler.cs" /> <Compile Include="IMetaTraderHandler.cs" />
<Compile Include="ITaskExecutor.cs" />
<Compile Include="LogConfigurator.cs" /> <Compile Include="LogConfigurator.cs" />
<Compile Include="MtCommandEventArgs.cs" /> <Compile Include="MtCommandEventArgs.cs" />
<Compile Include="IDisposableChannel.cs" /> <Compile Include="IDisposableChannel.cs" />
@@ -78,11 +79,11 @@
<Compile Include="MtConnectionProfile.cs" /> <Compile Include="MtConnectionProfile.cs" />
<Compile Include="MtExecutorManager.cs" /> <Compile Include="MtExecutorManager.cs" />
<Compile Include="MtExpert.cs" /> <Compile Include="MtExpert.cs" />
<Compile Include="MtInstrument.cs" /> <Compile Include="MtQuote.cs" />
<Compile Include="MtResponse.cs" /> <Compile Include="MtResponse.cs" />
<Compile Include="MtServer.cs" /> <Compile Include="MtServer.cs" />
<Compile Include="MtCommand.cs" /> <Compile Include="MtCommand.cs" />
<Compile Include="MtServerInstance.cs" /> <Compile Include="MtAdapter.cs" />
<Compile Include="MtService.cs" /> <Compile Include="MtService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
+53 -9
View File
@@ -4,13 +4,13 @@ using log4net;
namespace MTApiService namespace MTApiService
{ {
public class MtServerInstance public class MtAdapter
{ {
#region Fields #region Fields
private const string LogProfileName = "MtApiService"; private const string LogProfileName = "MtApiService";
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServerInstance)); private static readonly ILog Log = LogManager.GetLogger(typeof(MtAdapter));
private static readonly MtServerInstance Instance = new MtServerInstance(); private static readonly MtAdapter Instance = new MtAdapter();
private readonly Dictionary<int, MtServer> _servers = new Dictionary<int, MtServer>(); private readonly Dictionary<int, MtServer> _servers = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>(); private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>();
@@ -18,16 +18,16 @@ namespace MTApiService
#region Init Instance #region Init Instance
private MtServerInstance() private MtAdapter()
{ {
LogConfigurator.Setup(LogProfileName); LogConfigurator.Setup(LogProfileName);
} }
static MtServerInstance() static MtAdapter()
{ {
} }
public static MtServerInstance GetInstance() public static MtAdapter GetInstance()
{ {
return Instance; return Instance;
} }
@@ -60,7 +60,7 @@ namespace MTApiService
} }
} }
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler); var expert = new MtExpert(expertHandle, new MtQuote { Instrument = symbol, Bid = bid, Ask = ask, ExpertHandle = expertHandle }, mtHandler);
lock (_experts) lock (_experts)
{ {
@@ -111,7 +111,7 @@ namespace MTApiService
if (expert != null) if (expert != null)
{ {
expert.Quote = new MtQuote(symbol, bid, ask); expert.Quote = new MtQuote { Instrument = symbol, Bid = bid, Ask = ask, ExpertHandle = expertHandle };
} }
else else
{ {
@@ -133,7 +133,7 @@ namespace MTApiService
if (expert != null) if (expert != null)
{ {
expert.SendEvent(new MtEvent(eventType, payload)); expert.SendEvent(new MtEvent { EventType = eventType, Payload = payload, ExpertHandle = expertHandle });
} }
else else
{ {
@@ -208,6 +208,50 @@ namespace MTApiService
return retval; return retval;
} }
public object GetNamedParameter(int expertHandle, string name)
{
Log.DebugFormat("GetNamedParameter: begin. expertHandle = {0}, name = {1}", expertHandle, name);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("GetNamedParameter: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetNamedParameter(name);
Log.DebugFormat("GetNamedParameter: end. retval = {0}", retval);
return retval;
}
public bool ContainsNamedParameter(int expertHandle, string name)
{
Log.DebugFormat("ContainsNamedParameter: begin. expertHandle = {0}, name = {1}", expertHandle, name);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("ContainsNamedParameter: expert with id {0} has not been found.", expertHandle);
}
bool retval = expert != null ? expert.ContainsNamedParameter(name) : false;
Log.DebugFormat("ContainsNamedParameter: end. retval = {0}", retval);
return retval;
}
#endregion #endregion
#region Private Methods #region Private Methods
+1 -1
View File
@@ -11,13 +11,13 @@ namespace MTApiService
: base(callbackContext, binding, remoteAddress) : base(callbackContext, binding, remoteAddress)
{ {
InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted; InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted;
InnerDuplexChannel.Open();
} }
#region IMtApi Members #region IMtApi Members
public bool Connect() public bool Connect()
{ {
InnerDuplexChannel.Open();
return Channel.Connect(); return Channel.Connect();
} }
+42 -90
View File
@@ -6,38 +6,33 @@ using log4net;
namespace MTApiService namespace MTApiService
{ {
[CallbackBehavior(UseSynchronizationContext = false)] [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class MtClient: IMtApiCallback, IDisposable public class MtClient : IMtApiCallback, IDisposable
{ {
private const string ServiceName = "MtApiService"; private const string ServiceName = "MtApiService";
public delegate void MtQuoteHandler(MtQuote quote); public delegate void MtQuoteHandler(MtQuote quote);
public delegate void MtEventHandler(MtEvent e);
#region Fields #region Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtClient)); private static readonly ILog Log = LogManager.GetLogger(typeof(MtClient));
private MtApiProxy _proxy; private readonly MtApiProxy _proxy;
private bool _isConnected;
#endregion #endregion
#region Public Methods #region ctor
public void Open(string host, int port) public MtClient(string host, int port)
{ {
Log.DebugFormat("Open: begin. host = {0}, port = {1}", host, port);
if (string.IsNullOrEmpty(host)) if (string.IsNullOrEmpty(host))
throw new ArgumentNullException(nameof(host), "host is null or empty"); throw new ArgumentNullException(nameof(host), "host is null or empty");
if (port < 0 || port > 65536) if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid"); throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
var urlService = $"net.tcp://{host}:{port}/{ServiceName}"; Host = host;
Port = port;
if (_proxy != null) var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
{
Log.Warn("Open: end. _proxy is not null.");
return;
}
var bind = new NetTcpBinding(SecurityMode.None) var bind = new NetTcpBinding(SecurityMode.None)
{ {
@@ -55,28 +50,19 @@ namespace MTApiService
MaxNameTableCharCount = 2147483647 MaxNameTableCharCount = 2147483647
} }
}; };
// Commented next statement since it is not required
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService)); _proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted; _proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
} }
public void Open(int port) public MtClient(int port)
{ {
Log.DebugFormat("Open: begin. port = {0}", port);
if (port < 0 || port > 65536) if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid"); throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
var urlService = $"net.pipe://localhost/{ServiceName}_{port}"; Port = port;
if (_proxy != null) var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
{
Log.Warn("Open: end. _proxy is not null.");
return;
}
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{ {
@@ -94,61 +80,40 @@ namespace MTApiService
MaxNameTableCharCount = 2147483647 MaxNameTableCharCount = 2147483647
} }
}; };
// Commented next statement since it is not required
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService)); _proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted; _proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
} }
public void Close()
{
Log.Debug("Close: begin.");
if (_proxy != null) #endregion
{
_proxy.Faulted -= ProxyFaulted;
_proxy.Dispose();
_proxy = null;
}
_isConnected = false;
Log.Debug("Close: end.");
}
#region Public Methods
/// <exception cref="CommunicationException">Thrown when connection failed</exception> /// <exception cref="CommunicationException">Thrown when connection failed</exception>
public void Connect() public void Connect()
{ {
Log.Debug("Connect: begin."); Log.Debug("Connect: begin.");
if (_proxy == null) if (_proxy.State != CommunicationState.Created)
{ {
Log.Error("Connect: _proxy is not defined."); Log.ErrorFormat("Connected: end. Client has invalid state {0}", _proxy.State);
throw new CommunicationException("Connection failed to service. Proxy is not defined (needs to call Open)");
}
if (_isConnected)
{
Log.Warn("Connected: end. Client is already connected.");
return; return;
} }
bool coonected;
try try
{ {
_isConnected = _proxy.Connect(); coonected = _proxy.Connect();
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.ErrorFormat("Connect: Exception - {0}", ex.Message); Log.ErrorFormat("Connect: Exception - {0}", ex.Message);
Close();
throw new CommunicationException($"Connection failed to service. {ex.Message}"); throw new CommunicationException($"Connection failed to service. {ex.Message}");
} }
if (_isConnected == false) if (coonected == false)
{ {
Log.Error("Connect: end. Connection failed."); Log.Error("Connect: end. Connection failed.");
throw new CommunicationException("Connection failed"); throw new CommunicationException("Connection failed");
@@ -163,72 +128,60 @@ namespace MTApiService
try try
{ {
_isConnected = false; _proxy.Disconnect();
_proxy?.Disconnect();
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message); Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
Close();
} }
Log.Debug("Disconnect: end."); Log.Debug("Disconnect: end.");
} }
/// <exception cref="CommunicationException">Thrown when connection failed</exception> /// <exception cref="CommunicationException">Thrown when connection failed</exception>
public MtResponse SendCommand(int commandType, ArrayList parameters) public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary<string, object> namedParams, int expertHandle)
{ {
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count); Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
MtResponse result; if (IsConnected == false)
if (_isConnected == false)
{ {
Log.Error("SendCommand: Client is not connected."); Log.Error("SendCommand: Client is not connected.");
throw new CommunicationException("Client is not connected."); throw new CommunicationException("Client is not connected.");
} }
if (_proxy == null) MtResponse result;
{
Log.Error("SendCommand: Proxy is not defined.");
throw new CommunicationException("Proxy is not defined.");
}
try try
{ {
result = _proxy.SendCommand(new MtCommand(commandType, parameters)); result = _proxy.SendCommand(new MtCommand {
CommandType = commandType,
Parameters = parameters,
NamedParams = namedParams,
ExpertHandle = expertHandle});
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message); Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
Close();
throw new CommunicationException("Service connection failed! " + ex.Message); throw new CommunicationException("Service connection failed! " + ex.Message);
} }
Log.DebugFormat("SendCommand: end. result = {0}", result);
return result; return result;
} }
/// <exception cref="CommunicationException">Thrown when connection failed</exception> /// <exception cref="CommunicationException">Thrown when connection failed</exception>
public IEnumerable<MtQuote> GetQuotes() public List<MtQuote> GetQuotes()
{ {
Log.Debug("GetQuotes: begin."); Log.Debug("GetQuotes: begin.");
if (_isConnected == false) if (IsConnected == false)
{ {
Log.Warn("GetQuotes: end. Client is not connected."); Log.Warn("GetQuotes: end. Client is not connected.");
return null; return null;
} }
if (_proxy == null)
{
Log.Warn("GetQuotes: end. _proxy is not defined.");
return null;
}
List<MtQuote> result; List<MtQuote> result;
try try
@@ -239,8 +192,6 @@ namespace MTApiService
{ {
Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message); Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message);
Close();
throw new CommunicationException($"Service connection failed! {ex.Message}"); throw new CommunicationException($"Service connection failed! {ex.Message}");
} }
@@ -286,18 +237,17 @@ namespace MTApiService
{ {
Log.Debug("OnServerStopped: begin."); Log.Debug("OnServerStopped: begin.");
Close();
ServerDisconnected?.Invoke(this, EventArgs.Empty); ServerDisconnected?.Invoke(this, EventArgs.Empty);
Log.Debug("OnServerStopped: end."); Log.Debug("OnServerStopped: end.");
} }
public void OnMtEvent(MtEvent mtEvent) public void OnMtEvent(MtEvent e)
{ {
Log.DebugFormat("OnMtEvent: begin. event = {0}", mtEvent); Log.DebugFormat("OnMtEvent: begin. event = {0}", e);
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent)); MtEventReceived?.Invoke(e);
Log.Debug("OnMtEvent: end."); Log.Debug("OnMtEvent: end.");
} }
@@ -305,7 +255,10 @@ namespace MTApiService
#endregion #endregion
#region Properties #region Properties
public bool IsConnected => _proxy.State == CommunicationState.Opened && _isConnected; public string Host { get; private set; }
public int Port { get; private set; }
private bool IsConnected => _proxy.State == CommunicationState.Opened;
#endregion #endregion
@@ -315,7 +268,6 @@ namespace MTApiService
{ {
Log.Debug("ProxyFaulted: begin."); Log.Debug("ProxyFaulted: begin.");
Close();
ServerFailed?.Invoke(this, EventArgs.Empty); ServerFailed?.Invoke(this, EventArgs.Empty);
Log.Debug("ProxyFaulted: end."); Log.Debug("ProxyFaulted: end.");
@@ -329,7 +281,7 @@ namespace MTApiService
{ {
Log.Debug("Dispose: begin."); Log.Debug("Dispose: begin.");
Close(); _proxy.Dispose();
Log.Debug("Dispose: end."); Log.Debug("Dispose: end.");
} }
@@ -342,7 +294,7 @@ namespace MTApiService
public event MtQuoteHandler QuoteUpdated; public event MtQuoteHandler QuoteUpdated;
public event EventHandler ServerDisconnected; public event EventHandler ServerDisconnected;
public event EventHandler ServerFailed; public event EventHandler ServerFailed;
public event EventHandler<MtEventArgs> MtEventReceived; public event MtEventHandler MtEventReceived;
#endregion #endregion
} }
} }
+9 -8
View File
@@ -1,26 +1,27 @@
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Collections; using System.Collections;
using System.Collections.Generic;
namespace MTApiService namespace MTApiService
{ {
[DataContract] [DataContract]
public class MtCommand public class MtCommand
{ {
public MtCommand(int commandType, ArrayList parameters) [DataMember]
{ public int CommandType { get; set; }
CommandType = commandType;
Parameters = parameters;
}
[DataMember] [DataMember]
public int CommandType { get; private set; } public ArrayList Parameters { get; set; }
[DataMember] [DataMember]
public ArrayList Parameters { get; private set; } public Dictionary<string, object> NamedParams { get; set; }
[DataMember]
public int ExpertHandle { get; set; }
public override string ToString() public override string ToString()
{ {
return $"CommandType = {CommandType}"; return $"CommandType = {CommandType}; ExpertHandle = {ExpertHandle}";
} }
} }
} }
+5 -18
View File
@@ -7,30 +7,17 @@ namespace MTApiService
public class MtEvent public class MtEvent
{ {
[DataMember] [DataMember]
public int EventType { get; private set; } public int EventType { get; internal set; }
[DataMember] [DataMember]
public string Payload { get; private set; } public string Payload { get; internal set; }
public MtEvent(int eventType, string payload) [DataMember]
{ public int ExpertHandle { get; internal set; }
EventType = eventType;
Payload = payload;
}
public override string ToString() public override string ToString()
{ {
return "MtEvent = " + EventType + ", Payload = " + Payload; return $"EventType = {EventType}; Payload = {Payload}; ExpertHandle = {ExpertHandle}";
} }
} }
public class MtEventArgs: EventArgs
{
public MtEventArgs(MtEvent e)
{
Event = e;
}
public MtEvent Event { get; private set; }
}
} }
+55 -111
View File
@@ -4,14 +4,13 @@ using log4net;
namespace MTApiService namespace MTApiService
{ {
internal class MtCommandExecutorManager : ICommandManager internal class MtExecutorManager : ICommandManager
{ {
#region Private Fields #region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtCommandExecutorManager)); private static readonly ILog Log = LogManager.GetLogger(typeof(MtExecutorManager));
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
private readonly List<ITaskExecutor> _executorList = new List<ITaskExecutor>();
private readonly Dictionary<int, ITaskExecutor> _executorMap = new Dictionary<int, ITaskExecutor>();
private readonly object _locker = new object(); private readonly object _locker = new object();
#endregion #endregion
@@ -23,149 +22,94 @@ namespace MTApiService
lock (_locker) lock (_locker)
{ {
_commandExecutors.Clear(); _executorList.Clear();
_commandTasks.Clear(); _executorMap.Clear();
} }
Log.Debug("Stop: end."); Log.Debug("Stop: end.");
} }
public void AddCommandExecutor(MtExpert commandExecutor) public void AddExecutor(ITaskExecutor executor)
{ {
if (commandExecutor == null) if (executor == null)
throw new ArgumentNullException(nameof(commandExecutor)); throw new ArgumentNullException(nameof(executor));
Log.DebugFormat("AddCommandExecutor: begin. commandExecutor = {0}", commandExecutor); Log.DebugFormat("AddExecutor: begin. executor = {0}", executor);
var notify = false;
lock (_locker) lock (_locker)
{ {
if (_commandExecutors.Contains(commandExecutor)) if (_executorList.Contains(executor))
{ {
Log.Warn("AddCommandExecutor: end. Command executor already exist."); Log.Warn("AddExecutor: end. Executor already exist.");
return; return;
} }
_commandExecutors.Add(commandExecutor); _executorList.Add(executor);
if (_commandTasks.Count > 0) _executorMap[executor.Handle] = executor;
{
notify = true;
}
}
commandExecutor.CommandExecuted += CommandExecutor_CommandExecuted;
commandExecutor.CommandManager = this;
if (notify)
{
NotifyCommandReady();
} }
Log.Debug("AddCommandExecutor: end."); Log.Debug("AddCommandExecutor: end.");
} }
public void RemoveCommandExecutor(MtExpert commandExecutor) public void RemoveExecutor(ITaskExecutor executor)
{ {
if (commandExecutor == null) if (executor == null)
throw new ArgumentNullException(nameof(commandExecutor)); throw new ArgumentNullException(nameof(executor));
Log.DebugFormat("RemoveCommandExecutor: begin. commandExecutor = {0}", commandExecutor); Log.DebugFormat("RemoveExecutor: begin. executor = {0}", executor);
var notify = false;
lock (_locker) lock (_locker)
{ {
if (_commandExecutors.Contains(commandExecutor) == false) if (_executorList.Contains(executor) == false)
{ {
Log.Warn("RemoveCommandExecutor: end. Command executor is not exist in collection."); Log.Warn("RemoveExecutor: end. Executor is not exist in collection.");
return; return;
} }
_commandExecutors.Remove(commandExecutor); _executorList.Remove(executor);
if (_commandTasks.Count > 0) _executorMap.Remove(executor.Handle);
}
Log.Debug("RemoveExecutor: end.");
}
public MtCommandTask SendCommand(MtCommand command)
{
if (command == null)
throw new ArgumentNullException(nameof(command));
var task = new MtCommandTask(command);
Log.DebugFormat("SendTask: begin. command = {0}", command);
ITaskExecutor executor;
lock (_locker)
{
if (_executorMap.ContainsKey(command.ExpertHandle))
{ {
notify = true; executor = _executorMap[command.ExpertHandle];
}
else
{
executor = _executorList.Count > 0 ? _executorList[0] : null;
} }
} }
commandExecutor.CommandExecuted -= CommandExecutor_CommandExecuted; if (executor == null)
commandExecutor.CommandManager = null;
if (notify)
{ {
NotifyCommandReady(); Log.Error("SendTask: Executor is null!");
}
else
{
executor.Execute(task);
} }
Log.Debug("RemoveCommandExecutor: end."); Log.Debug("SendTask: end.");
return task;
} }
public void EnqueueCommandTask(MtCommandTask task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
Log.DebugFormat("EnqueueCommandTask: begin. task = {0}", task);
lock (_locker)
{
_commandTasks.Enqueue(task);
}
NotifyCommandReady();
Log.Debug("EnqueueCommandTask: end.");
}
public MtCommandTask DequeueCommandTask()
{
Log.Debug("DequeueCommandTask: called.");
lock (_locker)
{
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
}
}
#endregion
#region Private Methods
private void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
var commandExecutors = new List<MtExpert>();
lock (_locker)
{
commandExecutors.AddRange(_commandExecutors);
}
foreach (var executor in commandExecutors)
{
executor.NotifyCommandReady();
}
Log.DebugFormat("NotifyCommandReady: end. Notified executor count = {0}", commandExecutors.Count);
}
private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
{
Log.Debug("CommandExecutor_CommandExecuted: begin.");
var notify = false;
lock (_locker)
{
if (_commandTasks.Count > 0)
{
notify = true;
}
}
if (notify)
{
NotifyCommandReady();
}
Log.Debug("CommandExecutor_CommandExecuted: end.");
}
#endregion #endregion
} }
} }
+91 -52
View File
@@ -1,18 +1,20 @@
using System; using System;
using log4net; using log4net;
using System.Collections.Generic;
namespace MTApiService namespace MTApiService
{ {
public class MtExpert internal class MtExpert: ITaskExecutor
{ {
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote); public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
public delegate void MtEventHandler(MtExpert expert, MtEvent e);
#region Private Fields #region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert)); private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert));
private readonly IMetaTraderHandler _mtHadler; private readonly IMetaTraderHandler _mtHadler;
private MtCommandTask _commandTask; private MtCommandTask _currentTask;
private ICommandManager _commandManager; private readonly Queue<MtCommandTask> _taskQueue = new Queue<MtCommandTask>();
private readonly object _locker = new object(); private readonly object _locker = new object();
#endregion #endregion
@@ -41,9 +43,8 @@ namespace MTApiService
{ {
Log.DebugFormat("SendResponse: begin. response = {0}", response); Log.DebugFormat("SendResponse: begin. response = {0}", response);
_commandTask.SetResult(response); _currentTask.SetResult(response);
_commandTask = null; _currentTask = null;
FireOnCommandExecuted();
Log.Debug("SendResponse: end."); Log.Debug("SendResponse: end.");
} }
@@ -52,20 +53,16 @@ namespace MTApiService
{ {
Log.Debug("GetCommandType: called."); Log.Debug("GetCommandType: called.");
var commandManager = CommandManager; _currentTask = DequeueTask();
if (commandManager != null)
{
_commandTask = commandManager.DequeueCommandTask();
}
return _commandTask?.Command?.CommandType ?? 0; return _currentTask?.Command?.CommandType ?? 0;
} }
public object GetCommandParameter(int index) public object GetCommandParameter(int index)
{ {
Log.DebugFormat("GetCommandType: called. index = {0}", index); Log.DebugFormat("GetCommandParameter: called. index = {0}", index);
var command = _commandTask?.Command; var command = _currentTask?.Command;
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count) if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
{ {
return command.Parameters[index]; return command.Parameters[index];
@@ -74,6 +71,46 @@ namespace MTApiService
return null; return null;
} }
public object GetNamedParameter(string name)
{
Log.DebugFormat("GetNamedParameter: called. name = {0}", name);
var command = _currentTask?.Command;
if (command == null)
{
Log.Warn("GetNamedParameter: command is not defined in task.");
return null;
}
if (command.NamedParams == null)
{
Log.Warn("GetNamedParameter: NamedParams is not defined in command.");
return null;
}
return command.NamedParams[name];
}
public bool ContainsNamedParameter(string name)
{
Log.DebugFormat("ContainsNamedParameter: called. name = {0}", name);
var command = _currentTask?.Command;
if (command == null)
{
Log.Warn("ContainsNamedParameter: command is not defined in task.");
return false;
}
if (command.NamedParams == null)
{
Log.Warn("ContainsNamedParameter: NamedParams is not defined in command.");
return false;
}
return command.NamedParams.ContainsKey(name);
}
public void SendEvent(MtEvent mtEvent) public void SendEvent(MtEvent mtEvent)
{ {
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent); Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
@@ -90,7 +127,22 @@ namespace MTApiService
#endregion #endregion
#region ITaskExecutor
public void Execute(MtCommandTask task)
{
lock (_taskQueue)
{
_taskQueue.Enqueue(task);
}
NotifyCommandReady();
}
#endregion
#region Properties #region Properties
private MtQuote _quote; private MtQuote _quote;
public MtQuote Quote public MtQuote Quote
{ {
@@ -133,41 +185,34 @@ namespace MTApiService
} }
} }
public ICommandManager CommandManager
{
private get
{
lock (_locker)
{
return _commandManager;
}
}
set
{
lock (_locker)
{
_commandManager = value;
}
}
}
#endregion
#region IMtCommandExecutor
public void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
SendTickToMetaTrader();
Log.Debug("NotifyCommandReady: end.");
}
#endregion #endregion
#region Private Methods #region Private Methods
private void SendTickToMetaTrader() private MtCommandTask DequeueTask()
{ {
Log.Debug("DequeueTask: called.");
MtCommandTask task;
int count;
lock (_locker)
{
count = _taskQueue.Count;
task = _taskQueue.Count > 0 ? _taskQueue.Dequeue() : null;
}
Log.DebugFormat("DequeueTask: end. left task count = {0}.", count);
return task;
}
private void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
_mtHadler.SendTickToMetaTrader(Handle); _mtHadler.SendTickToMetaTrader(Handle);
Log.Debug("NotifyCommandReady: end.");
} }
private void FireOnQuoteChanged(MtQuote quote) private void FireOnQuoteChanged(MtQuote quote)
@@ -180,22 +225,16 @@ namespace MTApiService
Deinited?.Invoke(this, EventArgs.Empty); Deinited?.Invoke(this, EventArgs.Empty);
} }
private void FireOnCommandExecuted()
{
CommandExecuted?.Invoke(this, EventArgs.Empty);
}
private void FireOnMtEvent(MtEvent mtEvent) private void FireOnMtEvent(MtEvent mtEvent)
{ {
OnMtEvent?.Invoke(this, new MtEventArgs(mtEvent)); OnMtEvent?.Invoke(this, mtEvent);
} }
#endregion #endregion
#region Events #region Events
public event EventHandler Deinited; public event EventHandler Deinited;
public event MtQuoteHandler QuoteChanged; public event MtQuoteHandler QuoteChanged;
public event EventHandler CommandExecuted; public event MtEventHandler OnMtEvent;
public event EventHandler<MtEventArgs> OnMtEvent;
#endregion #endregion
} }
} }
-29
View File
@@ -1,29 +0,0 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtQuote
{
[DataMember]
public string Instrument { get; private set; }
[DataMember]
public double Bid { get; private set; }
[DataMember]
public double Ask { get; private set; }
public MtQuote(string instrument, double bid, double ask)
{
Instrument = instrument;
Bid = bid;
Ask = ask;
}
public override string ToString()
{
return "Instrument = " + Instrument + ", Bid = " + Bid + ", Ask = " + Ask;
}
}
}
+25
View File
@@ -0,0 +1,25 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtQuote
{
[DataMember]
public string Instrument { get; internal set; }
[DataMember]
public double Bid { get; internal set; }
[DataMember]
public double Ask { get; internal set; }
[DataMember]
public int ExpertHandle { get; internal set; }
public override string ToString()
{
return $"Instrument = {Instrument}; Bid = {Bid}; Ask = {Ask}; ExpertHandle = {ExpertHandle}";
}
}
}
+24 -1
View File
@@ -12,7 +12,8 @@ namespace MTApiService
{ {
static IEnumerable<Type> GetKnownTypes() static IEnumerable<Type> GetKnownTypes()
{ {
return new Type[] { typeof(MtResponseInt), typeof(MtResponseDouble), return new Type[] { typeof(MtResponseObject),
typeof(MtResponseInt), typeof(MtResponseDouble),
typeof(MtResponseString), typeof(MtResponseBool), typeof(MtResponseString), typeof(MtResponseBool),
typeof(MtResponseLong), typeof(MtResponseULong), typeof(MtResponseLong), typeof(MtResponseULong),
typeof(MtResponseDoubleArray), typeof(MtResponseIntArray), typeof(MtResponseDoubleArray), typeof(MtResponseIntArray),
@@ -22,6 +23,28 @@ namespace MTApiService
} }
public abstract object GetValue(); public abstract object GetValue();
[DataMember]
public int ErrorCode { get; set; }
}
[DataContract]
public class MtResponseObject : MtResponse
{
public MtResponseObject(object value)
{
Value = value;
}
[DataMember]
public object Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value?.ToString() ?? string.Empty;
}
} }
[DataContract] [DataContract]
+28 -11
View File
@@ -21,7 +21,7 @@ namespace MTApiService
private readonly MtService _service; private readonly MtService _service;
private readonly List<ServiceHost> _hosts = new List<ServiceHost>(); private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager(); private readonly MtExecutorManager _executorManager = new MtExecutorManager();
private readonly List<MtExpert> _experts = new List<MtExpert>(); private readonly List<MtExpert> _experts = new List<MtExpert>();
#endregion #endregion
@@ -62,8 +62,16 @@ namespace MTApiService
} }
//init local pipe host //init local pipe host
var localUrl = CreateConnectionAddress(null, port, true); var localPipeUrl = CreateConnectionAddress(null, port, true);
var localServiceHost = CreateServiceHost(localUrl, true); var localPipeServiceHost = CreateServiceHost(localPipeUrl, true);
if (localPipeServiceHost != null)
{
_hosts.Add(localPipeServiceHost);
}
//init localhost
var localUrl = CreateConnectionAddress("localhost", port, false);
var localServiceHost = CreateServiceHost(localUrl, false);
if (localServiceHost != null) if (localServiceHost != null)
{ {
_hosts.Add(localServiceHost); _hosts.Add(localServiceHost);
@@ -149,7 +157,7 @@ namespace MTApiService
_experts.Add(expert); _experts.Add(expert);
} }
_executorManager.AddCommandExecutor(expert); _executorManager.AddExecutor(expert);
_service.OnQuoteAdded(expert.Quote); _service.OnQuoteAdded(expert.Quote);
@@ -170,11 +178,20 @@ namespace MTApiService
return null; return null;
} }
var task = new MtCommandTask(command); var task = _executorManager.SendCommand(command);
_executorManager.EnqueueCommandTask(task);
//wait for execute command in MetaTrader //wait for execute command in MetaTrader
var response = task.WaitResult(WaitResponseTime); MtResponse response = null;
try
{
response = task.WaitResult(WaitResponseTime);
}
catch (Exception ex)
{
Log.WarnFormat("SendCommand: Exception - {0}", ex.Message);
}
Log.DebugFormat("SendCommand: end. response = {0}", response);
return response; return response;
} }
@@ -371,7 +388,7 @@ namespace MTApiService
expertsCount = _experts.Count; expertsCount = _experts.Count;
} }
_executorManager.RemoveCommandExecutor(expert); _executorManager.RemoveExecutor(expert);
expert.Deinited -= expert_Deinited; expert.Deinited -= expert_Deinited;
expert.QuoteChanged -= expert_QuoteChanged; expert.QuoteChanged -= expert_QuoteChanged;
@@ -398,11 +415,11 @@ namespace MTApiService
Log.Debug("expert_QuoteChanged: end."); Log.Debug("expert_QuoteChanged: end.");
} }
private void Expert_OnMtEvent(object sender, MtEventArgs e) private void Expert_OnMtEvent(MtExpert expert, MtEvent e)
{ {
Log.DebugFormat("Expert_OnMtEvent: begin. event = {0}", e.Event); Log.DebugFormat("Expert_OnMtEvent: begin. expert = {0}, event = {1}", expert, e);
_service.OnMtEvent(e.Event); _service.OnMtEvent(e);
Log.Debug("Expert_OnMtEvent: end."); Log.Debug("Expert_OnMtEvent: end.");
} }
+7 -7
View File
@@ -66,7 +66,7 @@ namespace MTApiService
if (callback == null) if (callback == null)
{ {
Log.Warn("Connect: end. Callback is not definded."); Log.Warn("Connect: end. Callback is not defined.");
return false; return false;
} }
@@ -158,7 +158,7 @@ namespace MTApiService
public void QuoteUpdate(MtQuote quote) public void QuoteUpdate(MtQuote quote)
{ {
Log.Debug("QuoteUpdate: begin."); Log.DebugFormat("QuoteUpdate: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteUpdate(quote)); ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
@@ -167,7 +167,7 @@ namespace MTApiService
public void OnQuoteAdded(MtQuote quote) public void OnQuoteAdded(MtQuote quote)
{ {
Log.Debug("OnQuoteAdded: begin."); Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteAdded(quote)); ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
@@ -176,18 +176,18 @@ namespace MTApiService
public void OnQuoteRemoved(MtQuote quote) public void OnQuoteRemoved(MtQuote quote)
{ {
Log.Debug("OnQuoteRemoved: begin."); Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteRemoved(quote)); ExecuteCallbackAction(a => a.OnQuoteRemoved(quote));
Log.Debug("OnQuoteRemoved: end."); Log.Debug("OnQuoteRemoved: end.");
} }
public void OnMtEvent(MtEvent mtEvent) public void OnMtEvent(MtEvent e)
{ {
Log.Debug("OnMtEvent: begin."); Log.DebugFormat("OnMtEvent: begin.quote = {0}", e);
ExecuteCallbackAction(a => a.OnMtEvent(mtEvent)); ExecuteCallbackAction(a => a.OnMtEvent(e));
Log.Debug("OnMtEvent: end."); Log.Debug("OnMtEvent: end.");
} }
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.23.0")] [assembly: AssemblyVersion("1.0.27.0")]
[assembly: AssemblyFileVersion("1.0.23.0")] [assembly: AssemblyFileVersion("1.0.27.0")]
+179 -199
View File
@@ -4,7 +4,8 @@
#include "MT4Handler.h" #include "MT4Handler.h"
#include "Windows.h" #include "Windows.h"
#include < vcclr.h > #include <vcclr.h>
#include <functional>
using namespace System; using namespace System;
using namespace MTApiService; using namespace MTApiService;
@@ -17,6 +18,8 @@ using namespace System::IO;
using namespace System::Collections::Generic; using namespace System::Collections::Generic;
using namespace System::Diagnostics; using namespace System::Diagnostics;
#define _DLLAPI extern "C" __declspec(dllexport)
void convertSystemString(wchar_t* dest, String^ src) void convertSystemString(wchar_t* dest, String^ src)
{ {
pin_ptr<const wchar_t> wch = PtrToStringChars(src); pin_ptr<const wchar_t> wch = PtrToStringChars(src);
@@ -24,264 +27,241 @@ void convertSystemString(wchar_t* dest, String^ src)
dest[wcslen(wch)] = '\0'; dest[wcslen(wch)] = '\0';
} }
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err) template <typename T> T Execute(std::function<T()> func, wchar_t* err, T default_value)
{ {
T result = default_value;
try try
{ {
result = func();
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
}
return result;
}
_DLLAPI bool _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
return Execute<bool>([&expertHandle, &port, symbol, &bid, &ask]() {
MT4Handler^ mtHandler = gcnew MT4Handler(); MT4Handler^ mtHandler = gcnew MT4Handler();
MtAdapter::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
return true;
}, err, false);
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:initExpert(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall deinitExpert(int expertHandle, wchar_t* err) _DLLAPI bool _stdcall deinitExpert(int expertHandle, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle]() {
{ MtAdapter::GetInstance()->DeinitExpert(expertHandle);
MtServerInstance::GetInstance()->DeinitExpert(expertHandle); return true;
} }, err, false);
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:deinitExpert(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err) _DLLAPI bool _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, symbol, &bid, &ask]() {
{ MtAdapter::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask); return true;
} }, err, false);
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:updateQuote(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err) _DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &eventType, payload]() {
{ MtAdapter::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
MtServerInstance::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload)); return true;
} }, err, false);
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:updateTimeBar(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendIntResponse(int expertHandle, int response) _DLLAPI bool _stdcall sendIntResponse(int expertHandle, int response, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &response]() {
{ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response)); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendBooleanResponse(int expertHandle, int response) _DLLAPI bool _stdcall sendBooleanResponse(int expertHandle, bool response, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &response]() {
{ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(response));
bool value = (response != 0) ? true : false; return true;
}, err, false);
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendDoubleResponse(int expertHandle, double response) _DLLAPI bool _stdcall sendDoubleResponse(int expertHandle, double response, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &response]() {
{ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response)); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendStringResponse(int expertHandle, wchar_t* response) _DLLAPI bool _stdcall sendStringResponse(int expertHandle, wchar_t* response, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, response]() {
{ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response))); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendVoidResponse(int expertHandle) _DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* message, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &code, message]() {
{ MtResponseString^ res = gcnew MtResponseString(gcnew String(message));
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr); res->ErrorCode = code;
} MtAdapter::GetInstance()->SendResponse(expertHandle, res);
catch (Exception^ e) return true;
{ }, err, false);
Debug::WriteLine("[ERROR] MTConnector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size) _DLLAPI bool _stdcall sendVoidResponse(int expertHandle, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle]() {
{ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseObject(nullptr));
return true;
}, err, false);
}
_DLLAPI bool _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size, wchar_t* err)
{
return Execute<bool>([&expertHandle, values, &size]() {
array<double>^ list = gcnew array<double>(size); array<double>^ list = gcnew array<double>(size);
for (int i = 0; i < size; i++)
for(int i = 0; i < size; i++)
{ {
list[i] = values[i]; list[i] = values[i];
} }
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list)); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size) _DLLAPI bool _stdcall sendIntArrayResponse(int expertHandle, int* values, int size, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, values, &size]() {
{
array<int>^ list = gcnew array<int>(size); array<int>^ list = gcnew array<int>(size);
for (int i = 0; i < size; i++)
for(int i = 0; i < size; i++)
{ {
list[i] = values[i]; list[i] = values[i];
} }
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list)); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall sendLongResponse(int expertHandle, __int64 response) _DLLAPI bool _stdcall sendLongResponse(int expertHandle, __int64 response, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &response]() {
{ MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response)); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall getCommandType(int expertHandle, int* res) _DLLAPI bool _stdcall getCommandType(int expertHandle, int* res, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, res]() {
{ *res = MtAdapter::GetInstance()->GetCommandType(expertHandle);
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getCommandType(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res) _DLLAPI bool _stdcall getIntValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &paramIndex, res]() {
{ *res = (int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getIntValue(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res) // --- index parameters
_DLLAPI bool _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &paramIndex, res]() {
{ *res = (double)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res) _DLLAPI bool _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &paramIndex, res]() {
{ convertSystemString(res, (String^)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex)); return true;
} }, err, false);
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getStringValue(): " + e->Message);
return 0;
}
return 1;
} }
int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res) _DLLAPI bool _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{ {
try return Execute<bool>([&expertHandle, &paramIndex, res]() {
{ *res = (bool)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex); return true;
*res = val == true ? 1 : 0; }, err, false);
} }
catch (Exception^ e)
{ _DLLAPI bool _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res, wchar_t* err)
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message); {
return 0; return Execute<bool>([&expertHandle, &paramIndex, res]() {
} *res = (__int64)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return 1; return true;
}, err, false);
}
// --- named parameters
_DLLAPI bool _stdcall containsNamedValue(int expertHandle, wchar_t* paramName)
{
wchar_t err[1000];
return Execute<bool>([&expertHandle, paramName]() {
return MtAdapter::GetInstance()->ContainsNamedParameter(expertHandle, gcnew String(paramName));
}, err, false);
}
_DLLAPI bool _stdcall getNamedIntValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (int)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedDoubleValue(int expertHandle, wchar_t* paramName, double* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (double)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedStringValue(int expertHandle, wchar_t* paramName, wchar_t* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
convertSystemString(res, (String^)obj);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedBooleanValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (bool)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedLongValue(int expertHandle, wchar_t* paramName, __int64* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
if (obj != nullptr)
*res = (__int64)obj;
return true;
}, err, false);
} }
-19
View File
@@ -1,19 +0,0 @@
LIBRARY MTConnector
EXPORTS initExpert
deinitExpert
updateQuote
sendEvent
sendIntResponse
sendBooleanResponse
sendDoubleResponse
sendStringResponse
sendVoidResponse
sendDoubleArrayResponse
sendIntArrayResponse
sendLongResponse
getCommandType
getIntValue
getDoubleValue
getStringValue
getBooleanValue
-5
View File
@@ -96,7 +96,6 @@
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -109,7 +108,6 @@
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -121,7 +119,6 @@
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -133,7 +130,6 @@
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@@ -154,7 +150,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.ico" /> <None Include="app.ico" />
<None Include="MTConnector.def" />
<None Include="ReadMe.txt" /> <None Include="ReadMe.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
-3
View File
@@ -44,9 +44,6 @@
<None Include="app.ico"> <None Include="app.ico">
<Filter>Resource Files</Filter> <Filter>Resource Files</Filter>
</None> </None>
<None Include="MTConnector.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="app.rc"> <ResourceCompile Include="app.rc">
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi
{
enum EnumColorFormat
{
COLOR_FORMAT_XRGB_NOALPHA = 0, //The component of the alpha channel is ignored
COLOR_FORMAT_ARGB_RAW = 1, //Color components are not handled by the terminal (must be correctly set by the user)
COLOR_FORMAT_ARGB_NORMALIZE = 2 //Color components are handled by the terminal
}
}
+46
View File
@@ -0,0 +1,46 @@
namespace MtApi
{
public enum EnumObject
{
OBJ_VLINE = 0, //Vertical Line
OBJ_HLINE = 1, //Horizontal Line
OBJ_TREND = 2, //Trend Line
BJ_TRENDBYANGLE = 3, //Trend Line By Angle
OBJ_CYCLES = 20, //Cycle Lines
OBJ_CHANNEL = 5, //Equidistant Channel
OBJ_STDDEVCHANNEL = 6, //Standard Deviation Channel
OBJ_REGRESSION = 4, //Linear Regression Channel
OBJ_PITCHFORK = 19, //Andrews’ Pitchfork
OBJ_GANNLINE = 7, //Gann Line
OBJ_GANNFAN = 8, //Gann Fan
OBJ_GANNGRID = 9, //Gann Grid
OBJ_FIBO = 10, //Fibonacci Retracement
OBJ_FIBOTIMES = 11, //Fibonacci Time Zones
OBJ_FIBOFAN = 12, //Fibonacci Fan
OBJ_FIBOARC = 13, //Fibonacci Arcs
OBJ_FIBOCHANNEL = 15, //Fibonacci Channel
OBJ_EXPANSION = 14, //Fibonacci Expansion
OBJ_RECTANGLE = 16, //Rectangle
OBJ_TRIANGLE = 17, //Triangle
OBJ_ELLIPSE = 18, //Ellipse
OBJ_ARROW_THUMB_UP = 29, //Thumbs Up
OBJ_ARROW_THUMB_DOWN = 30, //Thumbs Down
OBJ_ARROW_UP = 31, //Arrow Up
OBJ_ARROW_DOWN = 32, //Arrow Down
OBJ_ARROW_STOP = 33, //Stop Sign
OBJ_ARROW_CHECK = 34, //Check Sign
OBJ_ARROW_LEFT_PRICE = 35, //Left Price Label
OBJ_ARROW_RIGHT_PRICE = 36, //Right Price Label
OBJ_ARROW_BUY = 37, //Buy Sign
OBJ_ARROW_SELL = 38, //Sell Sign
OBJ_ARROW = 22, //Arrow
OBJ_TEXT = 21, //Text
OBJ_LABEL = 23, //Label
OBJ_BUTTON = 25, //Button
OBJ_BITMAP = 26, //Bitmap
OBJ_BITMAP_LABEL = 24, //Bitmap Label
OBJ_EDIT = 27, //Edit
OBJ_EVENT = 42, //The "Event" object corresponding to an event in the economic calendar
OBJ_RECTANGLE_LABEL = 28 //The "Rectangle label" object for creating and designing the custom graphical interface.
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace MtApi
{
public enum EnumObjectPropertyDouble
{
OBJPROP_PRICE = 20, // Price coordinate
OBJPROP_LEVELVALUE = 204, // Level value
OBJPROP_SCALE = 12, // Scale (properties of Gann objects, Fibonacci Arcs and Ellipse)
OBJPROP_ANGLE = 13, // Angle. For the objects with no angle specified, created from a program, the value is equal to EMPTY_VALUE
OBJPROP_DEVIATION = 16, // Deviation for the Standard Deviation Channel
}
}
+40
View File
@@ -0,0 +1,40 @@
namespace MtApi
{
public enum EnumObjectPropertyInteger
{
OBJPROP_COLOR = 6,
OBJPROP_STYLE = 7,
OBJPROP_WIDTH = 8,
OBJPROP_BACK = 9,
OBJPROP_ZORDER = 207,
OBJPROP_HIDDEN = 208,
OBJPROP_SELECTED = 17,
OBJPROP_READONLY = 1028,
OBJPROP_TYPE = 18,
OBJPROP_TIME = 19,
OBJPROP_SELECTABLE = 1000,
OBJPROP_CREATETIME = 998,
OBJPROP_LEVELS = 200,
OBJPROP_LEVELCOLOR = 201,
OBJPROP_LEVELSTYLE = 202,
OBJPROP_LEVELWIDTH = 203,
OBJPROP_ALIGN = 1036,
OBJPROP_FONTSIZE = 100,
OBJPROP_RAY_RIGHT = 1004,
OBJPROP_ELLIPSE = 11,
OBJPROP_ARROWCODE = 14,
OBJPROP_TIMEFRAMES = 15,
OBJPROP_ANCHOR = 1011,
OBJPROP_XDISTANCE = 102,
OBJPROP_YDISTANCE = 103,
OBJPROP_STATE = 1018,
OBJPROP_XSIZE = 1019,
OBJPROP_YSIZE = 1020,
OBJPROP_XOFFSET = 1033,
OBJPROP_YOFFSET = 1034,
OBJPROP_BGCOLOR = 1025,
OBJPROP_CORNER = 101,
OBJPROP_BORDER_TYPE = 1029,
OBJPROP_BORDER_COLOR = 1035
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace MtApi
{
public enum EnumObjectPropertyString
{
OBJPROP_NAME = 1037,
OBJPROP_TEXT = 999,
OBJPROP_TOOLTIP = 206,
OBJPROP_LEVELTEXT = 205,
OBJPROP_FONT = 1001,
OBJPROP_BMPFILE = 1017,
OBJPROP_SYMBOL = 1021
}
}
-42
View File
@@ -1,42 +0,0 @@
using System;
using System.Threading.Tasks;
namespace MtApi
{
static class ExtensionMethods
{
#region Event Methods
public static Task FireEventAsync(this MtApiQuoteHandler evenHandler, object sender, string symbol, double bid, double ask)
{
return Task.Factory.StartNew(() =>
{
evenHandler?.Invoke(sender, symbol, bid, ask);
});
}
public static Task FireEventAsync(this EventHandler eventHandler, object sender)
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, EventArgs.Empty);
});
}
public static Task FireEventAsync<T>(this EventHandler<T> eventHandler, object sender, T e)
where T : EventArgs
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, e);
});
}
#endregion
public static MtQuote Convert(this MTApiService.MtQuote quote)
{
return (quote != null) ? new MtQuote(quote.Instrument, quote.Bid, quote.Ask) : null;
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
namespace MtApi
{
[Flags]
public enum FlagFontStyle
{
//Flags for specifying font style
FONT_ITALIC = -2147483648,
FONT_UNDERLINE = 1073741824,
FONT_STRIKEOUT = 536870912,
//Flags for specifying font width
FW_DONTCARE = 0,
FW_THIN = 1,
FW_EXTRALIGHT = 2,
FW_ULTRALIGHT = 3,
FW_LIGHT = 4,
FW_NORMAL = 5,
FW_REGULAR = 6,
FW_MEDIUM = 7,
FW_SEMIBOLD = 8,
FW_DEMIBOLD = 9,
FW_BOLD = 10,
FW_EXTRABOLD = 11,
FW_ULTRABOLD = 12,
FW_HEAVY = 13,
FW_BLACK = 14
}
}
+6 -1
View File
@@ -59,12 +59,17 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ChartPeriod.cs" /> <Compile Include="ChartPeriod.cs" />
<Compile Include="EnumColorFormat.cs" />
<Compile Include="EnumObject.cs" />
<Compile Include="EnumObjectPropertyDouble.cs" />
<Compile Include="EnumObjectPropertyInteger.cs" />
<Compile Include="EnumObjectPropertyString.cs" />
<Compile Include="EnumSeriesInfoInteger.cs" /> <Compile Include="EnumSeriesInfoInteger.cs" />
<Compile Include="EnumSymbolInfoDouble.cs" /> <Compile Include="EnumSymbolInfoDouble.cs" />
<Compile Include="EnumSymbolInfoInteger.cs" /> <Compile Include="EnumSymbolInfoInteger.cs" />
<Compile Include="EnumTerminalInfoDouble.cs" /> <Compile Include="EnumTerminalInfoDouble.cs" />
<Compile Include="EnumTerminalInfoInteger.cs" /> <Compile Include="EnumTerminalInfoInteger.cs" />
<Compile Include="ExtensionMethods.cs" /> <Compile Include="FlagFontStyle.cs" />
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" /> <Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
<Compile Include="MqlRates.cs" /> <Compile Include="MqlRates.cs" />
<Compile Include="MqlTick.cs" /> <Compile Include="MqlTick.cs" />
+700 -114
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -13,9 +13,9 @@ namespace MtApi
return Color.FromArgb((byte)(color), (byte)(color >> 8), (byte)(color >> 16)); return Color.FromArgb((byte)(color), (byte)(color >> 8), (byte)(color >> 16));
} }
public static int ConvertToMtColor(Color color) public static int ConvertToMtColor(Color? color)
{ {
return color == Color.Empty ? 0xffffff : (Color.FromArgb(color.B, color.G, color.R).ToArgb() & 0xffffff); return color == null || color == Color.Empty ? 0xffffff : (Color.FromArgb(color.Value.B, color.Value.G, color.Value.R).ToArgb() & 0xffffff);
} }
} }
} }
+3 -3
View File
@@ -13,13 +13,13 @@ namespace MtApi
return new DateTime(tmpTime.Ticks + (time * 0x989680L)); return new DateTime(tmpTime.Ticks + (time * 0x989680L));
} }
public static int ConvertToMtTime(DateTime time) public static int ConvertToMtTime(DateTime? time)
{ {
int result = 0; int result = 0;
if (time != DateTime.MinValue) if (time != null && time != DateTime.MinValue)
{ {
DateTime tmpTime = new DateTime(1970, 1, 1); DateTime tmpTime = new DateTime(1970, 1, 1);
result = (int)((time.Ticks - tmpTime.Ticks) / 0x989680L); result = (int)((time.Value.Ticks - tmpTime.Ticks) / 0x989680L);
} }
return result; return result;
} }
+38 -9
View File
@@ -1,9 +1,4 @@
using System; namespace MtApi
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
{ {
enum MtCommandType enum MtCommandType
{ {
@@ -140,8 +135,8 @@ namespace MtApi
iBullsPower = 106, iBullsPower = 106,
iCCI = 107, iCCI = 107,
iCCIOnArray = 108, iCCIOnArray = 108,
iCustom = 109, //iCustom = 109,
iCustom_d = 10109, //iCustom_d = 10109,
iDeMarker = 110, iDeMarker = 110,
iEnvelopes = 111, iEnvelopes = 111,
iEnvelopesOnArray = 112, iEnvelopesOnArray = 112,
@@ -201,6 +196,40 @@ namespace MtApi
SymbolsTotal = 200, SymbolsTotal = 200,
SymbolName = 201, SymbolName = 201,
SymbolSelect = 202, SymbolSelect = 202,
SymbolInfoInteger = 203 SymbolInfoInteger = 203,
ChartId = 206,
ChartRedraw = 207,
//Object Functions
ObjectCreate = 208,
ObjectName = 209,
ObjectDelete = 210,
ObjectsDeleteAll = 211,
ObjectFind = 212,
ObjectGetTimeByValue = 213,
ObjectGetValueByTime = 214,
ObjectMove = 215,
ObjectsTotal = 216,
ObjectGetDouble = 217,
ObjectGetInteger = 218,
ObjectGetString = 219,
ObjectSetDouble = 220,
ObjectSetInteger = 221,
ObjectSetString = 222,
TextSetFont = 223,
TextOut = 224,
TextGetSize = 225,
ObjectDescription = 226,
ObjectGet = 227,
ObjectGetFiboDescription = 228,
ObjectGetShiftByValue = 229,
ObjectGetValueByShift = 230,
ObjectSet = 231,
ObjectSetFiboDescription = 232,
ObjectSetText = 233,
ObjectType = 234,
UnlockTicks = 235,
ChangeAccount = 280
} }
} }
+1 -4
View File
@@ -1,14 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi namespace MtApi
{ {
public class MtConnectionEventArgs: EventArgs public class MtConnectionEventArgs: EventArgs
{ {
public MtConnectionState Status { get; private set; } public MtConnectionState Status { get; private set; }
public String ConnectionMessage { get; private set; } public string ConnectionMessage { get; private set; }
public MtConnectionEventArgs(MtConnectionState status, string message) public MtConnectionEventArgs(MtConnectionState status, string message)
{ {
+9
View File
@@ -5,6 +5,7 @@
public string Instrument { get; private set; } public string Instrument { get; private set; }
public double Bid { get; private set; } public double Bid { get; private set; }
public double Ask { get; private set; } public double Ask { get; private set; }
public int ExpertHandle { get; private set; }
public MtQuote(string instrument, double bid, double ask) public MtQuote(string instrument, double bid, double ask)
{ {
@@ -12,5 +13,13 @@
Bid = bid; Bid = bid;
Ask = ask; Ask = ask;
} }
internal MtQuote(MTApiService.MtQuote quote)
{
Instrument = quote.Instrument;
Bid = quote.Bid;
Ask = quote.Ask;
ExpertHandle = quote.ExpertHandle;
}
} }
} }
-3
View File
@@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi namespace MtApi
{ {
Executable → Regular
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.32.0")] [assembly: AssemblyVersion("1.0.37.0")]
[assembly: AssemblyFileVersion("1.0.32.0")] [assembly: AssemblyFileVersion("1.0.37.0")]
-4
View File
@@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi namespace MtApi
{ {
-21
View File
@@ -1,21 +0,0 @@
using System;
namespace MtApi5
{
internal static class ExtensionMethods
{
#region Event Methods
public static void FireEvent(this EventHandler eventHandler, object sender)
{
eventHandler?.Invoke(sender, EventArgs.Empty);
}
public static void FireEvent<T>(this EventHandler<T> eventHandler, object sender, T e)
where T : EventArgs
{
eventHandler?.Invoke(sender, e);
}
#endregion
}
}
+1 -4
View File
@@ -1,14 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi5 namespace MtApi5
{ {
public class Mt5ConnectionEventArgs: EventArgs public class Mt5ConnectionEventArgs: EventArgs
{ {
public Mt5ConnectionState Status { get; private set; } public Mt5ConnectionState Status { get; private set; }
public String ConnectionMessage { get; private set; } public string ConnectionMessage { get; private set; }
public Mt5ConnectionEventArgs(Mt5ConnectionState status, string message) public Mt5ConnectionEventArgs(Mt5ConnectionState status, string message)
{ {
-1
View File
@@ -56,7 +56,6 @@
<Compile Include="Mt5Enums.cs" /> <Compile Include="Mt5Enums.cs" />
<Compile Include="Mt5ConnectionEventArgs.cs" /> <Compile Include="Mt5ConnectionEventArgs.cs" />
<Compile Include="Mt5ConnectionState.cs" /> <Compile Include="Mt5ConnectionState.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="MqlTradeRequest.cs" /> <Compile Include="MqlTradeRequest.cs" />
<Compile Include="MqlTradeResult.cs" /> <Compile Include="MqlTradeResult.cs" />
<Compile Include="Mt5QuoteEventArgs.cs" /> <Compile Include="Mt5QuoteEventArgs.cs" />
+163 -111
View File
@@ -7,6 +7,7 @@ using System.ServiceModel;
using MtApi5.Requests; using MtApi5.Requests;
using MtApi5.Responses; using MtApi5.Responses;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Threading.Tasks;
namespace MtApi5 namespace MtApi5
{ {
@@ -31,22 +32,17 @@ namespace MtApi5
#region Private Fields #region Private Fields
private readonly MtClient _client = new MtClient(); private MtClient _client;
private readonly object _locker = new object();
private volatile bool _isBacktestingMode = false; private volatile bool _isBacktestingMode = false;
private Mt5ConnectionState _connectionState = Mt5ConnectionState.Disconnected;
private int _executorHandle;
#endregion #endregion
#region Public Methods #region Public Methods
public MtApi5Client() public MtApi5Client()
{ {
LogConfigurator.Setup(LogProfileName); LogConfigurator.Setup(LogProfileName);
ConnectionState = Mt5ConnectionState.Disconnected;
_client.QuoteAdded += mClient_QuoteAdded;
_client.QuoteRemoved += mClient_QuoteRemoved;
_client.QuoteUpdated += mClient_QuoteUpdated;
_client.ServerDisconnected += mClient_ServerDisconnected;
_client.ServerFailed += mClient_ServerFailed;
} }
///<summary> ///<summary>
@@ -56,15 +52,7 @@ namespace MtApi5
///<param name="port">Port of host connection (default 8222) </param> ///<param name="port">Port of host connection (default 8222) </param>
public void BeginConnect(string host, int port) public void BeginConnect(string host, int port)
{ {
//if (string.IsNullOrEmpty(host) == false && (host.Equals("localhost") || host.Equals("127.0.0.1"))) Task.Factory.StartNew(() => Connect(host, port));
//{
// this.BeginConnect(port);
//}
//else
//{
Action<string, int> connectAction = Connect;
connectAction.BeginInvoke(host, port, null, null);
//}
} }
///<summary> ///<summary>
@@ -73,8 +61,7 @@ namespace MtApi5
///<param name="port">Port of host connection (default 8222) </param> ///<param name="port">Port of host connection (default 8222) </param>
public void BeginConnect(int port) public void BeginConnect(int port)
{ {
Action<int> connectAction = Connect; Task.Factory.StartNew(() => Connect(port));
connectAction.BeginInvoke(port, null, null);
} }
///<summary> ///<summary>
@@ -82,8 +69,7 @@ namespace MtApi5
///</summary> ///</summary>
public void BeginDisconnect() public void BeginDisconnect()
{ {
Action disconnectAction = Disconnect; Task.Factory.StartNew(() => Disconnect(false));
disconnectAction.BeginInvoke(null, null);
} }
///<summary> ///<summary>
@@ -91,11 +77,8 @@ namespace MtApi5
///</summary> ///</summary>
public IEnumerable<Mt5Quote> GetQuotes() public IEnumerable<Mt5Quote> GetQuotes()
{ {
IEnumerable<MtQuote> quotes; var client = Client;
lock (_client) var quotes = client != null ? client.GetQuotes() : null;
{
quotes = _client.GetQuotes();
}
return quotes?.Select(q => q.Parse()); return quotes?.Select(q => q.Parse());
} }
@@ -1432,7 +1415,37 @@ namespace MtApi5
///<summary> ///<summary>
///Connection status of MetaTrader API. ///Connection status of MetaTrader API.
///</summary> ///</summary>
public Mt5ConnectionState ConnectionState { get; private set; } public Mt5ConnectionState ConnectionState
{
get
{
lock (_locker)
{
return _connectionState;
}
}
}
///<summary>
///Handle of expert used to execute commands
///</summary>
public int ExecutorHandle
{
get
{
lock (_locker)
{
return _executorHandle;
}
}
set
{
lock (_locker)
{
_executorHandle = value;
}
}
}
#endregion #endregion
#region Events #region Events
@@ -1443,94 +1456,148 @@ namespace MtApi5
#endregion #endregion
#region Private Methods #region Private Methods
private void Connect(string host, int port) private MtClient Client
{ {
ConnectionState = Mt5ConnectionState.Connecting; get
ConnectionStateChanged.FireEvent(this
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, "Connecting to " + host + ":" + port));
try
{ {
lock (_client) lock (_locker)
{ {
_client.Open(host, port); return _client;
_client.Connect();
} }
} }
catch (Exception e) }
private void Connect(MtClient client)
{
lock (_locker)
{ {
ConnectionState = Mt5ConnectionState.Failed; if (_connectionState == Mt5ConnectionState.Connected
ConnectionStateChanged.FireEvent(this || _connectionState == Mt5ConnectionState.Connecting)
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, "Failed connection to " + host + ":" + port + ". " + e.Message)); {
return; return;
}
_connectionState = Mt5ConnectionState.Connecting;
} }
ConnectionState = Mt5ConnectionState.Connected; string message = string.IsNullOrEmpty(client.Host) ? $"Connecting to localhost:{client.Port}" : $"Connecting to {client.Host}:{client.Port}";
ConnectionStateChanged.FireEvent(this ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, message));
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connected, "Connected to " + host + ":" + port));
OnConnected(); var state = Mt5ConnectionState.Failed;
lock (_locker)
{
try
{
client.Connect();
state = Mt5ConnectionState.Connected;
}
catch (Exception e)
{
client.Dispose();
message = string.IsNullOrEmpty(client.Host) ? $"Failed connection to localhost:{client.Port}. {e.Message}" : $"Failed connection to {client.Host}:{client.Port}. {e.Message}";
}
if (state == Mt5ConnectionState.Connected)
{
_client = client;
_client.QuoteAdded += _client_QuoteAdded;
_client.QuoteRemoved += _client_QuoteRemoved;
_client.QuoteUpdated += _client_QuoteUpdated;
_client.ServerDisconnected += _client_ServerDisconnected;
_client.ServerFailed += _client_ServerFailed;
message = string.IsNullOrEmpty(client.Host) ? $"Connected to localhost:{client.Port}" : $"Connected to { client.Host}:{client.Port}";
}
_connectionState = state;
}
ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(state, message));
if (state == Mt5ConnectionState.Connected)
{
OnConnected();
}
}
private void Connect(string host, int port)
{
var client = new MtClient(host, port);
Connect(client);
} }
private void Connect(int port) private void Connect(int port)
{ {
ConnectionState = Mt5ConnectionState.Connecting; var client = new MtClient(port);
ConnectionStateChanged.FireEvent(this Connect(client);
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, "Connecting to 'localhost':" + port));
try
{
lock (_client)
{
_client.Open(port);
_client.Connect();
}
}
catch (Exception e)
{
ConnectionState = Mt5ConnectionState.Failed;
ConnectionStateChanged.FireEvent(this
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, "Failed connection to 'localhost':" + port + ". " + e.Message));
return;
}
ConnectionState = Mt5ConnectionState.Connected;
ConnectionStateChanged.FireEvent(this
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connected, "Connected to 'localhost':" + port));
OnConnected();
} }
private void Disconnect() private void Disconnect(bool failed)
{ {
lock (_client) var state = failed ? Mt5ConnectionState.Failed : Mt5ConnectionState.Disconnected;
var message = failed ? "Connection Failed" : "Disconnected";
lock (_locker)
{ {
_client.Disconnect(); if (_connectionState == Mt5ConnectionState.Disconnected
_client.Close(); || _connectionState == Mt5ConnectionState.Failed)
return;
if (_client != null)
{
_client.QuoteAdded -= _client_QuoteAdded;
_client.QuoteRemoved -= _client_QuoteRemoved;
_client.QuoteUpdated -= _client_QuoteUpdated;
_client.ServerDisconnected -= _client_ServerDisconnected;
_client.ServerFailed -= _client_ServerFailed;
if (!failed)
{
_client.Disconnect();
}
_client.Dispose();
_client = null;
}
_connectionState = state;
} }
ConnectionState = Mt5ConnectionState.Disconnected; ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(state, message));
ConnectionStateChanged.FireEvent(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Disconnected, "Disconnected"));
} }
private T SendCommand<T>(Mt5CommandType commandType, ArrayList commandParameters) private T SendCommand<T>(Mt5CommandType commandType, ArrayList commandParameters, Dictionary<string, object> namedParams = null)
{ {
MtResponse response; MtResponse response;
var client = Client;
if (client == null)
{
throw new Exception("No connection");
}
try try
{ {
lock (_client) response = client.SendCommand((int)commandType, commandParameters, namedParams, ExecutorHandle);
{
response = _client.SendCommand((int) commandType, commandParameters);
}
} }
catch (CommunicationException ex) catch (CommunicationException ex)
{ {
throw new Exception(ex.Message, ex); throw new Exception(ex.Message, ex);
} }
var responseValue = response?.GetValue(); if (response == null)
return responseValue != null ? (T) responseValue : default(T); {
throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null");
}
if (response.ErrorCode != 0)
{
throw new ExecutionException((ErrorCode)response.ErrorCode, response.ToString());
}
var responseValue = response.GetValue();
return responseValue != null ? (T)responseValue : default(T);
} }
private T SendRequest<T>(RequestBase request) where T : ResponseBase, new() private T SendRequest<T>(RequestBase request) where T : ResponseBase, new()
@@ -1545,25 +1612,14 @@ namespace MtApi5
}); });
var commandParameters = new ArrayList { serializer }; var commandParameters = new ArrayList { serializer };
MtResponseString res; var res = SendCommand<string>(Mt5CommandType.MtRequest, commandParameters);
try
{
lock (_client)
{
res = (MtResponseString)_client.SendCommand((int)Mt5CommandType.MtRequest, commandParameters);
}
}
catch (CommunicationException ex)
{
throw new Exception(ex.Message, ex);
}
if (res == null) if (res == null)
{ {
throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null"); throw new ExecutionException(ErrorCode.ErrCustom, "Response from MetaTrader is null");
} }
var response = JsonConvert.DeserializeObject<T>(res.Value); var response = JsonConvert.DeserializeObject<T>(res);
if (response.ErrorCode != 0) if (response.ErrorCode != 0)
{ {
throw new ExecutionException((ErrorCode)response.ErrorCode, response.ErrorMessage); throw new ExecutionException((ErrorCode)response.ErrorCode, response.ErrorMessage);
@@ -1573,7 +1629,7 @@ namespace MtApi5
} }
private void mClient_QuoteUpdated(MtQuote quote) private void _client_QuoteUpdated(MtQuote quote)
{ {
if (quote != null) if (quote != null)
{ {
@@ -1581,28 +1637,24 @@ namespace MtApi5
} }
} }
private void mClient_ServerDisconnected(object sender, EventArgs e) private void _client_ServerDisconnected(object sender, EventArgs e)
{ {
ConnectionState = Mt5ConnectionState.Disconnected; Disconnect(false);
ConnectionStateChanged.FireEvent(this
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Disconnected, "MtApi is disconnected"));
} }
private void mClient_ServerFailed(object sender, EventArgs e) private void _client_ServerFailed(object sender, EventArgs e)
{ {
ConnectionState = Mt5ConnectionState.Failed; Disconnect(true);
ConnectionStateChanged.FireEvent(this
, new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, "Failed connection with MtApi"));
} }
private void mClient_QuoteRemoved(MtQuote quote) private void _client_QuoteRemoved(MtQuote quote)
{ {
QuoteRemoved.FireEvent(this, new Mt5QuoteEventArgs(quote.Parse())); QuoteRemoved?.Invoke(this, new Mt5QuoteEventArgs(quote.Parse()));
} }
private void mClient_QuoteAdded(MtQuote quote) private void _client_QuoteAdded(MtQuote quote)
{ {
QuoteAdded.FireEvent(this, new Mt5QuoteEventArgs(quote.Parse())); QuoteAdded?.Invoke(this, new Mt5QuoteEventArgs(quote.Parse()));
} }
private void OnConnected() private void OnConnected()
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.11.0")] [assembly: AssemblyVersion("1.0.12")]
[assembly: AssemblyFileVersion("1.0.11.0")] [assembly: AssemblyFileVersion("1.0.12")]
File diff suppressed because it is too large Load Diff
+437 -270
View File
@@ -33,8 +33,11 @@ namespace TestApiClientUI
comboBox8.DataSource = Enum.GetNames(typeof(MarketInfoModeType)); comboBox8.DataSource = Enum.GetNames(typeof(MarketInfoModeType));
comboBox9.DataSource = Enum.GetNames(typeof(EnumTerminalInfoInteger)); comboBox9.DataSource = Enum.GetNames(typeof(EnumTerminalInfoInteger));
comboBox10.DataSource = Enum.GetNames(typeof(EnumTerminalInfoDouble)); comboBox10.DataSource = Enum.GetNames(typeof(EnumTerminalInfoDouble));
comboBox11.DataSource = Enum.GetNames(typeof(EnumObject));
comboBoxAccountInfoCmd.DataSource = Enum.GetNames(typeof(TradeOperation));
_apiClient.QuoteUpdated += apiClient_QuoteUpdated; _apiClient.QuoteUpdated += apiClient_QuoteUpdated;
_apiClient.QuoteUpdate += _apiClient_QuoteUpdate;
_apiClient.QuoteAdded += apiClient_QuoteAdded; _apiClient.QuoteAdded += apiClient_QuoteAdded;
_apiClient.QuoteRemoved += apiClient_QuoteRemoved; _apiClient.QuoteRemoved += apiClient_QuoteRemoved;
_apiClient.ConnectionStateChanged += apiClient_ConnectionStateChanged; _apiClient.ConnectionStateChanged += apiClient_ConnectionStateChanged;
@@ -47,6 +50,8 @@ namespace TestApiClientUI
comboBox3.SelectedIndex = 0; comboBox3.SelectedIndex = 0;
comboBox4.SelectedIndex = 0; comboBox4.SelectedIndex = 0;
comboBox5.SelectedIndex = 0; comboBox5.SelectedIndex = 0;
comboBox11.SelectedIndex = 0;
comboBoxAccountInfoCmd.SelectedIndex = 0;
_timerTradeMonitor = new TimerTradeMonitor(_apiClient) { Interval = 10000 }; // 10 sec _timerTradeMonitor = new TimerTradeMonitor(_apiClient) { Interval = 10000 }; // 10 sec
_timerTradeMonitor.AvailabilityOrdersChanged += _tradeMonitor_AvailabilityOrdersChanged; _timerTradeMonitor.AvailabilityOrdersChanged += _tradeMonitor_AvailabilityOrdersChanged;
@@ -112,12 +117,18 @@ namespace TestApiClientUI
private void apiClient_QuoteRemoved(object sender, MtQuoteEventArgs e) private void apiClient_QuoteRemoved(object sender, MtQuoteEventArgs e)
{ {
RunOnUiThread(() => RemoveQuote(e.Quote) ); if (e.Quote != null)
{
RunOnUiThread(() => RemoveQuote(e.Quote));
}
} }
private void apiClient_QuoteAdded(object sender, MtQuoteEventArgs e) private void apiClient_QuoteAdded(object sender, MtQuoteEventArgs e)
{ {
RunOnUiThread(() => AddNewQuote(e.Quote)); if (e.Quote != null)
{
RunOnUiThread(() => AddNewQuote(e.Quote));
}
} }
private void _apiClient_OnLastTimeBar(object sender, TimeBarArgs e) private void _apiClient_OnLastTimeBar(object sender, TimeBarArgs e)
@@ -131,72 +142,52 @@ namespace TestApiClientUI
private void apiClient_QuoteUpdated(object sender, string symbol, double bid, double ask) private void apiClient_QuoteUpdated(object sender, string symbol, double bid, double ask)
{ {
Console.WriteLine(@"Quote: Symbol = {0}, Bid = {1}, Ask = {2}", symbol, bid, ask); Console.WriteLine(@"Quote: Symbol = {0}, Bid = {1}, Ask = {2}", symbol, bid, ask);
}
private void _apiClient_QuoteUpdate(object sender, MtQuoteEventArgs e)
{
//if UI of quite is busy we are skipping this update //if UI of quite is busy we are skipping this update
if (_isUiQuoteUpdateReady) if (_isUiQuoteUpdateReady)
{ {
RunOnUiThread(() => ChangeQuote(symbol, bid, ask)); RunOnUiThread(() => ChangeQuote(e.Quote));
} }
} }
private void AddNewQuote(MtQuote quote) private void AddNewQuote(MtQuote quote)
{ {
if (quote == null) var key = quote.ExpertHandle.ToString();
return;
if (string.IsNullOrEmpty(quote.Instrument) == false if (listViewQuotes.Items.ContainsKey(key) == false)
&& listViewQuotes.Items.ContainsKey(quote.Instrument) == false)
{ {
var item = new ListViewItem(quote.Instrument) { Name = quote.Instrument }; var item = new ListViewItem(quote.Instrument) { Name = key };
item.SubItems.Add(quote.Bid.ToString(CultureInfo.CurrentCulture)); item.SubItems.Add(quote.Bid.ToString(CultureInfo.CurrentCulture));
item.SubItems.Add(quote.Ask.ToString(CultureInfo.CurrentCulture)); item.SubItems.Add(quote.Ask.ToString(CultureInfo.CurrentCulture));
item.SubItems.Add("1"); item.SubItems.Add(key);
listViewQuotes.Items.Add(item); listViewQuotes.Items.Add(item);
} }
else
{
var item = listViewQuotes.Items[quote.Instrument];
int feedCount;
int.TryParse(item.SubItems[3].Text, out feedCount);
feedCount++;
item.SubItems[3].Text = feedCount.ToString();
}
} }
private void RemoveQuote(MtQuote quote) private void RemoveQuote(MtQuote quote)
{ {
if (quote == null) var key = quote.ExpertHandle.ToString();
return;
if (string.IsNullOrEmpty(quote.Instrument) == false if (listViewQuotes.Items.ContainsKey(key))
&& listViewQuotes.Items.ContainsKey(quote.Instrument))
{ {
var item = listViewQuotes.Items[quote.Instrument]; listViewQuotes.Items.RemoveByKey(key);
int feedCount;
int.TryParse(item.SubItems[3].Text, out feedCount);
feedCount--;
if (feedCount <= 0)
{
listViewQuotes.Items.RemoveByKey(quote.Instrument);
}
else
{
item.SubItems[3].Text = feedCount.ToString();
}
} }
} }
private void ChangeQuote(string symbol, double bid, double ask) private void ChangeQuote(MtQuote quote)
{ {
_isUiQuoteUpdateReady = false; _isUiQuoteUpdateReady = false;
if (string.IsNullOrEmpty(symbol) == false) var key = quote.ExpertHandle.ToString();
if (listViewQuotes.Items.ContainsKey(key))
{ {
if (listViewQuotes.Items.ContainsKey(symbol)) var item = listViewQuotes.Items[key];
{ item.SubItems[1].Text = quote.Bid.ToString(CultureInfo.CurrentCulture);
var item = listViewQuotes.Items[symbol]; item.SubItems[2].Text = quote.Ask.ToString(CultureInfo.CurrentCulture);
item.SubItems[1].Text = bid.ToString(CultureInfo.CurrentCulture);
item.SubItems[2].Text = ask.ToString(CultureInfo.CurrentCulture);
}
} }
_isUiQuoteUpdateReady = true; _isUiQuoteUpdateReady = true;
@@ -256,6 +247,12 @@ namespace TestApiClientUI
textBoxOrderSymbol.Text = listViewQuotes.SelectedItems[0].Text; textBoxOrderSymbol.Text = listViewQuotes.SelectedItems[0].Text;
txtMarketInfoSymbol.Text = listViewQuotes.SelectedItems[0].Text; txtMarketInfoSymbol.Text = listViewQuotes.SelectedItems[0].Text;
textBoxSelectedSymbol.Text = listViewQuotes.SelectedItems[0].Text; textBoxSelectedSymbol.Text = listViewQuotes.SelectedItems[0].Text;
textBoxAccountInfoSymbol.Text = listViewQuotes.SelectedItems[0].Text;
if (checkBox2.Checked)
{
_apiClient.ExecutorHandle = int.Parse(listViewQuotes.SelectedItems[0].SubItems[3].Text);
}
} }
} }
@@ -526,206 +523,6 @@ namespace TestApiClientUI
}); });
} }
private void button3_Click(object sender, EventArgs e)
{
switch (comboBoxStatusCommand.SelectedIndex)
{
case 0:
{
var result = _apiClient.GetLastError();
PrintLog($"GetLastError result: {result}");
}
break;
case 1:
{
var result = _apiClient.IsConnected();
PrintLog($"IsConnected result: {result}");
}
break;
case 2:
{
var result = _apiClient.IsDemo();
PrintLog($"IsDemo result: {result}");
}
break;
case 3:
{
var result = _apiClient.IsDllsAllowed();
PrintLog($"IsDllsAllowed result: {result}");
}
break;
case 4:
{
var result = _apiClient.IsExpertEnabled();
PrintLog($"IsExpertEnabled result: {result}");
}
break;
case 5:
{
var result = _apiClient.IsLibrariesAllowed();
PrintLog($"IsLibrariesAllowed result: {result}");
}
break;
case 6:
{
var result = _apiClient.IsOptimization();
PrintLog($"IsOptimization result: {result}");
}
break;
case 7:
{
var result = _apiClient.IsStopped();
PrintLog($"IsStopped result: {result}");
}
break;
case 8:
{
var result = _apiClient.IsTesting();
PrintLog($"IsTesting result: {result}");
}
break;
case 9:
{
var result = _apiClient.IsTradeAllowed();
PrintLog($"IsTradeAllowed result: {result}");
}
break;
case 10:
{
var result = _apiClient.IsTradeContextBusy();
PrintLog($"IsTradeContextBusy result: {result}");
}
break;
case 11:
{
var result = _apiClient.IsVisualMode();
PrintLog($"IsVisualMode result: {result}");
}
break;
case 12:
{
var result = _apiClient.UninitializeReason();
PrintLog($"UninitializeReason result: {result}");
}
break;
case 13:
{
int errorCode;
int.TryParse(textBoxErrorCode.Text, out errorCode);
var result = _apiClient.ErrorDescription(errorCode);
PrintLog($"ErrorDescription result: {result}");
}
break;
default:
return;
}
}
private void button4_Click(object sender, EventArgs e)
{
switch (listBoxAccountInfo.SelectedIndex)
{
case 0:
{
var result = _apiClient.AccountBalance();
PrintLog($"AccountBalance result: {result}");
}
break;
case 1:
{
var result = _apiClient.AccountCredit();
PrintLog($"AccountCredit result: {result}");
}
break;
case 2:
{
var result = _apiClient.AccountCompany();
PrintLog($"AccountCompany result: {result}");
}
break;
case 3:
{
var result = _apiClient.AccountCurrency();
PrintLog($"AccountCurrency result: {result}");
}
break;
case 4:
{
var result = _apiClient.AccountEquity();
PrintLog($"AccountEquity result: {result}");
}
break;
case 5:
{
var result = _apiClient.AccountFreeMargin();
PrintLog($"AccountFreeMargin result: {result}");
}
break;
case 6:
{
var result = _apiClient.AccountFreeMarginCheck(textBoxAccountInfoSymbol.Text, (TradeOperation)comboBoxAccountInfoCmd.SelectedIndex, int.Parse(textBoxAccountInfoVolume.Text));
PrintLog($"AccountFreeMarginCheck result: {result}");
}
break;
case 7:
{
var result = _apiClient.AccountFreeMarginMode();
PrintLog($"AccountFreeMarginMode result: {result}");
}
break;
case 8:
{
var result = _apiClient.AccountLeverage();
PrintLog($"AccountLeverage result: {result}");
}
break;
case 9:
{
var result = _apiClient.AccountMargin();
PrintLog($"AccountMargin result: {result}");
}
break;
case 10:
{
var result = _apiClient.AccountName();
PrintLog($"AccountName result: {result}");
}
break;
case 11:
{
var result = _apiClient.AccountNumber();
PrintLog($"AccountNumber result: {result}");
}
break;
case 12:
{
var result = _apiClient.AccountProfit();
PrintLog($"AccountProfit result: {result}");
}
break;
case 13:
{
var result = _apiClient.AccountServer();
PrintLog($"AccountServer result: {result}");
}
break;
case 14:
{
var result = _apiClient.AccountStopoutLevel();
PrintLog($"AccountStopoutLevel result: {result}");
}
break;
case 15:
{
var result = _apiClient.AccountStopoutMode();
PrintLog($"AccountStopoutMode result: {result}");
}
break;
default:
return;
}
}
//MarketInfo //MarketInfo
private async void button5_Click(object sender, EventArgs e) private async void button5_Click(object sender, EventArgs e)
{ {
@@ -753,13 +550,13 @@ namespace TestApiClientUI
Console.WriteLine($"Finished time: {DateTime.Now}"); Console.WriteLine($"Finished time: {DateTime.Now}");
using (var file = new System.IO.StreamWriter($@"{System.IO.Path.GetTempPath()}\MtApi\test.txt")) //using (var file = new System.IO.StreamWriter($@"{System.IO.Path.GetTempPath()}\MtApi\test.txt"))
{ //{
foreach (var value in openPriceList) // foreach (var value in openPriceList)
{ // {
file.WriteLine(value); // file.WriteLine(value);
} // }
} //}
} }
private void button7_Click(object sender, EventArgs e) private void button7_Click(object sender, EventArgs e)
@@ -832,9 +629,9 @@ namespace TestApiClientUI
listBoxEventLog.Items.Clear(); listBoxEventLog.Items.Clear();
} }
private async Task<TResult> Execute<TResult>(Func<TResult> func) private Task<TResult> Execute<TResult>(Func<TResult> func)
{ {
return await Task.Factory.StartNew(() => return Task.Factory.StartNew(() =>
{ {
var result = default(TResult); var result = default(TResult);
try try
@@ -854,9 +651,30 @@ namespace TestApiClientUI
}); });
} }
private Task Execute(Action action)
{
return Task.Factory.StartNew(() =>
{
try
{
action();
}
catch (MtConnectionException ex)
{
PrintLog("MtExecutionException: " + ex.Message);
}
catch (MtExecutionException ex)
{
PrintLog("MtExecutionException: " + ex.Message + "; ErrorCode = " + ex.ErrorCode);
}
});
}
//OrderSend //OrderSend
private async void button1_Click(object sender, EventArgs e) private async void button1_Click(object sender, EventArgs e)
{ {
var ticket = -1;
var symbol = textBoxOrderSymbol.Text; var symbol = textBoxOrderSymbol.Text;
var cmd = (TradeOperation) comboBoxOrderCommand.SelectedIndex; var cmd = (TradeOperation) comboBoxOrderCommand.SelectedIndex;
@@ -877,28 +695,43 @@ namespace TestApiClientUI
var comment = textBoxOrderComment.Text; var comment = textBoxOrderComment.Text;
int magic; if (string.IsNullOrEmpty(comment))
int.TryParse(textBoxOrderMagic.Text, out magic);
var expiration = DateTime.Now;
Color arrowColor;
switch (comboBoxOrderColor.SelectedIndex)
{ {
case 0: ticket = await Execute(() => _apiClient.OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit));
arrowColor = Color.Green; }
break; else
case 1: {
arrowColor = Color.Blue; int magic;
break; if (!int.TryParse(textBoxOrderMagic.Text, out magic))
case 2: {
arrowColor = Color.Red; ticket = await Execute(() => _apiClient.OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment));
break; }
default: else
return; {
if (comboBoxOrderColor.SelectedIndex < 0 || comboBoxOrderColor.SelectedIndex > 2)
{
ticket = await Execute(() => _apiClient.OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic));
}
else
{
var expiration = DateTime.Now.AddDays(1);
Color arrowColor = Color.White;
switch (comboBoxOrderColor.SelectedIndex)
{
case 0:
arrowColor = Color.Green;
break;
case 1:
arrowColor = Color.Blue;
break;
case 2:
arrowColor = Color.Red;
break;
}
ticket = await Execute(() => _apiClient.OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrowColor));
}
}
} }
var ticket = await Execute(() => _apiClient.OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrowColor));
PrintLog($"Sended order result: ticket = {ticket}"); PrintLog($"Sended order result: ticket = {ticket}");
} }
@@ -1286,5 +1119,339 @@ namespace TestApiClientUI
var result = await Execute(() => _apiClient.TerminalInfoDouble(propId)); var result = await Execute(() => _apiClient.TerminalInfoDouble(propId));
PrintLog($"TerminalInfoDouble: result = {result}"); PrintLog($"TerminalInfoDouble: result = {result}");
} }
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
var checkbox = sender as CheckBox;
if (checkbox == null)
return;
int expertHandle = 0;
if (checkbox.Checked)
{
if (listViewQuotes.SelectedItems.Count > 0)
{
expertHandle = int.Parse(listViewQuotes.SelectedItems[0].SubItems[3].Text);
}
}
_apiClient.ExecutorHandle = expertHandle;
}
//GetLastError
private async void button40_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.GetLastError);
PrintLog($"GetLastError: result = {result}");
RunOnUiThread(() => { textBoxErrorCode.Text = result.ToString(); });
}
//ErrorDescription
private async void button39_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBoxErrorCode.Text))
{
MessageBox.Show(@"Error code is not defined!");
textBoxErrorCode.Focus();
return;
}
int errorCode;
if (int.TryParse(textBoxErrorCode.Text, out errorCode) == false)
{
MessageBox.Show(@"Failed to parse error code!");
textBoxErrorCode.Focus();
return;
}
var result = await Execute(() => _apiClient.ErrorDescription(errorCode));
PrintLog($"ErrorDescription: code = {errorCode}, description = {result}");
}
//IsConnected
private async void button41_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsConnected);
PrintLog($"IsConnected: result = {result}");
}
//IsDemo
private async void button42_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsDemo);
PrintLog($"IsDemo: result = {result}");
}
//IsDllsAllowed
private async void button43_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsDllsAllowed);
PrintLog($"IsDllsAllowed: result = {result}");
}
//IsExpertEnabled
private async void button44_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsExpertEnabled);
PrintLog($"IsExpertEnabled: result = {result}");
}
//IsLibrariesAllowed
private async void button45_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsLibrariesAllowed);
PrintLog($"IsLibrariesAllowed: result = {result}");
}
//IsOptimization
private async void button46_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsOptimization);
PrintLog($"IsOptimization: result = {result}");
}
//IsStopped
private async void button47_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsStopped);
PrintLog($"IsStopped: result = {result}");
}
//IsTesting
private async void button48_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsTesting);
PrintLog($"IsTesting: result = {result}");
}
//IsTradeAllowed
private async void button49_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsTradeAllowed);
PrintLog($"IsTradeAllowed: result = {result}");
}
//IsTradeContextBusy
private async void button50_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsTradeContextBusy);
PrintLog($"IsTradeContextBusy: result = {result}");
}
//IsVisualMode
private async void button51_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.IsVisualMode);
PrintLog($"IsVisualMode: result = {result}");
}
//UninitializeReason
private async void button52_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.UninitializeReason);
PrintLog($"UninitializeReason: result = {result}");
}
//AccountBalance
private async void button3_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountBalance);
PrintLog($"AccountBalance result: {result}");
}
//AccountCredit
private async void button53_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountCredit);
PrintLog($"AccountCredit result: {result}");
}
//AccountCompany
private async void button54_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountCompany);
PrintLog($"AccountCompany result: {result}");
}
//AccountCurrency
private async void button55_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountCurrency);
PrintLog($"AccountCurrency result: {result}");
}
//AccountEquity
private async void button56_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountEquity);
PrintLog($"AccountEquity result: {result}");
}
//AccountFreeMargin
private async void button57_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountFreeMargin);
PrintLog($"AccountFreeMargin result: {result}");
}
//AccountFreeMarginCheck
private async void button58_Click(object sender, EventArgs e)
{
var symbol = textBoxAccountInfoSymbol.Text;
if (string.IsNullOrEmpty(symbol))
{
MessageBox.Show(@"Symbol is not defined!");
textBoxAccountInfoSymbol.Focus();
return;
}
double volume;
if (double.TryParse(textBoxAccountInfoVolume.Text, out volume) == false)
{
MessageBox.Show(@"Failed to parse volume value!");
textBoxAccountInfoVolume.Focus();
return;
}
TradeOperation cmd;
Enum.TryParse(comboBoxAccountInfoCmd.Text, out cmd);
var result = await Execute(() => _apiClient.AccountFreeMarginCheck(symbol, cmd, volume));
PrintLog($"AccountFreeMarginCheck result: {result}");
}
//AccountFreeMarginMode
private async void button59_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountFreeMarginMode);
PrintLog($"AccountFreeMarginMode result: {result}");
}
//AccountLeverage
private async void button60_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountLeverage);
PrintLog($"AccountLeverage result: {result}");
}
//AccountMargin
private async void button61_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountMargin);
PrintLog($"AccountMargin result: {result}");
}
//AccountName
private async void button62_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountName);
PrintLog($"AccountName result: {result}");
}
//AccountNumber
private async void button63_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountNumber);
PrintLog($"AccountNumber result: {result}");
}
//AccountProfit
private async void button64_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountProfit);
PrintLog($"AccountProfit result: {result}");
}
//AccountServer
private async void button65_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountServer);
PrintLog($"AccountServer result: {result}");
}
//AccountStopoutLevel
private async void button66_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountStopoutLevel);
PrintLog($"AccountStopoutLevel result: {result}");
}
//AccountStopoutMode
private async void button67_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.AccountStopoutMode);
PrintLog($"AccountStopoutMode result: {result}");
}
//CharID
private async void button37_Click(object sender, EventArgs e)
{
var result = await Execute(_apiClient.ChartId);
PrintLog($"CharID: result = {result}");
RunOnUiThread(() => textBoxChartId.Text = result.ToString());
}
//ChartRedraw
private async void button38_Click(object sender, EventArgs e)
{
await Execute(() => _apiClient.ChartRedraw());
PrintLog($"ChartRedraw: called.");
}
//ObjectCreate
private async void button4_Click(object sender, EventArgs e)
{
const long chartId = 0;
const string objectName = "label_object";
EnumObject objectType;
Enum.TryParse(comboBox11.Text, out objectType);
var result = await Execute(() => _apiClient.ObjectCreate(chartId, objectName, objectType, 0, null, 0));
PrintLog($"ObjectCreate result: {result}");
}
//ObjectName
private async void button68_Click(object sender, EventArgs e)
{
const long chartId = 0;
const int objectIndex = 0;
var result = await Execute(() => _apiClient.ObjectName(chartId, objectIndex));
PrintLog($"ObjectName result: {result}");
}
private void button69_Click(object sender, EventArgs e)
{
_apiClient.UnlockTicks();
}
private async void button70_Click(object sender, EventArgs e)
{
var login = textBoxAccountLogin.Text;
var password = textBoxAccountPassword.Text;
var host = textBoxAccountHost.Text;
if (string.IsNullOrEmpty(login))
{
MessageBox.Show(@"Login is not defined!", @"Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
textBoxAccountLogin.Focus();
return;
}
if (string.IsNullOrEmpty(password))
{
MessageBox.Show(@"Password is not defined!", @"Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
textBoxAccountPassword.Focus();
return;
}
if (string.IsNullOrEmpty(host))
{
MessageBox.Show(@"Host is not defined!", @"Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
textBoxAccountHost.Focus();
return;
}
var result = await Execute(() => _apiClient.ChangeAccount(login, password, host));
PrintLog($"ChangeAccount result: {result}");
}
} }
} }
+2 -2
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup> </startup>
</configuration> </configuration>
@@ -1,7 +1,7 @@
'------------------------------------------------------------------------------ '------------------------------------------------------------------------------
' <auto-generated> ' <auto-generated>
' This code was generated by a tool. ' This code was generated by a tool.
' Runtime Version:4.0.30319.17929 ' Runtime Version:4.0.30319.42000
' '
' Changes to this file may cause incorrect behavior and will be lost if ' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated. ' the code is regenerated.
@@ -1,7 +1,7 @@
'------------------------------------------------------------------------------ '------------------------------------------------------------------------------
' <auto-generated> ' <auto-generated>
' This code was generated by a tool. ' This code was generated by a tool.
' Runtime Version:4.0.30319.17929 ' Runtime Version:4.0.30319.42000
' '
' Changes to this file may cause incorrect behavior and will be lost if ' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated. ' the code is regenerated.
@@ -11,6 +11,7 @@
Option Strict On Option Strict On
Option Explicit On Option Explicit On
Imports System
Namespace My.Resources Namespace My.Resources
@@ -21,10 +22,10 @@ Namespace My.Resources
'''<summary> '''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc. ''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary> '''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _ <Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _ Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _ Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _ Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager Private resourceMan As Global.System.Resources.ResourceManager
@@ -34,7 +35,7 @@ Namespace My.Resources
'''<summary> '''<summary>
''' Returns the cached ResourceManager instance used by this class. ''' Returns the cached ResourceManager instance used by this class.
'''</summary> '''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _ <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get Get
If Object.ReferenceEquals(resourceMan, Nothing) Then If Object.ReferenceEquals(resourceMan, Nothing) Then
@@ -49,12 +50,12 @@ Namespace My.Resources
''' Overrides the current thread's CurrentUICulture property for all ''' Overrides the current thread's CurrentUICulture property for all
''' resource lookups using this strongly typed resource class. ''' resource lookups using this strongly typed resource class.
'''</summary> '''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _ <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo Friend Property Culture() As Global.System.Globalization.CultureInfo
Get Get
Return resourceCulture Return resourceCulture
End Get End Get
Set(ByVal value As Global.System.Globalization.CultureInfo) Set
resourceCulture = value resourceCulture = value
End Set End Set
End Property End Property
@@ -1,7 +1,7 @@
'------------------------------------------------------------------------------ '------------------------------------------------------------------------------
' <auto-generated> ' <auto-generated>
' This code was generated by a tool. ' This code was generated by a tool.
' Runtime Version:4.0.30319.17929 ' Runtime Version:4.0.30319.42000
' '
' Changes to this file may cause incorrect behavior and will be lost if ' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated. ' the code is regenerated.
@@ -14,26 +14,26 @@ Option Explicit On
Namespace My Namespace My
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _ <Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0"), _ Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0"), _
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _ Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Partial Friend NotInheritable Class MySettings Partial Friend NotInheritable Class MySettings
Inherits Global.System.Configuration.ApplicationSettingsBase Inherits Global.System.Configuration.ApplicationSettingsBase
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings)
#Region "My.Settings Auto-Save Functionality" #Region "My.Settings Auto-Save Functionality"
#If _MyType = "WindowsForms" Then #If _MyType = "WindowsForms" Then
Private Shared addedHandler As Boolean Private Shared addedHandler As Boolean
Private Shared addedHandlerLockObject As New Object Private Shared addedHandlerLockObject As New Object
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _ <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
If My.Application.SaveMySettingsOnExit Then If My.Application.SaveMySettingsOnExit Then
My.Settings.Save() My.Settings.Save()
End If End If
End Sub End Sub
#End If #End If
#End Region #End Region
@@ -41,14 +41,14 @@ Namespace My
Get Get
#If _MyType = "WindowsForms" Then #If _MyType = "WindowsForms" Then
If Not addedHandler Then If Not addedHandler Then
SyncLock addedHandlerLockObject SyncLock addedHandlerLockObject
If Not addedHandler Then If Not addedHandler Then
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
addedHandler = True addedHandler = True
End If End If
End SyncLock End SyncLock
End If End If
#End If #End If
Return defaultInstance Return defaultInstance
End Get End Get
@@ -13,8 +13,9 @@
<AssemblyName>TestMtApi</AssemblyName> <AssemblyName>TestMtApi</AssemblyName>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<MyType>WindowsForms</MyType> <MyType>WindowsForms</MyType>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile>
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
@@ -40,6 +41,7 @@
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>TestMtApi.xml</DocumentationFile> <DocumentationFile>TestMtApi.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn> <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
@@ -50,6 +52,7 @@
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DocumentationFile>TestMtApi.xml</DocumentationFile> <DocumentationFile>TestMtApi.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn> <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<OptionExplicit>On</OptionExplicit> <OptionExplicit>On</OptionExplicit>
@@ -67,7 +70,6 @@
<ApplicationManifest>My Project\app.manifest</ApplicationManifest> <ApplicationManifest>My Project\app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="MtApi, Version=1.0.7.0, Culture=neutral, processorArchitecture=MSIL" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Deployment" /> <Reference Include="System.Deployment" />
@@ -126,6 +128,7 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" />
<None Include="My Project\app.manifest" /> <None Include="My Project\app.manifest" />
<None Include="My Project\Application.myapp"> <None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator> <Generator>MyApplicationCodeGenerator</Generator>
@@ -159,6 +162,12 @@
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\MtApi\MtApi.csproj">
<Project>{7a76c388-a8fb-4949-8170-24d4742e934e}</Project>
<Name>MtApi</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+163
View File
@@ -0,0 +1,163 @@
//+----------------------------------------------------------------------------+
//| mql4-auth.mqh |
//+----------------------------------------------------------------------------+
//| Built by Sergey Lukin |
//| contact@sergeylukin.com |
//+----------------------------------------------------------------------------+
#include <WinUser32.mqh>
#import "user32.dll"
int GetAncestor(int,int);
int GetLastActivePopup(int);
int GetDlgItem(int,int);
int GetParent(int hWnd);
#import
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool loginDialogIsOpen()
{
int hwnd=WindowHandle(Symbol(),Period());
int hMetaTrader,hLoginDialog=0;
// Retrieve Terminal Window Handler
while(!IsStopped())
{
hwnd=GetParent(hwnd);
if(hwnd==0) break;
hMetaTrader=hwnd;
}
hLoginDialog=GetLastActivePopup(hMetaTrader);
if(hLoginDialog!=0)
{
return(true);
} else {
return(false);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void closeLoginDialog()
{
int hwnd=WindowHandle(Symbol(),Period());
int hMetaTrader,hLoginDialog=0,hCancelButton=0;
// Retrieve Terminal Window Handler
while(!IsStopped())
{
hwnd=GetParent(hwnd);
if(hwnd==0) break;
hMetaTrader=hwnd;
}
Sleep(60);
hLoginDialog=GetLastActivePopup(hMetaTrader);
if(hLoginDialog!=0)
{
hCancelButton=GetDlgItem(hLoginDialog,0x2);
if(hCancelButton!=0)
{
// Click "Cancel" button in Login Dialog
PostMessageA(hCancelButton,0x00F5,0,0);
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool auth(string login,string passwd,string server)
{
datetime s=TimeLocal();
int h = 0, e = 0, a = GetAncestor(WindowHandle(Symbol(), NULL), 2);
int i = 0;
PostMessageA(a,WM_COMMAND,35429,0);
while(e==0)
{
// Give us up to a minute to find the Login dialog
if(TimeLocal()-s>60)
{
return(false);
}
h=GetLastActivePopup(a);
// Select login field
e=GetDlgItem(h,0x49d);
Sleep(1);
}
// Press DELETE key many times in login field to remove current value
for(i=1; i<=100; i++)
{
PostMessageA(e,WM_KEYDOWN,0x2E,1);
}
// Iterate over characters in "login" string and pass them to login field one by one
char login_chars[];
string2CharsArray(login,login_chars);
for(i=0; i<ArraySize(login_chars); i++)
{
PostMessageA(e,WM_CHAR,login_chars[i],0);
}
// Select password field
e=GetDlgItem(h,0x4c4);
// Press DELETE key many times in password field to remove current value
for(i=1; i<=100; i++)
{
PostMessageA(e,WM_KEYDOWN,0x2E,1);
}
// Iterate over characters in "passwd" string and pass them to password field one by one
char password_chars[];
string2CharsArray(passwd,password_chars);
for(i=0; i<ArraySize(password_chars); i++)
{
PostMessageA(e,WM_CHAR,password_chars[i],0);
}
// Select server field
e=GetDlgItem(h,0x50d);
// Press DELETE key many times in server field to remove current value
for(i=1; i<=100; i++)
{
PostMessageA(e,WM_KEYDOWN,0x2E,1);
}
// Iterate over characters in "server" string and pass them to server field one by one
char server_chars[];
string2CharsArray(server,server_chars);
for(i=0; i<ArraySize(server_chars); i++)
{
PostMessageA(e,WM_CHAR,server_chars[i],0);
}
Sleep(2*1000);
// Press submit button
e=GetDlgItem(h,0x1);
SendMessageA(e,0x00F5,0,0);
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/*
* Iterates over string and puts each character code in array
*/
void string2CharsArray(string myString,char &chars[])
{
int cnt=StringLen(myString);
ArrayResize(chars,cnt);
for(int i=0; i<cnt; i++)
{
chars[i]=StringGetChar(myString,i);
}
}
//+------------------------------------------------------------------+