diff --git a/OLAP/CSVcube.mqh b/OLAP/CSVcube.mqh new file mode 100644 index 0000000..e34891a Binary files /dev/null and b/OLAP/CSVcube.mqh differ diff --git a/OLAP/GUI/OLAPGUI.mqh b/OLAP/GUI/OLAPGUI.mqh new file mode 100644 index 0000000..ba8f604 Binary files /dev/null and b/OLAP/GUI/OLAPGUI.mqh differ diff --git a/OLAP/GUI/OLAPGUI_Opts.mqh b/OLAP/GUI/OLAPGUI_Opts.mqh new file mode 100644 index 0000000..d52be70 Binary files /dev/null and b/OLAP/GUI/OLAPGUI_Opts.mqh differ diff --git a/OLAP/GUI/OLAPGUI_Trades.mqh b/OLAP/GUI/OLAPGUI_Trades.mqh new file mode 100644 index 0000000..c91d56c Binary files /dev/null and b/OLAP/GUI/OLAPGUI_Trades.mqh differ diff --git a/OLAP/GroupReportInputs.mqh b/OLAP/GroupReportInputs.mqh new file mode 100644 index 0000000..520108f Binary files /dev/null and b/OLAP/GroupReportInputs.mqh differ diff --git a/OLAP/HTMLcube.mqh b/OLAP/HTMLcube.mqh new file mode 100644 index 0000000..b731550 Binary files /dev/null and b/OLAP/HTMLcube.mqh differ diff --git a/OLAP/OLAPCommon.mqh b/OLAP/OLAPCommon.mqh new file mode 100644 index 0000000..1b7d589 Binary files /dev/null and b/OLAP/OLAPCommon.mqh differ diff --git a/OLAP/OLAPOpts.mqh b/OLAP/OLAPOpts.mqh new file mode 100644 index 0000000..57be27e Binary files /dev/null and b/OLAP/OLAPOpts.mqh differ diff --git a/OLAP/OLAPQuotes.mqh b/OLAP/OLAPQuotes.mqh new file mode 100644 index 0000000..3957a0d Binary files /dev/null and b/OLAP/OLAPQuotes.mqh differ diff --git a/OLAP/OLAPTrades.mqh b/OLAP/OLAPTrades.mqh new file mode 100644 index 0000000..3a180e2 Binary files /dev/null and b/OLAP/OLAPTrades.mqh differ diff --git a/OLAP/OLAPTradesCustom.mqh b/OLAP/OLAPTradesCustom.mqh new file mode 100644 index 0000000..2f0df83 Binary files /dev/null and b/OLAP/OLAPTradesCustom.mqh differ diff --git a/OLAP/PairArray.mqh b/OLAP/PairArray.mqh new file mode 100644 index 0000000..d19e73a Binary files /dev/null and b/OLAP/PairArray.mqh differ diff --git a/OLAP/ReportCubeBase.mqh b/OLAP/ReportCubeBase.mqh new file mode 100644 index 0000000..649ab89 Binary files /dev/null and b/OLAP/ReportCubeBase.mqh differ diff --git a/OLAP/TSTcube.mqh b/OLAP/TSTcube.mqh new file mode 100644 index 0000000..98b8677 Binary files /dev/null and b/OLAP/TSTcube.mqh differ diff --git a/OpenCL/Element.mqh b/OpenCL/Element.mqh new file mode 100644 index 0000000..be8d467 --- /dev/null +++ b/OpenCL/Element.mqh @@ -0,0 +1,27 @@ +//+------------------------------------------------------------------+ +//| Element.mqh | +//| Copyright 2023, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2023, MetaQuotes Ltd." +#property link "https://www.mql5.com" +//+------------------------------------------------------------------+ +//| defines | +//+------------------------------------------------------------------+ +// #define MacrosHello "Hello, world!" +// #define MacrosYear 2010 +//+------------------------------------------------------------------+ +//| DLL imports | +//+------------------------------------------------------------------+ +// #import "user32.dll" +// int SendMessageA(int hWnd,int Msg,int wParam,int lParam); +// #import "my_expert.dll" +// int ExpertRecalculate(int wParam,int lParam); +// #import +//+------------------------------------------------------------------+ +//| EX5 imports | +//+------------------------------------------------------------------+ +// #import "stdlib.ex5" +// string ErrorDescription(int error_code); +// #import +//+------------------------------------------------------------------+ diff --git a/OpenCL/OpenCL.mqh b/OpenCL/OpenCL.mqh new file mode 100644 index 0000000..cb04159 --- /dev/null +++ b/OpenCL/OpenCL.mqh @@ -0,0 +1,659 @@ +//+------------------------------------------------------------------+ +//| OpenCL.mqh | +//| Copyright 2000-2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Class for working with OpenCL | +//+------------------------------------------------------------------+ +class COpenCL + { +protected: + int m_context; + int m_program; + //--- kernel + string m_kernel_names[]; + int m_kernels[]; + int m_kernels_total; + //--- buffers + int m_buffers[]; + int m_buffers_total; + string m_device_extensions; + bool m_support_cl_khr_fp64; +public: + //--- constructor/destructor + COpenCL(); + ~COpenCL(); + //--- get handles + int GetContext(void) const { return(m_context); } + int GetProgram(void) const { return(m_program); } + int GetKernel(const int kernel_index) const; + string GetKernelName(const int kernel_index) const; + //--- global and local memory size + bool GetGlobalMemorySize(long &global_memory_size); + bool GetLocalMemorySize(long &local_memory_size); + //--- maximal workgroup size + bool GetMaxWorkgroupSize(long &max_workgroup_size); + //--- check support working with double + bool SupportDouble(void) const { return(m_support_cl_khr_fp64); } + //--- initialization and shutdown + bool Initialize(const string program,const bool show_log=true); + bool ContextCreate(const int device=CL_USE_ANY); + bool ProgramCreate(const string program,const bool show_log=true); + void ContextClean(void); + void Shutdown(void); + //--- set buffers/kernels count + bool SetBuffersCount(const int total_buffers); + bool SetKernelsCount(const int total_kernels); + //--- kernel operations + bool KernelCreate(const int kernel_index,const string kernel_name); + bool KernelFree(const int kernel_index); + //--- device and kernel info + long GetDeviceInfo(const int prop); + long GetDeviceInfoInteger(ENUM_OPENCL_PROPERTY_INTEGER prop); + long GetKernelInfoInteger(const int kernel_index,ENUM_OPENCL_PROPERTY_INTEGER prop); + //--- buffer operations + bool BufferCreate(const int buffer_index,const uint size_in_bytes,const uint flags); + bool BufferFree(const int buffer_index); + template + bool BufferFromArray(const int buffer_index,T &data[],const uint data_array_offset,const uint data_array_count,const uint flags); + template + bool BufferFromMatrix(const int buffer_index,matrix &data,const uint flags); + template + bool BufferFromVector(const int buffer_index,vector &data,const uint flags); + template + bool BufferToMatrix(const int buffer_index,matrix &data,const ulong rows=-1,const ulong cols=-1); + template + bool BufferToVector(const int buffer_index,vector &data,const ulong size=-1); + template + bool BufferRead(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count); + template + bool BufferWrite(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count); + //--- set kernel arguments + template + bool SetArgument(const int kernel_index,const int arg_index,T value); + bool SetArgumentBuffer(const int kernel_index,const int arg_index,const int buffer_index); + bool SetArgumentLocalMemory(const int kernel_index,const int arg_index,const int local_memory_size); + //--- kernel execution + bool Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[]); + bool Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[],const uint &local_work_size[]); + }; +//+------------------------------------------------------------------+ +//| COpenCL class constructor | +//+------------------------------------------------------------------+ +COpenCL::COpenCL() + { + m_context=INVALID_HANDLE; + m_program=INVALID_HANDLE; + m_buffers_total=0; + m_kernels_total=0; + m_device_extensions=""; + m_support_cl_khr_fp64=false; + } +//+------------------------------------------------------------------+ +//| COpenCL class destructor | +//+------------------------------------------------------------------+ +COpenCL::~COpenCL() + { + Shutdown(); + } +//+------------------------------------------------------------------+ +//| GetKernel | +//+------------------------------------------------------------------+ +int COpenCL::GetKernel(const int kernel_index) const + { + if(m_kernels_total<=0 || kernel_index<0 || kernel_index>=m_kernels_total) + return(INVALID_HANDLE); +//--- + return m_kernels[kernel_index]; + } +//+------------------------------------------------------------------+ +//| GetKernelName | +//+------------------------------------------------------------------+ +string COpenCL::GetKernelName(const int kernel_index) const + { + if(m_kernels_total<=0 || kernel_index<0 || kernel_index>=m_kernels_total) + return(""); +//--- + return m_kernel_names[kernel_index]; + } +//+------------------------------------------------------------------+ +//| GetGlobalMemorySize | +//+------------------------------------------------------------------+ +bool COpenCL::GetGlobalMemorySize(long &global_memory_size) + { + if(m_context==INVALID_HANDLE) + return(false); + +//--- get global memory size + global_memory_size=CLGetInfoInteger(m_context,CL_DEVICE_GLOBAL_MEM_SIZE); + if(global_memory_size==-1) + return(false); +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| GetLocalMemorySize | +//+------------------------------------------------------------------+ +bool COpenCL::GetLocalMemorySize(long &local_memory_size) + { + if(m_context==INVALID_HANDLE) + return(false); + +//--- get local memory size + local_memory_size=CLGetInfoInteger(m_context,CL_DEVICE_LOCAL_MEM_SIZE); + if(local_memory_size==-1) + return(false); +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| GetMaxWorkgroupSize | +//+------------------------------------------------------------------+ +bool COpenCL::GetMaxWorkgroupSize(long &max_workgroup_size) + { + if(m_context==INVALID_HANDLE) + return(false); + +//--- get maximal workgroup size + max_workgroup_size=CLGetInfoInteger(m_context,CL_DEVICE_MAX_WORK_GROUP_SIZE); + if(max_workgroup_size==-1) + return(false); +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| Initialize | +//+------------------------------------------------------------------+ +bool COpenCL::Initialize(const string program,const bool show_log) + { + if(!ContextCreate(CL_USE_ANY)) + return(false); + return(ProgramCreate(program,show_log)); + } +//+------------------------------------------------------------------+ +//| ContextCreate | +//+------------------------------------------------------------------+ +bool COpenCL::ContextCreate(const int device) + { + if((m_context=CLContextCreate(device))==INVALID_HANDLE) + { + Print("OpenCL not found. Error code=",GetLastError()); + return(false); + } +//--- check support working with doubles (cl_khr_fp64) + if(CLGetInfoString(m_context,CL_DEVICE_EXTENSIONS,m_device_extensions)) + { + string extenstions[]; + StringSplit(m_device_extensions,' ',extenstions); + m_support_cl_khr_fp64=false; + int size=ArraySize(extenstions); + for(int i=0; i=m_kernels_total) + return(false); +//--- + int kernel_handle=m_kernels[kernel_index]; + if(kernel_handle==INVALID_HANDLE || m_kernel_names[kernel_index]!=kernel_name) + { + //--- create kernel + if((kernel_handle=CLKernelCreate(m_program,kernel_name))==INVALID_HANDLE) + { + CLProgramFree(m_program); + CLContextFree(m_context); + Print("OpenCL kernel create failed. Error code=",GetLastError()); + return(false); + } + else + { + m_kernels[kernel_index]=kernel_handle; + m_kernel_names[kernel_index]=kernel_name; + } + } + return(true); + } +//+------------------------------------------------------------------+ +//| KernelFree | +//+------------------------------------------------------------------+ +bool COpenCL::KernelFree(const int kernel_index) + { +//--- check kernel index + if(kernel_index<0 || kernel_index>=m_kernels_total) + return(false); + if(m_kernels[kernel_index]==INVALID_HANDLE) + return(false); +//--- free kernel handle + CLKernelFree(m_kernels[kernel_index]); + m_kernels[kernel_index]=INVALID_HANDLE; +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +long COpenCL::GetDeviceInfo(const int prop) + { + if(m_context==INVALID_HANDLE) + return(-1); + + uchar data[]; + uint size; + if(!CLGetDeviceInfo(m_context,prop,data,size)) + return(-1); + if(size<4) + return(-1); + + union res_data + { + uchar cdata[8]; + long ldata; + } res; + if(size<=8) + { + ZeroMemory(res); + ArrayCopy(res.cdata,data); + } + else + ArrayCopy(res.cdata,data,0,8); + + return(res.ldata); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +long COpenCL::GetDeviceInfoInteger(ENUM_OPENCL_PROPERTY_INTEGER prop) + { + if(m_context==INVALID_HANDLE) + return(-1); + + return(CLGetInfoInteger(m_context,prop)); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +long COpenCL::GetKernelInfoInteger(const int kernel_index,ENUM_OPENCL_PROPERTY_INTEGER prop) + { + if(kernel_index<0 || kernel_index>=m_kernels_total) + return(-1); + + return(CLGetInfoInteger(m_kernels[kernel_index],prop)); + } +//+------------------------------------------------------------------+ +//| BufferCreate | +//+------------------------------------------------------------------+ +bool COpenCL::BufferCreate(const int buffer_index,const uint size_in_bytes,const uint flags) + { +//--- check parameters + if(buffer_index<0 || buffer_index>=m_buffers_total) + return(false); + + if(m_context==INVALID_HANDLE) + return(false); +//--- + int buffer_handle=CLBufferCreate(m_context,size_in_bytes,flags); + if(buffer_handle!=INVALID_HANDLE) + { + m_buffers[buffer_index]=buffer_handle; + return(true); + } + else + return(false); + } +//+------------------------------------------------------------------+ +//| BufferFree | +//+------------------------------------------------------------------+ +bool COpenCL::BufferFree(const int buffer_index) + { +//--- check buffer index + if(buffer_index<0 || buffer_index>=m_buffers_total) + return(false); + if(m_buffers[buffer_index]==INVALID_HANDLE) + return(false); +//--- free buffer handle + CLBufferFree(m_buffers[buffer_index]); + m_buffers[buffer_index]=INVALID_HANDLE; +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| BufferFromArray | +//+------------------------------------------------------------------+ +template +bool COpenCL::BufferFromArray(const int buffer_index,T &data[],const uint data_array_offset,const uint data_array_count,const uint flags) + { +//--- check parameters + if(m_context==INVALID_HANDLE) + return(false); + if(buffer_index<0 || buffer_index>=m_buffers_total || data_array_count<=0) + return(false); + +//--- buffer does not exists, create it + if(m_buffers[buffer_index]==INVALID_HANDLE) + { + uint size_in_bytes=data_array_count*sizeof(T); + int buffer_handle=CLBufferCreate(m_context,size_in_bytes,flags); + if(buffer_handle!=INVALID_HANDLE) + { + m_buffers[buffer_index]=buffer_handle; + } + else + return(false); + } +//--- write data to OpenCL buffer + uint data_written=CLBufferWrite(m_buffers[buffer_index],data,0,data_array_offset,data_array_count); + if(data_written!=data_array_count) + return(false); +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| BufferWriteFromMatrix | +//+------------------------------------------------------------------+ +template +bool COpenCL::BufferFromMatrix(const int buffer_index,matrix &data,const uint flags) + { +//--- check parameters + if(m_context==INVALID_HANDLE) + return(false); + if(buffer_index<0 || buffer_index>=m_buffers_total || data.Rows()==0 || data.Cols()==0) + return(false); + + uint matrix_size=uint(data.Rows()*data.Cols()); +//--- buffer does not exists, create it + if(m_buffers[buffer_index]==INVALID_HANDLE) + { + uint size_in_bytes=matrix_size*sizeof(T); + int buffer_handle=CLBufferCreate(m_context,size_in_bytes,flags); + if(buffer_handle!=INVALID_HANDLE) + m_buffers[buffer_index]=buffer_handle; + else + return(false); + } +//--- write data to OpenCL buffer + return(CLBufferWrite(m_buffers[buffer_index],0,data)); + } +//+------------------------------------------------------------------+ +//| BufferWriteFromVector | +//+------------------------------------------------------------------+ +template +bool COpenCL::BufferFromVector(const int buffer_index,vector &data,const uint flags) + { +//--- check parameters + if(m_context==INVALID_HANDLE) + return(false); + if(buffer_index<0 || buffer_index>=m_buffers_total || data.Size()==0) + return(false); + +//--- buffer does not exists, create it + if(m_buffers[buffer_index]==INVALID_HANDLE) + { + uint size_in_bytes=(uint)data.Size()*sizeof(T); + int buffer_handle=CLBufferCreate(m_context,size_in_bytes,flags); + if(buffer_handle!=INVALID_HANDLE) + m_buffers[buffer_index]=buffer_handle; + else + return(false); + } +//--- write data to OpenCL buffer + return(CLBufferWrite(m_buffers[buffer_index],0,data)); + } +//+------------------------------------------------------------------+ +//| BufferReadToMatrix | +//+------------------------------------------------------------------+ +template +bool COpenCL::BufferToMatrix(const int buffer_index,matrix &data,const ulong rows,const ulong cols) + { +//--- check parameters + if(buffer_index<0 || buffer_index>=m_buffers_total) + return(false); + if(m_buffers[buffer_index]==INVALID_HANDLE) + return(false); + if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) + return(false); +//--- read data from OpenCL buffer + return(CLBufferRead(m_buffers[buffer_index],0,data,rows,cols)); + } +//+------------------------------------------------------------------+ +//| BufferReadToVector | +//+------------------------------------------------------------------+ +template +bool COpenCL::BufferToVector(const int buffer_index,vector &data,const ulong size) + { +//--- check parameters + if(buffer_index<0 || buffer_index>=m_buffers_total) + return(false); + if(m_buffers[buffer_index]==INVALID_HANDLE) + return(false); + if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) + return(false); +//--- read data from OpenCL buffer + return(CLBufferRead(m_buffers[buffer_index],0,data,size)); + } +//+------------------------------------------------------------------+ +//| BufferRead | +//+------------------------------------------------------------------+ +template +bool COpenCL::BufferRead(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count) + { +//--- check parameters + if(buffer_index<0 || buffer_index>=m_buffers_total || data_array_count<=0) + return(false); + if(m_buffers[buffer_index]==INVALID_HANDLE) + return(false); + if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) + return(false); +//--- read data from OpenCL buffer + uint data_read=CLBufferRead(m_buffers[buffer_index],data,cl_buffer_offset,data_array_offset,data_array_count); + if(data_read!=data_array_count) + return(false); +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| BufferWrite | +//+------------------------------------------------------------------+ +template +bool COpenCL::BufferWrite(const int buffer_index,T &data[],const uint cl_buffer_offset,const uint data_array_offset,const uint data_array_count) + { +//--- check parameters + if(buffer_index<0 || buffer_index>=m_buffers_total || data_array_count<=0) + return(false); + if(m_buffers[buffer_index]==INVALID_HANDLE) + return(false); + if(m_context==INVALID_HANDLE) + return(false); +//--- write data to OpenCL buffer + uint data_written=CLBufferWrite(m_buffers[buffer_index],data,cl_buffer_offset,data_array_offset,data_array_count); + if(data_written!=data_array_count) + return(false); +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| SetArgument | +//+------------------------------------------------------------------+ +template +bool COpenCL::SetArgument(const int kernel_index,const int arg_index,T value) + { + if(kernel_index<0 || kernel_index>=m_kernels_total) + return(false); + + int kernel_handle=m_kernels[kernel_index]; + if(kernel_handle==INVALID_HANDLE) + return(false); +//--- + return CLSetKernelArg(kernel_handle,arg_index,value); + } +//+------------------------------------------------------------------+ +//| SetArgumentBuffer | +//+------------------------------------------------------------------+ +bool COpenCL::SetArgumentBuffer(const int kernel_index,const int arg_index,const int buffer_index) + { + if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) + return(false); + if(kernel_index<0 || kernel_index>=m_kernels_total) + return(false); + if(buffer_index<0 || buffer_index>=m_buffers_total) + return(false); + if(m_buffers[buffer_index]==INVALID_HANDLE) + return(false); +//--- + return CLSetKernelArgMem(m_kernels[kernel_index],arg_index,m_buffers[buffer_index]); + } +//+------------------------------------------------------------------+ +//| SetArgumentLocalMemory | +//+------------------------------------------------------------------+ +bool COpenCL::SetArgumentLocalMemory(const int kernel_index,const int arg_index,const int local_memory_size) + { + if(m_context==INVALID_HANDLE || m_program==INVALID_HANDLE) + return(false); + if(kernel_index<0 || kernel_index>=m_kernels_total) + return(false); +//--- check device local memory size + long device_local_memory_size=CLGetInfoInteger(m_context,CL_DEVICE_LOCAL_MEM_SIZE); + if(local_memory_size>device_local_memory_size) + return(false); +//--- + return CLSetKernelArgMemLocal(m_kernels[kernel_index],arg_index,local_memory_size); + } +//+------------------------------------------------------------------+ +//| Execute | +//+------------------------------------------------------------------+ +bool COpenCL::Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[]) + { + if(kernel_index<0 || kernel_index>=m_kernels_total) + return(false); + int kernel_handle=m_kernels[kernel_index]; + if(kernel_handle==INVALID_HANDLE) + return(false); +//--- + return CLExecute(kernel_handle,work_dim,work_offset,work_size); + } +//+------------------------------------------------------------------+ +//| Execute | +//+------------------------------------------------------------------+ +bool COpenCL::Execute(const int kernel_index,const int work_dim,const uint &work_offset[],const uint &work_size[],const uint &local_work_size[]) + { + if(kernel_index<0 || kernel_index>=m_kernels_total) + return(false); +//--- + return CLExecute(m_kernels[kernel_index],work_dim,work_offset,work_size,local_work_size); + } +//+------------------------------------------------------------------+ diff --git a/Orchard/LicenceCheck/LicenceFileCheck.mqh b/Orchard/LicenceCheck/LicenceFileCheck.mqh new file mode 100644 index 0000000..84a7a28 --- /dev/null +++ b/Orchard/LicenceCheck/LicenceFileCheck.mqh @@ -0,0 +1,124 @@ +/* + LicenceFileCheck.mqh + Copyright 2021, Orchard Forex + https://www.orchardforex.com +*/ + +#property copyright "Copyright 2013-2020, Orchard Forex" +#property link "https://www.orchardforex.com" +#property version "1.00" + +class CLicenceFile { + +protected: + string mProductName; + string mProductKey; + string mData; + + virtual bool LoadData( string &data ); + virtual string LicencePath(); + +public: + CLicenceFile( string productName, string productKey ); + ~CLicenceFile() {} + + bool Check(); + string KeyGen( string data ); // Allow account to pass in + string Hash( string data ); + bool FileGen( string data ); + + void chekload2(string &dat1) {LoadData(dat1);} + string GetData() { return ( mData ); } +}; + +CLicenceFile::CLicenceFile( string productName, string productKey ) { + + mProductName = productName; + mProductKey = productKey; +} + +string CLicenceFile::LicencePath() { return ( "Orchard\\Licence\\" + mProductName + ".lic" ); } + +bool CLicenceFile::Check() { + + mData = ""; + string data = ""; + if ( !LoadData( data ) ) return false; + + int pos = StringFind( data, "\n" ); + if ( pos <= 0 ) { + Print( "Licence file is not valid" ); + return ( false ); + } + + string signature = StringSubstr( data, 0, pos ); + mData = StringSubstr( data, pos + 1 ); + Print("mdata ",mData," sign ",signature); + string key = KeyGen( mData ); + if ( key != signature ) { + Print( "Licence is invalid" ); + return ( false ); + } + + return ( true ); +} + +bool CLicenceFile::LoadData( string &data ) { + Print("load 02"); + string licencePath = LicencePath(); + + // Open and read the file each time in case it has been modified between iterations + int handle = FileOpen( licencePath, FILE_READ | FILE_BIN | FILE_ANSI ); + if ( handle == INVALID_HANDLE ) { + PrintFormat( "Could not open licence file %s", licencePath ); + return ( false ); + } + + int len = ( int )FileSize( handle ); + data = FileReadString( handle, len ); + FileClose( handle ); + Print("load 02 2"); + return true; +} + +string CLicenceFile::KeyGen( string data ) { + + string keyString = data + mProductKey; + return Hash( keyString ); +} + +string CLicenceFile::Hash( string data ) { + + uchar dataChar[]; + StringToCharArray( data, dataChar, 0, StringLen( data ) ); + + uchar cryptChar[]; + CryptEncode( CRYPT_HASH_SHA256, dataChar, dataChar, cryptChar ); + + string result = ""; + int count = ArraySize( cryptChar ); + for ( int i = 0; i < count; i++ ) { + result += StringFormat( "%.2x", cryptChar[i] ); + } + return result; +} + +bool CLicenceFile::FileGen( string data ) { + + string licencePath = LicencePath(); + + int handle = FileOpen( licencePath, FILE_WRITE | FILE_BIN | FILE_ANSI ); + if ( handle == INVALID_HANDLE ) { + PrintFormat( "Could not create licence file %s", licencePath ); + return ( false ); + } + + string signature = KeyGen( data ); + string contents = signature + "\n" + data; + FileWriteString( handle, contents ); + FileFlush( handle ); + FileClose( handle ); + + Print( "Licence file '" + licencePath + "' created" ); + return ( true ); +} diff --git a/Orchard/LicenceCheck/LicenceWebCheck.mqh b/Orchard/LicenceCheck/LicenceWebCheck.mqh new file mode 100644 index 0000000..d1b6774 --- /dev/null +++ b/Orchard/LicenceCheck/LicenceWebCheck.mqh @@ -0,0 +1,97 @@ +/* + LicenceWebCheck.mqh + Copyright 2021, Orchard Forex + https://www.orchardforex.com +*/ + +#property copyright "Copyright 2013-2020, Orchard Forex" +#property link "https://www.orchardforex.com" +#property version "1.00" + +// this is important for MT4 +#property strict + +#include "LicenceFileCheck.mqh" + +class CLicenceWeb : public CLicenceFile { + +protected: + string mAccount; + string mRegistration; + + virtual bool LoadData( string &data ); + virtual string LicencePath(); + +public: + CLicenceWeb( string productName, string productKey, string registration, long account = -1 ); + ~CLicenceWeb() {} + + void SetRegistration(); + + void chekload1(string &dat1) {LoadData(dat1);} +}; + +CLicenceWeb::CLicenceWeb( string productName, string productKey, string registration, long account = -1 ) : CLicenceFile( productName, productKey ) { + + mRegistration = registration; + if ( account < 0 ) { + account = AccountInfoInteger( ACCOUNT_LOGIN ); + } + mAccount = string( account ); + string data2; + chekload2(data2); + Print("data 2",data2); +} + +void CLicenceWeb::SetRegistration() { mRegistration = Hash( mProductName + "_" + mAccount ); } + +string CLicenceWeb::LicencePath() { return ( "Orchard\\Licence\\" + Hash( mProductName + "_" + mAccount ) + ".lic" ); } + +bool CLicenceWeb::LoadData( string &data ) { + Print("load 01"); + string headers = ""; + char postData[]; + char resultData[]; + string resultHeaders; + int timeout = 5000; // 1 second, may be too short for a slow connection + + string url = "https://raw.githubusercontent.com"; + // string api = StringFormat( "https://drive.google.com/uc?id=%s&export=download", mRegistration ); + // string api = StringFormat( "%s/OrchardForexTutorials/Licence/raw/main/%s.txt", url, mRegistration ); + string api = StringFormat( "%s/amirghadiri1987/License/refs/heads/main/%s.lic", url, mRegistration ); + Print("api ",api); + + ResetLastError(); + int response = WebRequest( "GET", api, headers, timeout, postData, resultData, resultHeaders ); + int errorCode = GetLastError(); + + // Add this code to handle 303 redirect but it creates more problems + // if (response==303) { + // int locStart = StringFind(resultHeaders, "Location: ", 0)+10; + // int locEnd = StringFind(resultHeaders, "\r", locStart); + // api = StringSubstr(resultHeaders, locStart, locEnd-locStart); + // ResetLastError(); + // response = WebRequest( "GET", api, headers, timeout, postData, resultData, resultHeaders ); + // errorCode = GetLastError(); + //} + + data = CharArrayToString( resultData ); + + switch ( response ) { + case -1: + Print( "Error in WebRequest. Error code =", errorCode ); + Print( "Add the address " + url + " in the list of allowed URLs" ); + return false; + break; + case 200: + //--- Success + return true; + break; + default: + PrintFormat( "Unexpected response code %i", response ); + return false; + break; + } + + return false; +} diff --git a/Orchard/LicenceCheck/WebLicenceTest.mqh b/Orchard/LicenceCheck/WebLicenceTest.mqh new file mode 100644 index 0000000..d8ea7a5 --- /dev/null +++ b/Orchard/LicenceCheck/WebLicenceTest.mqh @@ -0,0 +1,76 @@ +/* + WebLicenceTest + Copyright 2021, Orchard Forex + https://www.orchardforex.com +*/ + +#include + +input string InpProductName = "product1"; // Product name used in file name +input string InpProductKey = "key1"; // Secret product key +input int InpAccount = 123456; // Customer Account number +input bool InpTesting = false; // Is this a test + +CLicenceWeb *licenceWeb; + +void OnStart_() { + + licenceWeb = new CLicenceWeb( InpProductName, InpProductKey, "", InpAccount ); + licenceWeb.SetRegistration(); + if ( !InpTesting ) { + Make(); + } + else { + Test(); + } + string data1; + licenceWeb.chekload1(data1); + + Print("data1 ",data1); + delete licenceWeb; +} + +void Make() { + + // Just making up some data here + // You could use anything that works for you + // Account number, expiry time, grace expiry time + string data = licenceWeb.Hash( string( InpAccount ) ) + "\n" + licenceWeb.Hash( InpProductName ) + "\n" + TimeToString( TimeCurrent() + ( 86400 * 30 ) ) + "\n" + + TimeToString( TimeCurrent() + ( 86400 * 33 ) ); + + // Not necessary to do this, just for demonstration + string signature = licenceWeb.KeyGen( data ); + Print( "The signature is " + signature ); + + // Create the file to ship to the customer + if ( !licenceWeb.FileGen( data ) ) { + Print( "Failed to create licence file" ); + return; + } + + Print( "Created licence file" ); +} + +void Test() { + + Print( "Now testing licence" ); + if ( !licenceWeb.Check() ) { + Print( "Oops, problem with the licence" ); + return; + } + + Print( "Valid Licence" ); + string parts[]; + string licenceData = licenceWeb.GetData(); + StringSplit( licenceData, '\n', parts ); + + PrintFormat( "Account=%s, %s", parts[0], ( parts[0] == licenceWeb.Hash( string( InpAccount ) ) ) ? "correct" : "fail" ); + + PrintFormat( "Product=%s, %s", parts[1], ( parts[1] == licenceWeb.Hash( InpProductName ) ) ? "correct" : "fail" ); + + PrintFormat( "Expires at %s", parts[2] ); + PrintFormat( "Grace expires at %s", parts[3] ); +} + +// bnH1yjYYpwp+dBDfzfvgUzmOGVhtv6hTHeYX7MwVhcQ=.lic +// bnH1yjYYpwp+dBDfzfvgUzmOGVhtv6hTHeYX7MwVhcQ= diff --git a/PairPlot/Histogram.mqh b/PairPlot/Histogram.mqh new file mode 100644 index 0000000..c31ff17 Binary files /dev/null and b/PairPlot/Histogram.mqh differ diff --git a/PairPlot/PairPlot.mqh b/PairPlot/PairPlot.mqh new file mode 100644 index 0000000..0582178 Binary files /dev/null and b/PairPlot/PairPlot.mqh differ diff --git a/PairPlot/PairPlotDemo.mqh b/PairPlot/PairPlotDemo.mqh new file mode 100644 index 0000000..d422d5f Binary files /dev/null and b/PairPlot/PairPlotDemo.mqh differ diff --git a/PairPlot/Plot.mqh b/PairPlot/Plot.mqh new file mode 100644 index 0000000..f00aa98 Binary files /dev/null and b/PairPlot/Plot.mqh differ diff --git a/PairPlot/PlotBase.mqh b/PairPlot/PlotBase.mqh new file mode 100644 index 0000000..7ea1158 --- /dev/null +++ b/PairPlot/PlotBase.mqh @@ -0,0 +1,163 @@ +//+------------------------------------------------------------------+ +//| PlotBase.mqh | +//| Copyright 2018, MetaQuotes Software Corp. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2018, MetaQuotes Software Corp." +#property link "https://www.mql5.com" +#property version "1.00" +//--- +#include +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +class CPlotBase : public CGraphic + { +protected: + long m_chart_id; // chart ID + int m_subwin; // chart subwindow + +public: + CPlotBase(); + ~CPlotBase(); +//--- + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int size); + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); + virtual bool SetTimeseriesColor(uint clr, uint timeserie=0); +//--- + // virtual void TextUp(string text, uint clr); + // virtual void TextDown(string text, uint clr); + // virtual void TextLeft(string text, uint clr); + // virtual void TextRight(string text, uint clr); +//--- geometry + virtual bool Shift(const int dx,const int dy); +//--- state + virtual bool Show(void); + virtual bool Hide(void); + }; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +CPlotBase::CPlotBase() + { + HistoryNameWidth(0); + HistorySymbolSize(0); + m_x.MaxLabels(3); + m_y.MaxLabels(3); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +CPlotBase::~CPlotBase() + { + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CPlotBase::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int size) + { + int x2=x1+size; + int y2=y1+size; + return Create(chart,name,subwin,x1,y1,x2,y2); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CPlotBase::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) + { + if(!CGraphic::Create(chart,name,subwin,x1,y1,x2,y2)) + return false; + m_chart_id=chart; + m_subwin=subwin; + return true; + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CPlotBase::SetTimeseriesColor(uint clr,uint timeserie=0) + { + if((int)timeserie>=m_arr_curves.Total()) + return false; +//--- + CCurve *curve=m_arr_curves.At(timeserie); + if(CheckPointer(curve)==POINTER_INVALID) + return false; +//--- + curve.Color(clr); +//--- + return true; + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +// CPlotBase::TextUp(string text, uint clr) +// { +// // m_canvas.FontAngleSet(0); +// // TextAdd(m_width/2,1,text,clr,TA_CENTER|TA_TOP); +// } +// //+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +// CPlotBase::TextDown(string text, uint clr) +// { +// m_canvas.FontAngleSet(0); +// TextAdd(m_width/2,m_height-1,text,clr,TA_CENTER|TA_BOTTOM); +// } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +// CPlotBase::TextLeft(string text, uint clr) +// { +// m_canvas.FontAngleSet(900); +// TextAdd(1,m_height/2,text,clr,TA_CENTER|TA_TOP); +// } +// //+------------------------------------------------------------------+ +// //| | +// //+------------------------------------------------------------------+ +// CPlotBase::TextRight(string text, uint clr) +// { +// m_canvas.FontAngleSet(900); +// TextAdd(m_width-1,m_height/2,text,clr,TA_CENTER|TA_BOTTOM); +// } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CPlotBase::Show(void) + { + string obj_name=ChartObjectName(); + if(obj_name==NULL || ObjectFind(m_chart_id,obj_name)<0) + return false; + if(!ObjectSetInteger(m_chart_id,obj_name,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS)) + return false; + Update(false); + return true; + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CPlotBase::Hide(void) + { + string obj_name=ChartObjectName(); + if(obj_name==NULL || ObjectFind(m_chart_id,obj_name)<0) + return false; + return ObjectSetInteger(m_chart_id,obj_name,OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CPlotBase::Shift(const int dx,const int dy) + { + string obj_name=ChartObjectName(); + if(obj_name==NULL || ObjectFind(m_chart_id,obj_name)<0) + return false; +//--- + int x=(int)ObjectGetInteger(m_chart_id,obj_name,OBJPROP_XDISTANCE)+dx; + int y=(int)ObjectGetInteger(m_chart_id,obj_name,OBJPROP_YDISTANCE)+dy; + if(!ObjectSetInteger(m_chart_id,obj_name,OBJPROP_XDISTANCE,x)) + return false; + if(!ObjectSetInteger(m_chart_id,obj_name,OBJPROP_YDISTANCE,y)) + return false; +//--- + return true; + } +//+------------------------------------------------------------------+ diff --git a/PairPlot/Scatter.mqh b/PairPlot/Scatter.mqh new file mode 100644 index 0000000..6a2d649 --- /dev/null +++ b/PairPlot/Scatter.mqh @@ -0,0 +1,66 @@ +//+------------------------------------------------------------------+ +//| Scatter.mqh | +//| Copyright 2018, MetaQuotes Software Corp. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2018, MetaQuotes Software Corp." +#property link "https://www.mql5.com" +#property version "1.00" +//--- +#include "PlotBase.mqh" +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +class CScatter : public CPlotBase + { +public: + CScatter(); + ~CScatter(); +//--- + int AddTimeseries(const double ×eries_1[],const double ×eries_2[]); + bool UpdateTimeseries(const double ×eries_1[],const double ×eries_2[],uint timeserie=0); + + }; +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +CScatter::CScatter() + { + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +CScatter::~CScatter() + { + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +int CScatter::AddTimeseries(const double ×eries_1[],const double ×eries_2[]) + { + CCurve *curve=CGraphic::CurveAdd(timeseries_1,timeseries_2,CURVE_POINTS); + if(curve==NULL) + return -1; + curve.PointsSize(2); + curve.TrendLineVisible(true); + return (m_arr_curves.Total()-1); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CScatter::UpdateTimeseries(const double ×eries_1[],const double ×eries_2[], uint timeserie=0) + { + if((int)timeserie>=m_arr_curves.Total()) + return false; + if(ArraySize(timeseries_1)!=ArraySize(timeseries_2) || ArraySize(timeseries_1)==0) + return false; +//--- + CCurve *curve=m_arr_curves.At(timeserie); + if(CheckPointer(curve)==POINTER_INVALID) + return false; +//--- + curve.Update(timeseries_1,timeseries_2); +//--- + return true; + } +//+------------------------------------------------------------------+ diff --git a/Panel/ElButton.mqh b/Panel/ElButton.mqh new file mode 100644 index 0000000..a325782 Binary files /dev/null and b/Panel/ElButton.mqh differ diff --git a/Panel/ElChart.mqh b/Panel/ElChart.mqh new file mode 100644 index 0000000..558ab7b Binary files /dev/null and b/Panel/ElChart.mqh differ diff --git a/Panel/Events/Event.mqh b/Panel/Events/Event.mqh new file mode 100644 index 0000000..86a042b Binary files /dev/null and b/Panel/Events/Event.mqh differ diff --git a/Panel/Events/EventChart.mqh b/Panel/Events/EventChart.mqh new file mode 100644 index 0000000..2c58897 Binary files /dev/null and b/Panel/Events/EventChart.mqh differ diff --git a/Panel/Events/EventChartEndEdit.mqh b/Panel/Events/EventChartEndEdit.mqh new file mode 100644 index 0000000..f26ed74 Binary files /dev/null and b/Panel/Events/EventChartEndEdit.mqh differ diff --git a/Panel/Events/EventChartObjClick.mqh b/Panel/Events/EventChartObjClick.mqh new file mode 100644 index 0000000..ab43b78 Binary files /dev/null and b/Panel/Events/EventChartObjClick.mqh differ diff --git a/Panel/Events/EventRefresh.mqh b/Panel/Events/EventRefresh.mqh new file mode 100644 index 0000000..18f46f3 Binary files /dev/null and b/Panel/Events/EventRefresh.mqh differ diff --git a/Panel/Node.mqh b/Panel/Node.mqh new file mode 100644 index 0000000..9231d6e Binary files /dev/null and b/Panel/Node.mqh differ diff --git a/ProgressBars/Colors.mqh b/ProgressBars/Colors.mqh new file mode 100644 index 0000000..607b803 --- /dev/null +++ b/ProgressBars/Colors.mqh @@ -0,0 +1,805 @@ +//+------------------------------------------------------------------+ +//| Colors.mqh | +//| Copyright 2015, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +class CColors + { +private: + double Arctan2(const double x,const double y); + double Hue_To_RGB(double v1,double v2,double vH); +public: + CColors(); + ~CColors(); + //--- > http://www.easyrgb.com/index.php?X=MATH + // start of list < + void RGBtoXYZ(const double aR,const double aG,const double aB,double &oX,double &oY,double &oZ); + void XYZtoRGB(const double aX,const double aY,const double aZ,double &oR,double &oG,double &oB); + void XYZtoYxy(const double aX,const double aY,const double aZ,double &oY,double &ox,double &oy); + void YxyToXYZ(const double aY,const double ax,const double ay,double &oX,double &oY,double &oZ); + void XYZtoHunterLab(const double aX,const double aY,const double aZ,double &oL,double &oa,double &ob); + void HunterLabToXYZ(const double aL,const double aa,const double ab,double &oX,double &oY,double &oZ); + void XYZtoCIELab(const double aX,const double aY,const double aZ,double &oCIEL,double &oCIEa,double &oCIEb); + void CIELabToXYZ(const double aCIEL,const double aCIEa,const double aCIEb,double &oX,double &oY,double &oZ); + void CIELabToCIELCH(const double aCIEL,const double aCIEa,const double aCIEb,double &oCIEL,double &oCIEC,double &oCIEH); + void CIELCHtoCIELab(const double aCIEL,const double aCIEC,const double aCIEH,double &oCIEL,double &oCIEa,double &oCIEb); + void XYZtoCIELuv(const double aX,const double aY,const double aZ,double &oCIEL,double &oCIEu,double &oCIEv); + void CIELuvToXYZ(const double aCIEL,const double aCIEu,const double aCIEv,double &oX,double &oY,double &oZ); + void RGBtoHSL(const double aR,const double aG,const double aB,double &oH,double &oS,double &oL); + void HSLtoRGB(const double aH,const double aS,const double aL,double &oR,double &oG,double &oB); + void RGBtoHSV(const double aR,const double aG,const double aB,double &oH,double &oS,double &oV); + void HSVtoRGB(const double aH,const double aS,const double aV,double &oR,double &oG,double &oB); + void RGBtoCMY(const double aR,const double aG,const double aB,double &oC,double &oM,double &oY); + void CMYtoRGB(const double aC,const double aM,const double aY,double &oR,double &oG,double &oB); + void CMYtoCMYK(const double aC,const double aM,const double aY,double &oC,double &oM,double &oY,double &oK); + void CMYKtoCMY(const double aC,const double aM,const double aY,const double aK,double &oC,double &oM,double &oY); + //--- > end of list + // + void ColorToRGB(const color aColor,double &aR,double &aG,double &aB); + double GetR(const color aColor); + double GetG(const color aColor); + double GetB(const color aColor); + color RGBToColor(const double aR,const double aG,const double aB); + color MixColors(const color aCol1,const color aCol2,const double aK); + void Gradient(color &aColors[],color &aOut[],int aOutCount,bool aCycle=false); + void RGBtoXYZsimple(double aR,double aG,double aB,double &oX,double &oY,double &oZ); + void XYZtoRGBsimple(const double aX,const double aY,const double aZ,double &oR,double &oG,double &oB); + color Negative(const color aColor); + color StandardColor(const color aColor,int &aIndex); + double RGBtoGray(double aR,double aG,double aB); + double RGBtoGraySimple(double aR,double aG,double aB); + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CColors::CColors(void) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CColors::~CColors(void) + { + } +//+------------------------------------------------------------------+ +//| Arctan2 | +//+------------------------------------------------------------------+ +double CColors::Arctan2(const double x,const double y) + { + if(y==0) + { + if(x<0) + return(M_PI); + //--- + return(0); + } + else + { + if(x>0) + return(::MathArctan(y/x)); + //--- + if(x<0) + { + if(y>0) + return(::MathArctan(y/x)+M_PI); + //--- + return(::MathArctan(y/x)-M_PI); + } + else + { + if(y<0) + return(-M_PI_2); + //--- + return(M_PI_2); + } + } + } +//+------------------------------------------------------------------+ +//| Hue_To_RGB | +//+------------------------------------------------------------------+ +double CColors::Hue_To_RGB(double v1,double v2,double vH) + { + if(vH<0) + vH+=1.0; + if(vH>1.0) + vH-=1; + if((6.0*vH)<1.0) + return(v1+(v2-v1)*6.0*vH); + if((2.0*vH)<1.0) + return(v2); + if((3.0*vH)<2.0) + return(v1+(v2-v1)*((2.0/3.0)-vH)*6.0); +//--- + return(v1); + } +//+------------------------------------------------------------------+ +//| RGB XYZ | +//+------------------------------------------------------------------+ +void CColors::RGBtoXYZ(const double aR,const double aG,const double aB,double &oX,double &oY,double &oZ) + { + double var_R=aR/255; + double var_G=aG/255; + double var_B=aB/255; +//--- + if(var_R>0.04045) + var_R=::MathPow((var_R+0.055)/1.055,2.4); + else + var_R=var_R/12.92; +//--- + if(var_G>0.04045) + var_G=::MathPow((var_G+0.055)/1.055,2.4); + else + var_G=var_G/12.92; +//--- + if(var_B>0.04045) + var_B=::MathPow((var_B+0.055)/1.055,2.4); + else + var_B=var_B/12.92; +//--- + var_R =var_R*100.0; + var_G =var_G*100.0; + var_B =var_B*100.0; + oX =var_R*0.4124+var_G*0.3576+var_B*0.1805; + oY =var_R*0.2126+var_G*0.7152+var_B*0.0722; + oZ =var_R*0.0193+var_G*0.1192+var_B*0.9505; + } +//+------------------------------------------------------------------+ +//| XYZ RGB | +//+------------------------------------------------------------------+ +void CColors::XYZtoRGB(const double aX,const double aY,const double aZ,double &oR,double &oG,double &oB) + { + double var_X =aX/100; + double var_Y =aY/100; + double var_Z =aZ/100; + double var_R =var_X*3.2406+var_Y*-1.5372+var_Z*-0.4986; + double var_G =var_X*(-0.9689)+var_Y*1.8758+var_Z*0.0415; + double var_B =var_X*0.0557+var_Y*(-0.2040)+var_Z*1.0570; +//--- + if(var_R>0.0031308) + var_R=1.055*(::MathPow(var_R,1.0/2.4))-0.055; + else + var_R=12.92*var_R; +//--- + if(var_G>0.0031308) + var_G=1.055*(::MathPow(var_G,1.0/2.4))-0.055; + else + var_G=12.92*var_G; +//--- + if(var_B>0.0031308) + var_B=1.055*(::MathPow(var_B,1.0/2.4))-0.055; + else + var_B=12.92*var_B; +//--- + oR =var_R*255.0; + oG =var_G*255.0; + oB =var_B*255.0; + } +//+------------------------------------------------------------------+ +//| XYZ Yxy | +//+------------------------------------------------------------------+ +void CColors::XYZtoYxy(const double aX,const double aY,const double aZ,double &oY,double &ox,double &oy) + { + oY =aY; + ox =aX/(aX+aY+aZ); + oy =aY/(aX+aY+aZ); + } +//+------------------------------------------------------------------+ +//| Yxy XYZ | +//+------------------------------------------------------------------+ +void CColors::YxyToXYZ(const double aY,const double ax,const double ay,double &oX,double &oY,double &oZ) + { + oX =ax*(aY/ay); + oY =aY; + oZ =(1.0-ax-ay)*(aY/ay); + } +//+------------------------------------------------------------------+ +//| XYZ HunterLab | +//+------------------------------------------------------------------+ +void CColors::XYZtoHunterLab(const double aX,const double aY,const double aZ,double &oL,double &oa,double &ob) + { + oL =10.0*::MathSqrt(aY); + oa =17.5*(((1.02*aX)-aY)/::MathSqrt(aY)); + ob =7.0*((aY-(0.847*aZ))/::MathSqrt(aY)); + } +//+------------------------------------------------------------------+ +//| HunterLab XYZ | +//+------------------------------------------------------------------+ +void CColors::HunterLabToXYZ(const double aL,const double aa,const double ab,double &oX,double &oY,double &oZ) + { + double var_Y =aL/10.0; + double var_X =aa/17.5*aL/10.0; + double var_Z =ab/7.0*aL/10.0; +//--- + oY =::MathPow(var_Y,2); + oX =(var_X+oY)/1.02; + oZ =-(var_Z-oY)/0.847; + } +//+------------------------------------------------------------------+ +//| XYZ CIELab | +//+------------------------------------------------------------------+ +void CColors::XYZtoCIELab(const double aX,const double aY,const double aZ,double &oCIEL,double &oCIEa,double &oCIEb) + { + double ref_X =95.047; + double ref_Y =100.0; + double ref_Z =108.883; + double var_X =aX/ref_X; + double var_Y =aY/ref_Y; + double var_Z =aZ/ref_Z; +//--- + if(var_X>0.008856) + var_X=::MathPow(var_X,1.0/3.0); + else + var_X=(7.787*var_X)+(16.0/116.0); +//--- + if(var_Y>0.008856) + var_Y=::MathPow(var_Y,1.0/3.0); + else + var_Y=(7.787*var_Y)+(16.0/116.0); +//--- + if(var_Z>0.008856) + var_Z=::MathPow(var_Z,1.0/3.0); + else + var_Z=(7.787*var_Z)+(16.0/116.0); +//--- + oCIEL =(116.0*var_Y)-16.0; + oCIEa =500.0*(var_X-var_Y); + oCIEb =200*(var_Y-var_Z); + } +//+------------------------------------------------------------------+ +//| CIELab ToXYZ | +//+------------------------------------------------------------------+ +void CColors::CIELabToXYZ(const double aCIEL,const double aCIEa,const double aCIEb,double &oX,double &oY,double &oZ) + { + double var_Y =(aCIEL+16.0)/116.0; + double var_X =aCIEa/500.0+var_Y; + double var_Z =var_Y-aCIEb/200.0; +//--- + if(::MathPow(var_Y,3)>0.008856) + var_Y=::MathPow(var_Y,3); + else + var_Y=(var_Y-16.0/116.0)/7.787; +//--- + if(::MathPow(var_X,3)>0.008856) + var_X=::MathPow(var_X,3); + else + var_X=(var_X-16.0/116.0)/7.787; +//--- + if(::MathPow(var_Z,3)>0.008856) + var_Z=::MathPow(var_Z,3); + else + var_Z=(var_Z-16.0/116.0)/7.787; +//--- + double ref_X =95.047; + double ref_Y =100.0; + double ref_Z =108.883; +//--- + oX =ref_X*var_X; + oY =ref_Y*var_Y; + oZ =ref_Z*var_Z; + } +//+------------------------------------------------------------------+ +//| CIELab CIELCH | +//+------------------------------------------------------------------+ +void CColors::CIELabToCIELCH(const double aCIEL,const double aCIEa,const double aCIEb,double &oCIEL,double &oCIEC,double &oCIEH) + { + double var_H=this.Arctan2(aCIEb,aCIEa); +//--- + if(var_H>0) + var_H=(var_H/M_PI)*180.0; + else + var_H=360.0-(::MathAbs(var_H)/M_PI)*180.0; +//--- + oCIEL =aCIEL; + oCIEC =::MathSqrt(::MathPow(aCIEa,2)+::MathPow(aCIEb,2)); + oCIEH =var_H; + } +//+------------------------------------------------------------------+ +//| CIELCH CIELab | +//+------------------------------------------------------------------+ +void CColors::CIELCHtoCIELab(const double aCIEL,const double aCIEC,const double aCIEH,double &oCIEL,double &oCIEa,double &oCIEb) + { +//--- from 0 to 360 + oCIEL =aCIEL; + oCIEa =::MathCos(M_PI*aCIEH/180.0)*aCIEC; + oCIEb =::MathSin(M_PI*aCIEH/180)*aCIEC; + } +//+------------------------------------------------------------------+ +//| XYZ CIELuv | +//+------------------------------------------------------------------+ +void CColors::XYZtoCIELuv(const double aX,const double aY,const double aZ,double &oCIEL,double &oCIEu,double &oCIEv) + { + double var_U =(4.0*aX)/(aX+(15.0*aY)+(3.0*aZ)); + double var_V =(9.0*aY)/(aX+(15.0*aY)+(3.0*aZ)); + double var_Y =aY/100.0; +//--- + if(var_Y>0.008856) + var_Y=::MathPow(var_Y,1.0/3.0); + else + var_Y=(7.787*var_Y)+(16.0/116.0); +//--- + double ref_X =95.047; + double ref_Y =100.000; + double ref_Z =108.883; + double ref_U =(4.0*ref_X)/(ref_X+(15.0*ref_Y)+(3.0*ref_Z)); + double ref_V =(9.0*ref_Y)/(ref_X+(15.0*ref_Y)+(3.0*ref_Z)); +//--- + oCIEL =(116.0*var_Y)-16.0; + oCIEu =13.0*oCIEL*(var_U-ref_U); + oCIEv =13.0*oCIEL*(var_V-ref_V); + } +//+------------------------------------------------------------------+ +//| CIELuv XYZ | +//+------------------------------------------------------------------+ +void CColors::CIELuvToXYZ(const double aCIEL,const double aCIEu,const double aCIEv,double &oX,double &oY,double &oZ) + { + double var_Y=(aCIEL+16.0)/116.0; +//--- + if(::MathPow(var_Y,3)>0.008856) + var_Y=::MathPow(var_Y,3); + else + var_Y=(var_Y-16.0/116.0)/7.787; +//--- + double ref_X =95.047; + double ref_Y =100.000; + double ref_Z =108.883; + double ref_U =(4.0*ref_X)/(ref_X+(15.0*ref_Y)+(3.0*ref_Z)); + double ref_V =(9.0*ref_Y)/(ref_X+(15.0*ref_Y)+(3.0*ref_Z)); + double var_U =aCIEu/(13.0*aCIEL)+ref_U; + double var_V =aCIEv/(13.0*aCIEL)+ref_V; +//--- + oY=var_Y*100.0; + oX=-(9.0*oY*var_U)/((var_U-4.0)*var_V-var_U*var_V); + oZ=(9.0*oY-(15.0*var_V*oY)-(var_V*oX))/(3.0*var_V); + } +//+------------------------------------------------------------------+ +//| RGB HSL | +//+------------------------------------------------------------------+ +void CColors::RGBtoHSL(const double aR,const double aG,const double aB,double &oH,double &oS,double &oL) + { + double var_R =(aR/255); + double var_G =(aG/255); + double var_B =(aB/255); + double var_Min =::MathMin(var_R,::MathMin(var_G,var_B)); + double var_Max =::MathMax(var_R,::MathMax(var_G,var_B)); + double del_Max =var_Max-var_Min; +//--- + oL=(var_Max+var_Min)/2; +//--- + if(del_Max==0) + { + oH=0; + oS=0; + } + else + { + if(oL<0.5) + oS=del_Max/(var_Max+var_Min); + else + oS=del_Max/(2.0-var_Max-var_Min); + //--- + double del_R =(((var_Max-var_R)/6.0)+(del_Max/2.0))/del_Max; + double del_G =(((var_Max-var_G)/6.0)+(del_Max/2.0))/del_Max; + double del_B =(((var_Max-var_B)/6.0)+(del_Max/2.0))/del_Max; + //--- + if(var_R==var_Max) + oH=del_B-del_G; + else if(var_G==var_Max) + oH=(1.0/3.0)+del_R-del_B; + else if(var_B==var_Max) + oH=(2.0/3.0)+del_G-del_R; + //--- + if(oH<0) + oH+=1.0; + //--- + if(oH>1) + oH-=1.0; + } + } +//+------------------------------------------------------------------+ +//| HSL RGB | +//+------------------------------------------------------------------+ +void CColors::HSLtoRGB(const double aH,const double aS,const double aL,double &oR,double &oG,double &oB) + { + if(aS==0) + { + oR=aL*255; + oG=aL*255; + oB=aL*255; + } + else + { + double var_2=0.0; + //--- + if(aL<0.5) + var_2=aL*(1.0+aS); + else + var_2=(aL+aS)-(aS*aL); + //--- + double var_1=2.0*aL-var_2; + oR =255.0*Hue_To_RGB(var_1,var_2,aH+(1.0/3.0)); + oG =255.0*Hue_To_RGB(var_1,var_2,aH); + oB =255.0*Hue_To_RGB(var_1,var_2,aH-(1.0/3.0)); + } + } +//+------------------------------------------------------------------+ +//| RGB HSV | +//+------------------------------------------------------------------+ +void CColors::RGBtoHSV(const double aR,const double aG,const double aB,double &oH,double &oS,double &oV) + { + const double var_R =(aR/255.0); + const double var_G =(aG/255.0); + const double var_B =(aB/255.0); + const double var_Min =::MathMin(var_R,::MathMin(var_G, var_B)); + const double var_Max =::MathMax(var_R,::MathMax(var_G,var_B)); + const double del_Max =var_Max-var_Min; +//--- + oV=var_Max; +//--- + if(del_Max==0) + { + oH=0; + oS=0; + } + else + { + oS=del_Max/var_Max; + const double del_R =(((var_Max-var_R)/6.0)+(del_Max/2))/del_Max; + const double del_G =(((var_Max-var_G)/6.0)+(del_Max/2))/del_Max; + const double del_B =(((var_Max-var_B)/6.0)+(del_Max/2))/del_Max; + //--- + if(var_R==var_Max) + oH=del_B-del_G; + else if(var_G==var_Max) + oH=(1.0/3.0)+del_R-del_B; + else if(var_B==var_Max) + oH=(2.0/3.0)+del_G-del_R; + //--- + if(oH<0) + oH+=1.0; + //--- + if(oH>1.0) + oH-=1.0; + } + } +//+------------------------------------------------------------------+ +//| HSV RGB | +//+------------------------------------------------------------------+ +void CColors::HSVtoRGB(const double aH,const double aS,const double aV,double &oR,double &oG,double &oB) + { + if(aS==0) + { + oR =aV*255.0; + oG =aV*255.0; + oB =aV*255.0; + } + else + { + double var_h=aH*6.0; + //--- + if(var_h==6) + var_h=0; + //--- + int var_i =int(var_h); + double var_1 =aV*(1.0-aS); + double var_2 =aV*(1.0-aS*(var_h-var_i)); + double var_3 =aV*(1.0-aS*(1.0-(var_h-var_i))); + double var_r =0.0; + double var_g =0.0; + double var_b =0.0; + //--- + if(var_i==0) + { + var_r =aV; + var_g =var_3; + var_b =var_1; + } + else if(var_i==1.0) + { + var_r=var_2; + var_g=aV; + var_b=var_1; + } + else if(var_i==2.0) + { + var_r=var_1; + var_g=aV; + var_b=var_3; + } + else if(var_i==3) + { + var_r=var_1; + var_g=var_2; + var_b=aV; + } + else if(var_i==4) + { + var_r=var_3; + var_g=var_1; + var_b=aV; + } + else + { + var_r=aV; + var_g=var_1; + var_b=var_2; + } + //--- + oR =var_r*255.0; + oG =var_g*255.0; + oB =var_b*255.0; + } + } +//+------------------------------------------------------------------+ +//| RGB CMY | +//+------------------------------------------------------------------+ +void CColors::RGBtoCMY(const double aR,const double aG,const double aB,double &oC,double &oM,double &oY) + { + oC =1.0-(aR/255.0); + oM =1.0-(aG/255.0); + oY =1.0-(aB/255.0); + } +//+------------------------------------------------------------------+ +//| CMY RGB | +//+------------------------------------------------------------------+ +void CColors::CMYtoRGB(const double aC,const double aM,const double aY,double &oR,double &oG,double &oB) + { + oR =(1.0-aC)*255.0; + oG =(1.0-aM)*255.0; + oB =(1.0-aY)*255.0; + } +//+------------------------------------------------------------------+ +//| CMY CMYK | +//+------------------------------------------------------------------+ +void CColors::CMYtoCMYK(const double aC,const double aM,const double aY,double &oC,double &oM,double &oY,double &oK) + { + double var_K=1; +//--- + if(aC>8)&0xff); + } +//+------------------------------------------------------------------+ +//| B | +//+------------------------------------------------------------------+ +double CColors::GetB(const color aColor) + { + return((aColor>>16)&0xff); + } +//+------------------------------------------------------------------+ +//| RGB const color | +//+------------------------------------------------------------------+ +color CColors::RGBToColor(const double aR,const double aG,const double aB) + { + int int_r =(int)::MathRound(aR); + int int_g =(int)::MathRound(aG); + int int_b =(int)::MathRound(aB); + int Color =0; +//--- + Color=int_b; + Color<<=8; + Color|=int_g; + Color<<=8; + Color|=int_r; +//--- + return((color)Color); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +color CColors::MixColors(const color aCol1,const color aCol2,const double aK) + { +//--- aK - 0 1 + double R1=0.0,G1=0.0,B1=0.0,R2=0.0,G2=0.0,B2=0.0; +//--- + ColorToRGB(aCol1,R1,G1,B1); + ColorToRGB(aCol2,R2,G2,B2); +//--- + R1+=(int)::MathRound(aK*(R2-R1)); + G1+=(int)::MathRound(aK*(G2-G1)); + B1+=(int)::MathRound(aK*(B2-B1)); +//--- + return(RGBToColor(R1,G1,B1)); + } +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void CColors::Gradient(color &aColors[], // + color &aOut[], // + int aOutCount, // + bool aCycle=false) // . , + { + ::ArrayResize(aOut,aOutCount); +//--- + int InCount =::ArraySize(aColors)+aCycle; + int PrevJ =0; + int nci =0; + double K =0.0; +//--- + for(int i=1; i Prevention of exceeding the array size." + +//--- Font +#define FONT ("Calibri") +#define FONT_SIZE (8) + +//--- Timer step (milliseconds) +#define TIMER_STEP_MSC (16) +//+------------------------------------------------------------------+ diff --git a/ProgressBars/Element.mqh b/ProgressBars/Element.mqh new file mode 100644 index 0000000..176e3a0 --- /dev/null +++ b/ProgressBars/Element.mqh @@ -0,0 +1,243 @@ +//+------------------------------------------------------------------+ +//| Element.mqh | +//| Copyright 2023, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#include "Objects.mqh" +#include "Colors.mqh" + +//+------------------------------------------------------------------+ +//| Base class of control | +//+------------------------------------------------------------------+ +class CElement + { +protected: + //--- Class instance for working with the color + CColors m_clr; + //--- (1) Name of class and (2) program, (3) program type + string m_class_name; + string m_program_name; + ENUM_PROGRAM_TYPE m_program_type; + //--- Identifier and window number of the chart + long m_chart_id; + int m_subwin; + //--- Identifier and index of control + int m_id; + int m_index; + //--- Coordinates and boundaries + int m_x; + int m_y; + int m_x2; + int m_y2; + int m_x_size; + int m_y_size; + int m_x_gap; + int m_y_gap; + //--- Control states + bool m_is_visible; + bool m_is_dropdown; + int m_is_object_tabs; + //--- Focus + bool m_mouse_focus; + //--- Chart corner and anchor point of objects + ENUM_BASE_CORNER m_corner; + ENUM_ANCHOR_POINT m_anchor; + //--- Number of colors in the gradient + int m_gradient_colors_total; + //--- Common array of pointers to all objects in this control + CChartObject *m_objects[]; + //--- +public: + CElement(void); + ~CElement(void); + //--- (1) Obtaining and setting the class name, (2) obtaining the program name, + // (3) obtaining the program type, (4) setting the number of the chart window + string ClassName(void) const { return(m_class_name); } + void ClassName(const string class_name) { m_class_name=class_name; } + string ProgramName(void) const { return(m_program_name); } + ENUM_PROGRAM_TYPE ProgramType(void) const { return(m_program_type); } + void SubwindowNumber(const int number) { m_subwin=number; } + //--- Obtaining the object pointer by the specified index + CChartObject *Object(const int index); + //--- (1) Obtaining the number of the control objects, (2) emptying the object array + int ObjectsElementTotal(void) const { return(::ArraySize(m_objects)); } + void FreeObjectsArray(void) { ::ArrayFree(m_objects); } + //--- Setting and obtaining the control identifier + void Id(const int id) { m_id=id; } + int Id(void) const { return(m_id); } + //--- Setting and obtaining the control index + void Index(const int index) { m_index=index; } + int Index(void) const { return(m_index); } + //--- Boundaries + int X(void) const { return(m_x); } + void X(const int x) { m_x=x; } + int Y(void) const { return(m_y); } + void Y(const int y) { m_y=y; } + int X2(void) const { return(m_x+m_x_size); } + int Y2(void) const { return(m_y+m_y_size); } + //--- Size + int XSize(void) const { return(m_x_size); } + void XSize(const int x_size) { m_x_size=x_size; } + int YSize(void) const { return(m_y_size); } + void YSize(const int y_size) { m_y_size=y_size; } + //--- Indents from the edge point (xy) + int XGap(void) const { return(m_x_gap); } + void XGap(const int x_gap) { m_x_gap=x_gap; } + int YGap(void) const { return(m_y_gap); } + void YGap(const int y_gap) { m_y_gap=y_gap; } + //--- Control states + void IsVisible(const bool flag) { m_is_visible=flag; } + bool IsVisible(void) const { return(m_is_visible); } + void IsDropdown(const bool flag) { m_is_dropdown=flag; } + bool IsDropdown(void) const { return(m_is_dropdown); } + void IsObjectTabs(const int index) { m_is_object_tabs=index; } + int IsObjectTabs(void) const { return(m_is_object_tabs); } + //--- (1) Focus, (2) setting the gradient size + bool MouseFocus(void) const { return(m_mouse_focus); } + void MouseFocus(const bool focus) { m_mouse_focus=focus; } + void GradientColorsTotal(const int total) { m_gradient_colors_total=total; } + //--- +public: + //--- Chart event handler + virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) {} + //--- Timer + virtual void OnEventTimer(void) {} + //--- Moving the control + virtual void Moving(const int x,const int y) {} + //--- (1) Showing, (2) hiding, (3) resetting, (4) deleting + virtual void Show(void) {} + virtual void Hide(void) {} + virtual void Reset(void) {} + virtual void Delete(void) {} + //--- (1) Setting, (2) resetting of priorities for left clicking on mouse + virtual void SetZorders(void) {} + virtual void ResetZorders(void) {} + //--- +protected: + //--- Method to add pointers of primitive objects to the common array + void AddToArray(CChartObject &object); + //--- Initializing the array gradient + void InitColorArray(const color outer_color,const color hover_color,color &color_array[]); + //--- Changing the object color + void ChangeObjectColor(const string name,const bool mouse_focus,const ENUM_OBJECT_PROPERTY_INTEGER property, + const color outer_color,const color hover_color,const color &color_array[]); + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CElement::CElement(void) : m_x(0), + m_y(0), + m_x2(0), + m_y2(0), + m_x_size(0), + m_y_size(0), + m_x_gap(0), + m_y_gap(0), + m_is_visible(true), + m_is_dropdown(false), + m_mouse_focus(false), + m_id(WRONG_VALUE), + m_index(WRONG_VALUE), + m_gradient_colors_total(3), + m_is_object_tabs(WRONG_VALUE), + m_corner(CORNER_LEFT_UPPER), + m_anchor(ANCHOR_LEFT_UPPER), + m_program_name(PROGRAM_NAME), + m_program_type(PROGRAM_TYPE), + m_class_name("") + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CElement::~CElement(void) + { + } +//+------------------------------------------------------------------+ +//| Returns the object pointer of the control by index | +//+------------------------------------------------------------------+ +CChartObject *CElement::Object(const int index) + { + int array_size=::ArraySize(m_objects); +//--- Verifying the size of the object array + if(array_size<1) + { + ::Print(__FUNCTION__," > No ("+m_class_name+") objects in this control!"); + return(NULL); + } +//--- Correction in case the size was exceeded + int i=(index>=array_size)? array_size-1 :(index<0)? 0 : index; +//--- Return the object pointer + return(m_objects[i]); + } +//+------------------------------------------------------------------+ +//| Adds object pointer to an array | +//+------------------------------------------------------------------+ +void CElement::AddToArray(CChartObject &object) + { + int size=ObjectsElementTotal(); + ::ArrayResize(m_objects,size+1); + m_objects[size]=::GetPointer(object); + } +//+------------------------------------------------------------------+ +//| Initialization of the gradient array | +//+------------------------------------------------------------------+ +void CElement::InitColorArray(const color outer_color,const color hover_color,color &color_array[]) + { +//--- Array of the gradient colors + color colors[2]; + colors[0]=outer_color; + colors[1]=hover_color; +//--- Formation of the color array + m_clr.Gradient(colors,color_array,m_gradient_colors_total); + } +//+------------------------------------------------------------------+ +//| Changing of object color when hovering the cursor over it | +//+------------------------------------------------------------------+ +void CElement::ChangeObjectColor(const string name,const bool mouse_focus,const ENUM_OBJECT_PROPERTY_INTEGER property, + const color outer_color,const color hover_color,const color &color_array[]) + { + if(::ArraySize(color_array)<1) + return; +//--- Obtain the current object color + color current_color=(color)::ObjectGetInteger(m_chart_id,name,property); +//--- If the cursor is over the object + if(mouse_focus) + { + //--- Leave, if the specified color has been reached + if(current_color==hover_color) + return; + //--- Move from the first to the last one + for(int i=0; i=0; i--) + { + //--- If colors do not match, move to the following + if(color_array[i]!=current_color) + continue; + //--- + color new_color=(i-1<0)? color_array[i]: color_array[i-1]; + //--- Change color + ::ObjectSetInteger(m_chart_id,name,property,new_color); + break; + } + } + } +//+------------------------------------------------------------------+ diff --git a/ProgressBars/Enums.mqh b/ProgressBars/Enums.mqh new file mode 100644 index 0000000..0757682 Binary files /dev/null and b/ProgressBars/Enums.mqh differ diff --git a/ProgressBars/Objects.mqh b/ProgressBars/Objects.mqh new file mode 100644 index 0000000..d0067ec --- /dev/null +++ b/ProgressBars/Objects.mqh @@ -0,0 +1,306 @@ +//+------------------------------------------------------------------+ +//| Objects.mqh | +//| Copyright 2023, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#include "Enums.mqh" +#include "Defines.mqh" +#include +#include +//--- List of classes in file for a quick navigation (Alt+G) +class CRectLabel; +class CEdit; +class CLabel; +class CBmpLabel; +class CButton; +//+------------------------------------------------------------------+ +//| Class with additional properties for the Rectangle Label object | +//+------------------------------------------------------------------+ +class CRectLabel : public CChartObjectRectLabel + { +protected: + int m_x; + int m_y; + int m_x2; + int m_y2; + int m_x_gap; + int m_y_gap; + int m_x_size; + int m_y_size; + bool m_mouse_focus; +public: + CRectLabel(void); + ~CRectLabel(void); + //--- Coordinates + int X(void) { return(m_x); } + void X(const int x) { m_x=x; } + int Y(void) { return(m_y); } + void Y(const int y) { m_y=y; } + int X2(void) { return(m_x+m_x_size); } + int Y2(void) { return(m_y+m_y_size); } + //--- Indents from the edge point (xy) + int XGap(void) { return(m_x_gap); } + void XGap(const int x_gap) { m_x_gap=x_gap; } + int YGap(void) { return(m_y_gap); } + void YGap(const int y_gap) { m_y_gap=y_gap; } + //--- Sizes + int XSize(void) { return(m_x_size); } + void XSize(const int x_size) { m_x_size=x_size; } + int YSize(void) { return(m_y_size); } + void YSize(const int y_size) { m_y_size=y_size; } + //--- Focus + bool MouseFocus(void) { return(m_mouse_focus); } + void MouseFocus(const bool focus) { m_mouse_focus=focus; } + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CRectLabel::CRectLabel(void) : m_x(0), + m_y(0), + m_x2(0), + m_y2(0), + m_x_gap(0), + m_y_gap(0), + m_x_size(0), + m_y_size(0), + m_mouse_focus(false) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CRectLabel::~CRectLabel(void) + { + } +//+------------------------------------------------------------------+ +//| Class with additional properties for the Edit object | +//+------------------------------------------------------------------+ +class CEdit : public CChartObjectEdit + { +protected: + int m_x; + int m_y; + int m_x2; + int m_y2; + int m_x_gap; + int m_y_gap; + int m_x_size; + int m_y_size; + bool m_mouse_focus; +public: + CEdit(void); + ~CEdit(void); + //--- Coordinates + int X(void) { return(m_x); } + void X(const int x) { m_x=x; } + int Y(void) { return(m_y); } + void Y(const int y) { m_y=y; } + int X2(void) { return(m_x+m_x_size); } + int Y2(void) { return(m_y+m_y_size); } + //--- Indents from the edge point (xy) + int XGap(void) { return(m_x_gap); } + void XGap(const int x_gap) { m_x_gap=x_gap; } + int YGap(void) { return(m_y_gap); } + void YGap(const int y_gap) { m_y_gap=y_gap; } + //--- Sizes + int XSize(void) { return(m_x_size); } + void XSize(const int x_size) { m_x_size=x_size; } + int YSize(void) { return(m_y_size); } + void YSize(const int y_size) { m_y_size=y_size; } + //--- Focus + bool MouseFocus(void) { return(m_mouse_focus); } + void MouseFocus(const bool focus) { m_mouse_focus=focus; } + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CEdit::CEdit(void) : m_x(0), + m_y(0), + m_x2(0), + m_y2(0), + m_x_gap(0), + m_y_gap(0), + m_x_size(0), + m_y_size(0), + m_mouse_focus(false) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CEdit::~CEdit(void) + { + } +//+------------------------------------------------------------------+ +//| Class with additional properties for the Label object | +//+------------------------------------------------------------------+ +class CLabel : public CChartObjectLabel + { +protected: + int m_x; + int m_y; + int m_x2; + int m_y2; + int m_x_gap; + int m_y_gap; + int m_x_size; + int m_y_size; +public: + CLabel(void); + ~CLabel(void); + //--- Coordinates + int X(void) { return(m_x); } + void X(const int x) { m_x=x; } + int Y(void) { return(m_y); } + void Y(const int y) { m_y=y; } + int X2(void) { return(m_x+m_x_size); } + int Y2(void) { return(m_y+m_y_size); } + //--- Indents from the edge point (xy) + int XGap(void) { return(m_x_gap); } + void XGap(const int x_gap) { m_x_gap=x_gap; } + int YGap(void) { return(m_y_gap); } + void YGap(const int y_gap) { m_y_gap=y_gap; } + //--- Sizes + int XSize(void) { return(m_x_size); } + void XSize(const int x_size) { m_x_size=x_size; } + int YSize(void) { return(m_y_size); } + void YSize(const int y_size) { m_y_size=y_size; } + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CLabel::CLabel(void) : m_x(0), + m_y(0), + m_x2(0), + m_y2(0), + m_x_gap(0), + m_y_gap(0), + m_x_size(0), + m_y_size(0) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CLabel::~CLabel(void) + { + } +//+------------------------------------------------------------------+ +//| Class with additional properties for the Bmp Label object | +//+------------------------------------------------------------------+ +class CBmpLabel : public CChartObjectBmpLabel + { +protected: + int m_x; + int m_y; + int m_x2; + int m_y2; + int m_x_gap; + int m_y_gap; + int m_x_size; + int m_y_size; + bool m_mouse_focus; +public: + CBmpLabel(void); + ~CBmpLabel(void); + //--- Coordinates + int X(void) { return(m_x); } + void X(const int x) { m_x=x; } + int Y(void) { return(m_y); } + void Y(const int y) { m_y=y; } + int X2(void) { return(m_x+m_x_size); } + int Y2(void) { return(m_y+m_y_size); } + //--- Indents from the edge point (xy) + int XGap(void) { return(m_x_gap); } + void XGap(const int x_gap) { m_x_gap=x_gap; } + int YGap(void) { return(m_y_gap); } + void YGap(const int y_gap) { m_y_gap=y_gap; } + //--- Sizes + int XSize(void) { return(m_x_size); } + void XSize(const int x_size) { m_x_size=x_size; } + int YSize(void) { return(m_y_size); } + void YSize(const int y_size) { m_y_size=y_size; } + //--- Focus + bool MouseFocus(void) { return(m_mouse_focus); } + void MouseFocus(const bool focus) { m_mouse_focus=focus; } + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CBmpLabel::CBmpLabel(void) : m_x(0), + m_y(0), + m_x2(0), + m_y2(0), + m_x_gap(0), + m_y_gap(0), + m_x_size(0), + m_y_size(0), + m_mouse_focus(false) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CBmpLabel::~CBmpLabel(void) + { + } +//+------------------------------------------------------------------+ +//| Class with additional properties for the Edit object | +//+------------------------------------------------------------------+ +class CButton : public CChartObjectButton + { +protected: + int m_x; + int m_y; + int m_x2; + int m_y2; + int m_x_gap; + int m_y_gap; + int m_x_size; + int m_y_size; + bool m_mouse_focus; +public: + CButton(void); + ~CButton(void); + //--- Coordinates + int X(void) { return(m_x); } + void X(const int x) { m_x=x; } + int Y(void) { return(m_y); } + void Y(const int y) { m_y=y; } + int X2(void) { return(m_x+m_x_size); } + int Y2(void) { return(m_y+m_y_size); } + //--- Indents from the edge point (xy) + int XGap(void) { return(m_x_gap); } + void XGap(const int x_gap) { m_x_gap=x_gap; } + int YGap(void) { return(m_y_gap); } + void YGap(const int y_gap) { m_y_gap=y_gap; } + //--- Sizes + int XSize(void) { return(m_x_size); } + void XSize(const int x_size) { m_x_size=x_size; } + int YSize(void) { return(m_y_size); } + void YSize(const int y_size) { m_y_size=y_size; } + //--- Focus + bool MouseFocus(void) { return(m_mouse_focus); } + void MouseFocus(const bool focus) { m_mouse_focus=focus; } + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CButton::CButton(void) : m_x(0), + m_y(0), + m_x2(0), + m_y2(0), + m_x_gap(0), + m_y_gap(0), + m_x_size(0), + m_y_size(0), + m_mouse_focus(false) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CButton::~CButton(void) + { + } +//+------------------------------------------------------------------+ diff --git a/ProgressBars/Window.mqh b/ProgressBars/Window.mqh new file mode 100644 index 0000000..d94f42b Binary files /dev/null and b/ProgressBars/Window.mqh differ diff --git a/ProgressBars/WndContainer.mqh b/ProgressBars/WndContainer.mqh new file mode 100644 index 0000000..2107067 Binary files /dev/null and b/ProgressBars/WndContainer.mqh differ diff --git a/ProgressBars/WndEvents.mqh b/ProgressBars/WndEvents.mqh new file mode 100644 index 0000000..938d75f Binary files /dev/null and b/ProgressBars/WndEvents.mqh differ diff --git a/Retrace/Button.mqh b/Retrace/Button.mqh new file mode 100644 index 0000000..f2a9a0d --- /dev/null +++ b/Retrace/Button.mqh @@ -0,0 +1,152 @@ +//+------------------------------------------------------------------+ +//| Button.mqh | +//| Copyright 2000-2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#include +#include +#include "Colors.mqh" +#include "Font.mqh" +#include "Setting.mqh" +//+------------------------------------------------------------------+ +//| Class CButton | +//| Usage: control that is displayed by | +//| the CChartObjectButton object | +//+------------------------------------------------------------------+ +class CButton : public CWndObj + { +private: + CThemes m_Themes; + CFont m_Fonts; + CChartObjectButton m_button; // chart object + +public: + CButton(void); + ~CButton(void); + //--- create + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); + //--- state + bool Pressed(void) const { return(m_button.State()); } + bool Pressed(const bool pressed) { return(m_button.State(pressed)); } + //--- properties + bool Locking(void) const { return(IS_CAN_LOCK); } + void Locking(const bool flag); + +protected: + //--- handlers of object settings + virtual bool OnSetText(void) { return(m_button.Description(m_text)); } + virtual bool OnSetColor(void) { return(m_button.Color(m_color)); } + virtual bool OnSetColorBackground(void) { return(m_button.BackColor(m_color_background)); } + virtual bool OnSetColorBorder(void) { return(m_button.BorderColor(m_color_border)); } + virtual bool OnSetFont(void) { return(m_button.Font(m_Fonts.FontsByIndex((int)Sets.FontName))); } + virtual bool OnSetFontSize(void) { return(m_button.FontSize(m_font_size)); } + //--- internal event handlers + virtual bool OnCreate(void); + virtual bool OnShow(void); + virtual bool OnHide(void); + virtual bool OnMove(void); + virtual bool OnResize(void); + //--- ����� ����������� + virtual bool OnMouseDown(void); + virtual bool OnMouseUp(void); + }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CButton::CButton(void) + { + m_Themes.ApplyTheme((int)Sets.Themes); + m_color =m_Themes.CONTROLS_BUTTON_TEXT; + m_color_background=m_Themes.CONTROLS_BUTTON_DISABLE; + m_color_border =CONTROLS_BUTTON_COLOR_BORDER; + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CButton::~CButton(void) + { + } +//+------------------------------------------------------------------+ +//| Create a control | +//+------------------------------------------------------------------+ +bool CButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) + { +//--- call method of the parent class + if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2)) + return(false); +//--- create the chart object + if(!m_button.Create(chart,name,subwin,x1,y1,Width(),Height())) + return(false); +//--- call the settings handler + return(OnChange()); + } +//+------------------------------------------------------------------+ +//| Locking flag | +//+------------------------------------------------------------------+ +void CButton::Locking(const bool flag) + { + if(flag) + PropFlagsSet(WND_PROP_FLAG_CAN_LOCK); + else + PropFlagsReset(WND_PROP_FLAG_CAN_LOCK); + } +//+------------------------------------------------------------------+ +//| Create object on chart | +//+------------------------------------------------------------------+ +bool CButton::OnCreate(void) + { +//--- create the chart object by previously set parameters + return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height())); + } +//+------------------------------------------------------------------+ +//| Display object on chart | +//+------------------------------------------------------------------+ +bool CButton::OnShow(void) + { + return(m_button.Timeframes(OBJ_ALL_PERIODS)); + } +//+------------------------------------------------------------------+ +//| Hide object from chart | +//+------------------------------------------------------------------+ +bool CButton::OnHide(void) + { + return(m_button.Timeframes(OBJ_NO_PERIODS)); + } +//+------------------------------------------------------------------+ +//| Absolute movement of the chart object | +//+------------------------------------------------------------------+ +bool CButton::OnMove(void) + { +//--- position the chart object + return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top)); + } +//+------------------------------------------------------------------+ +//| Resize the chart object | +//+------------------------------------------------------------------+ +bool CButton::OnResize(void) + { +//--- resize the chart object + return(m_button.X_Size(m_rect.Width()) && m_button.Y_Size(m_rect.Height())); + } +//+------------------------------------------------------------------+ +//| Handler of click on the left mouse button | +//+------------------------------------------------------------------+ +bool CButton::OnMouseDown(void) + { + if(!IS_CAN_LOCK) + Pressed(!Pressed()); +//--- call of the method of the parent class + return(CWnd::OnMouseDown()); + } +//+------------------------------------------------------------------+ +//| Handler of click on the left mouse button | +//+------------------------------------------------------------------+ +bool CButton::OnMouseUp(void) + { +//--- depress the button if it is not fixed + if(m_button.State() && !IS_CAN_LOCK) + m_button.State(false); +//--- call of the method of the parent class + return(CWnd::OnMouseUp()); + } +//+------------------------------------------------------------------+ diff --git a/Retrace/Colors.mqh b/Retrace/Colors.mqh new file mode 100644 index 0000000..0fc5ddc --- /dev/null +++ b/Retrace/Colors.mqh @@ -0,0 +1,685 @@ + +enum ThemeType { + Midnight_Blue, + Periwinkle_Dream, + Lime_Breeze, + Autumn_Spice, + Winter_Wonderland, + Spring_Blossom, + Summer_Breeze, + Midnight_Dream, + Tropical_Paradise, + // Midnight_Blue, + Forest_Green, + Sunset_Orange, + Calm_Pastel, + Ocean_Breeze, + Desert_Sand, + Crimson_Rose, + Cool_Mint, + Black_Theme, + Brown_Theme, + White_Theme_1, + White_Theme_2 + // Add more themes here as needed +}; + + + +class CThemes +{ +public: + color CONTROLS_BUTTON_TEXT, CONTROLS_BUTTON_ENABLE, CONTROLS_BUTTON_DISABLE, + CONTROLS_LABEL_TEXT, CONTROLS_LABEL_BACKGROUND, CONTROLS_LABEL_TEXT_TOOLTIP, CONTROLS_LABEL_TEXT_TITLE, CONTROLS_LABEL_TITLE_BACKGROUND, CONTROLS_LABEL_TEXT_ARM, CONTROLS_LABEL_TEXT_ANSWER, + CONTROLS_LABEL_LOG_TEXT, + CONTROL_EDIT_TEXT, CONTROL_EDIT_BACKGROUND, CONTROL_EDIT_BORDER, + CONTROL_COMBOBOX_BACKGROUND, CONTROL_COMBOBOX_BORDER, CONTROL_COMBOBOX_BACKGROUND_ITEM, CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL, + CONTROL_BACK_BACGROUND, CONTROL_BORDER_BACKGROUND, + CONTROL_CLINET, CONTROL_CLINET_BACKGROUND, + CONTROL_CAPTION_TEXT, CONTROL_CAPTION_BACKGROUND, CONTROL_CAPTION_BORDERP, + CONTROL_PROGRESS_BACKGROUND, CONTROL_PROGRESS_FORGROUND, + CONTROL_LICENSE_BIGGER, CONTROL_LICENSE_SMALLER; +// CONTROLS_LABEL_TEXT_ARM +// CONTROLS_LABEL_LOG_TEXT +// CONTROLS_LABEL_TEXT_ANSWER + + virtual color AdjustBrightness(color baseColor, double factor); + virtual void ApplyThemeBrightness(bool isDarkMode); + void ApplyTheme(int theme) + { + switch (theme) + { + default: + case Midnight_Blue: + { + CONTROLS_BUTTON_TEXT = C'255,255,255'; // C'182,182,182' + CONTROLS_BUTTON_ENABLE = C'0,0,139'; + CONTROLS_BUTTON_DISABLE = C'169,169,169'; + CONTROLS_LABEL_TEXT = C'224,255,255'; + CONTROLS_LABEL_TEXT_ARM = C'255,255,0'; + CONTROLS_LABEL_LOG_TEXT = C'205,247,21'; + CONTROLS_LABEL_TEXT_ANSWER = C'160,252,252'; + CONTROLS_LABEL_BACKGROUND = C'0,0,139'; + CONTROLS_LABEL_TEXT_TOOLTIP = C'224,255,255'; + CONTROLS_LABEL_TEXT_TITLE = C'255,255,0'; + CONTROLS_LABEL_TITLE_BACKGROUND = C'0,0,139'; + CONTROL_EDIT_TEXT = C'255,255,255'; + CONTROL_EDIT_BORDER = C'0,191,255'; + CONTROL_EDIT_BACKGROUND = C'0,0,139'; + CONTROL_COMBOBOX_BACKGROUND = C'0,0,139'; + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,255,0'; + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'224,255,255'; + CONTROL_BACK_BACGROUND = C'0,211,217'; + CONTROL_BORDER_BACKGROUND = C'0,191,255'; + CONTROL_CLINET = C'255,255,255'; + CONTROL_CLINET_BACKGROUND = C'0,0,139'; + CONTROL_CAPTION_TEXT = C'255,255,255'; + CONTROL_CAPTION_BACKGROUND = C'0,0,139'; + CONTROL_CAPTION_BORDERP = C'0,191,255'; + CONTROL_PROGRESS_BACKGROUND = C'114,235,1'; + CONTROL_PROGRESS_FORGROUND = C'255,255,255'; + CONTROL_LICENSE_BIGGER = C'236,184,39'; + CONTROL_LICENSE_SMALLER = C'231,21,21'; + } + break; + + case Periwinkle_Dream: + { + CONTROLS_BUTTON_TEXT = C'78,73,73'; // White + CONTROLS_BUTTON_ENABLE = C'106,90,205'; // Slate Blue + CONTROLS_BUTTON_DISABLE = C'204,204,255'; // Periwinkle + CONTROLS_LABEL_TEXT = C'26,66,245'; // Crimson + CONTROLS_LABEL_TEXT_ARM = C'129,79,160'; + CONTROLS_LABEL_LOG_TEXT = C'26,194,245'; + CONTROLS_LABEL_TEXT_ANSWER = C'88,114,231'; + CONTROLS_LABEL_BACKGROUND = C'218,112,214'; // Orchid + CONTROLS_LABEL_TEXT_TOOLTIP = C'0,128,128'; // Teal + CONTROLS_LABEL_TEXT_TITLE = C'43,35,48'; // Coral + CONTROLS_LABEL_TITLE_BACKGROUND = C'106,90,205'; // Slate Blue + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'218,165,32'; // Goldenrod + CONTROL_EDIT_BACKGROUND = C'94,94,201'; // Periwinkle + CONTROL_COMBOBOX_BACKGROUND = C'94,94,201'; // Orchid + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'106,90,205'; // Slate Blue + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,127,80'; // Coral + CONTROL_BACK_BACGROUND = C'204,204,255'; // Periwinkle + CONTROL_BORDER_BACKGROUND = C'218,165,32'; // Goldenrod + CONTROL_CLINET = C'255,255,255'; // White + CONTROL_CLINET_BACKGROUND = C'218,112,214'; // Orchid + CONTROL_CAPTION_TEXT = C'255,255,255'; // White + CONTROL_CAPTION_BACKGROUND = C'106,90,205'; // Slate Blue + CONTROL_CAPTION_BORDERP = C'0,128,128'; // Teal + } + break; + + case Lime_Breeze: + { + CONTROLS_BUTTON_TEXT = C'0,100,0'; // Dark Green + CONTROLS_BUTTON_ENABLE = C'83,197,149'; // Lawn Green + CONTROLS_BUTTON_DISABLE = C'173,255,47'; // Green Yellow + CONTROLS_LABEL_TEXT = C'50,205,50'; // Lime Green + CONTROLS_LABEL_TEXT_ARM = C'11,141,228'; + CONTROLS_LABEL_LOG_TEXT = C'136,136,85'; + CONTROLS_LABEL_TEXT_ANSWER = C'4,255,4'; + CONTROLS_LABEL_BACKGROUND = C'240,255,240'; // Honeydew + CONTROLS_LABEL_TEXT_TOOLTIP = C'154,205,50'; // Yellow Green + CONTROLS_LABEL_TEXT_TITLE = C'24,24,22'; // Yellow + CONTROLS_LABEL_TITLE_BACKGROUND = C'124,252,0'; // Lawn Green + CONTROL_EDIT_TEXT = C'85,107,47'; // Dark Olive Green + CONTROL_EDIT_BORDER = C'173,255,47'; // Green Yellow + CONTROL_EDIT_BACKGROUND = C'240,255,240'; // Honeydew + CONTROL_COMBOBOX_BACKGROUND = C'124,252,0'; // Lawn Green + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'85,107,47'; // Dark Olive Green + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,255,0'; // Yellow + CONTROL_BACK_BACGROUND = C'173,255,47'; // Green Yellow + CONTROL_BORDER_BACKGROUND = C'85,107,47'; // Dark Olive Green + CONTROL_CLINET = C'255,255,255'; // White + CONTROL_CLINET_BACKGROUND = C'240,255,240'; // Honeydew + CONTROL_CAPTION_TEXT = C'73,50,205'; // Lime Green + CONTROL_CAPTION_BACKGROUND = C'124,252,0'; // Lawn Green + CONTROL_CAPTION_BORDERP = C'154,205,50'; // Yellow Green + + } + break; + + case Autumn_Spice: + { + CONTROLS_BUTTON_TEXT = C'82,41,11'; // Saddle Brown + CONTROLS_BUTTON_ENABLE = C'210,105,30'; // Chocolate + CONTROLS_BUTTON_DISABLE = C'160,82,45'; // Sienna + CONTROLS_LABEL_TEXT = C'255,228,181'; // Moccasin + CONTROLS_LABEL_TEXT_ARM = C'4,0,252'; + CONTROLS_LABEL_LOG_TEXT = C'125,240,110'; + CONTROLS_LABEL_TEXT_ANSWER = C'247,191,94'; + CONTROLS_LABEL_BACKGROUND = C'139,69,19'; // Saddle Brown + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,140,0'; // Dark Orange + CONTROLS_LABEL_TEXT_TITLE = C'94,92,205'; // Indian Red + CONTROLS_LABEL_TITLE_BACKGROUND = C'210,105,30'; // Chocolate + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'205,133,63'; // Peru + CONTROL_EDIT_BACKGROUND = C'139,69,19'; // Saddle Brown + CONTROL_COMBOBOX_BACKGROUND = C'210,105,30'; // Chocolate + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,228,181'; // Moccasin + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'139,69,19'; // Saddle Brown + CONTROL_BACK_BACGROUND = C'160,82,45'; // Sienna + CONTROL_BORDER_BACKGROUND = C'205,133,63'; // Peru + CONTROL_CLINET = C'255,245,238'; // Seashell + CONTROL_CLINET_BACKGROUND = C'210,105,30'; // Chocolate + CONTROL_CAPTION_TEXT = C'139,69,19'; // Saddle Brown + CONTROL_CAPTION_BACKGROUND = C'255,228,181'; // Moccasin + CONTROL_CAPTION_BORDERP = C'205,92,92'; // Indian Red + } + break; + + case Winter_Wonderland: + { + CONTROLS_BUTTON_TEXT = C'255,255,255'; // White + CONTROLS_BUTTON_ENABLE = C'70,130,180'; // Steel Blue + CONTROLS_BUTTON_DISABLE = C'121,168,230'; // Pale Turquoise + CONTROLS_LABEL_TEXT = C'240,248,255'; // Alice Blue + CONTROLS_LABEL_TEXT_ANSWER = C'215,233,250'; + CONTROLS_LABEL_TEXT_ARM = C'0,0,255'; + CONTROLS_LABEL_LOG_TEXT = C'21,255,21'; + CONTROLS_LABEL_BACKGROUND = C'70,130,180'; // Steel Blue + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,215,0'; // Gold + CONTROLS_LABEL_TEXT_TITLE = C'0,0,139'; // Dark Blue + CONTROLS_LABEL_TITLE_BACKGROUND = C'70,130,180'; // Steel Blue + CONTROL_EDIT_TEXT = C'0,0,0'; // Black + CONTROL_EDIT_BORDER = C'176,224,230'; // Powder Blue + CONTROL_EDIT_BACKGROUND = C'151,185,216'; // Alice Blue + CONTROL_COMBOBOX_BACKGROUND = C'151,185,216'; // Steel Blue + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,255,255'; // White + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'0,0,139'; // Dark Blue + CONTROL_BACK_BACGROUND = C'175,238,238'; // Pale Turquoise + CONTROL_BORDER_BACKGROUND = C'176,224,230'; // Powder Blue + CONTROL_CLINET = C'255,250,250'; // Snow + CONTROL_CLINET_BACKGROUND = C'70,130,180'; // Steel Blue + CONTROL_CAPTION_TEXT = C'255,255,255'; // White + CONTROL_CAPTION_BACKGROUND = C'70,130,180'; // Steel Blue + CONTROL_CAPTION_BORDERP = C'255,215,0'; // Gold + } + break; + + case Spring_Blossom: + { + CONTROLS_BUTTON_TEXT = C'255,105,180'; // Hot Pink + CONTROLS_BUTTON_ENABLE = C'144,238,144'; // Light Green + CONTROLS_BUTTON_DISABLE = C'255,182,193'; // Light Pink + CONTROLS_LABEL_TEXT = C'0,0,236'; // Lavender Blush + CONTROLS_LABEL_TEXT_ARM = C'255,20,147'; + CONTROLS_LABEL_LOG_TEXT = C'40,223,236'; + CONTROLS_LABEL_TEXT_ANSWER = C'109,109,236'; + CONTROLS_LABEL_BACKGROUND = C'144,238,144'; // Light Green + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,69,0'; // Red Orange + CONTROLS_LABEL_TEXT_TITLE = C'255,20,147'; // Deep Pink + CONTROLS_LABEL_TITLE_BACKGROUND = C'144,238,144'; // Light Green + CONTROL_EDIT_TEXT = C'0,0,0'; // Black + CONTROL_EDIT_BORDER = C'0,255,127'; // Spring Green + CONTROL_EDIT_BACKGROUND = C'255,228,225'; // Lavender Blush + CONTROL_COMBOBOX_BACKGROUND = C'144,238,144'; // Light Green + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,255,240'; // Ivory + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,20,147'; // Deep Pink + CONTROL_BACK_BACGROUND = C'255,182,193'; // Light Pink + CONTROL_BORDER_BACKGROUND = C'0,255,127'; // Spring Green + CONTROL_CLINET = C'255,250,250'; // Snow + CONTROL_CLINET_BACKGROUND = C'144,238,144'; // Light Green + CONTROL_CAPTION_TEXT = C'255,105,180'; // Hot Pink + CONTROL_CAPTION_BACKGROUND = C'255,228,225'; // Lavender Blush + CONTROL_CAPTION_BORDERP = C'255,20,147'; // Deep Pink + } + break; + + case Summer_Breeze: + { + CONTROLS_BUTTON_TEXT = C'0,0,0'; // Black + CONTROLS_BUTTON_ENABLE = C'0,204,102'; // Medium Sea Green + CONTROLS_BUTTON_DISABLE = C'192,192,192'; // Light Gray + CONTROLS_LABEL_TEXT = C'0,102,204'; // Dodger Blue + CONTROLS_LABEL_TEXT_ARM = C'255,99,71'; + CONTROLS_LABEL_LOG_TEXT = C'122,138,136'; + CONTROLS_LABEL_TEXT_ANSWER = C'98,145,192'; + CONTROLS_LABEL_BACKGROUND = C'255,255,255'; // White + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,69,0'; // Red Orange + CONTROLS_LABEL_TEXT_TITLE = C'255,99,71'; // Tomato + CONTROLS_LABEL_TITLE_BACKGROUND = C'0,204,102'; // Medium Sea Green + CONTROL_EDIT_TEXT = C'0,0,0'; // Black + CONTROL_EDIT_BORDER = C'0,204,204'; // Turquoise + CONTROL_EDIT_BACKGROUND = C'255,255,255'; // White + CONTROL_COMBOBOX_BACKGROUND = C'0,204,102'; // Medium Sea Green + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'173,216,230'; // Light Blue + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'0,0,0'; // Black + CONTROL_BACK_BACGROUND = C'255,215,0'; // Gold + CONTROL_BORDER_BACKGROUND = C'0,204,204'; // Turquoise + CONTROL_CLINET = C'255,250,205'; // Lemon Chiffon + CONTROL_CLINET_BACKGROUND = C'240,248,255'; // Alice Blue + CONTROL_CAPTION_TEXT = C'0,0,0'; // Black + CONTROL_CAPTION_BACKGROUND = C'173,216,230'; // Light Blue + CONTROL_CAPTION_BORDERP = C'255,69,0'; // Red Orange + } + break; + + + case Midnight_Dream: + { + CONTROLS_BUTTON_TEXT = C'224,102,255'; // Medium Purple + CONTROLS_BUTTON_ENABLE = C'75,0,130'; // Indigo + CONTROLS_BUTTON_DISABLE = C'138,43,226'; // Blue Violet + CONTROLS_LABEL_TEXT = C'255,250,250'; // Snow + CONTROLS_LABEL_TEXT_ARM = C'0,49,211'; + CONTROLS_LABEL_LOG_TEXT = C'5,248,208'; + CONTROLS_LABEL_TEXT_ANSWER = C'250,206,206'; + CONTROLS_LABEL_BACKGROUND = C'75,0,130'; // Indigo + CONTROLS_LABEL_TEXT_TOOLTIP = C'148,0,211'; // Dark Orchid + CONTROLS_LABEL_TEXT_TITLE = C'186,85,211'; // Orchid + CONTROLS_LABEL_TITLE_BACKGROUND = C'75,0,130'; // Indigo + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'123,104,238'; // Medium Slate Blue + CONTROL_EDIT_BACKGROUND = C'75,0,130'; // Indigo + CONTROL_COMBOBOX_BACKGROUND = C'75,0,130'; // Indigo + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'224,102,255'; // Medium Purple + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,250,250'; // Snow + CONTROL_BACK_BACGROUND = C'138,43,226'; // Blue Violet + CONTROL_BORDER_BACKGROUND = C'123,104,238'; // Medium Slate Blue + CONTROL_CLINET = C'240,248,255'; // Alice Blue + CONTROL_CLINET_BACKGROUND = C'75,0,130'; // Indigo + CONTROL_CAPTION_TEXT = C'224,102,255'; // Medium Purple + CONTROL_CAPTION_BACKGROUND = C'255,250,250'; // Snow + CONTROL_CAPTION_BORDERP = C'148,0,211'; // Dark Orchid + } + break; + + case Tropical_Paradise: + { + CONTROLS_BUTTON_TEXT = C'48,47,45'; // Gold + CONTROLS_BUTTON_ENABLE = C'0,255,127'; // Spring Green + CONTROLS_BUTTON_DISABLE = C'255,140,0'; // Dark Orange + CONTROLS_LABEL_TEXT = C'255,228,196'; // Misty Rose + CONTROLS_LABEL_TEXT_ARM = C'0,60,255'; + CONTROLS_LABEL_LOG_TEXT = C'131,136,153'; + CONTROLS_LABEL_TEXT_ANSWER = C'250,207,154'; + CONTROLS_LABEL_BACKGROUND = C'0,191,255'; // Deep Sky Blue + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,69,0'; // Red Orange + CONTROLS_LABEL_TEXT_TITLE = C'0,60,255'; // Magenta + CONTROLS_LABEL_TITLE_BACKGROUND = C'0,191,255'; // Deep Sky Blue + CONTROL_EDIT_TEXT = C'0,0,0'; // Black + CONTROL_EDIT_BORDER = C'60,179,113'; // Medium Sea Green + CONTROL_EDIT_BACKGROUND = C'255,228,196'; // Misty Rose + CONTROL_COMBOBOX_BACKGROUND = C'0,191,255'; // Deep Sky Blue + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,255,224'; // Light Yellow + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'0,255,127'; // Spring Green + CONTROL_BACK_BACGROUND = C'255,140,0'; // Dark Orange + CONTROL_BORDER_BACKGROUND = C'60,179,113'; // Medium Sea Green + CONTROL_CLINET = C'255,250,250'; // Snow + CONTROL_CLINET_BACKGROUND = C'0,191,255'; // Deep Sky Blue + CONTROL_CAPTION_TEXT = C'41,138,230'; // Gold + CONTROL_CAPTION_BACKGROUND = C'255,228,196'; // Misty Rose + CONTROL_CAPTION_BORDERP = C'255,69,0'; // Red Orange + } + break; + + case Forest_Green: + { + CONTROLS_BUTTON_TEXT = C'240,255,240'; // Honeydew + CONTROLS_BUTTON_ENABLE = C'34,139,34'; // Forest Green + CONTROLS_BUTTON_DISABLE = C'120,128,105'; // Olive Green + CONTROLS_LABEL_TEXT = C'245,245,220'; // Beige + CONTROLS_LABEL_TEXT_ARM = C'173,255,47'; + CONTROLS_LABEL_LOG_TEXT = C'118,170,238'; + CONTROLS_LABEL_TEXT_ANSWER = C'250,250,185'; + CONTROLS_LABEL_BACKGROUND = C'34,139,34'; // Forest Green + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,255,240'; // Ivory + CONTROLS_LABEL_TEXT_TITLE = C'173,255,47'; // Light Green + CONTROLS_LABEL_TITLE_BACKGROUND = C'34,139,34'; // Forest Green + CONTROL_EDIT_TEXT = C'240,255,240'; // Honeydew + CONTROL_EDIT_BORDER = C'0,100,0'; // Dark Green + CONTROL_EDIT_BACKGROUND = C'107,142,35'; // Olive Green + CONTROL_COMBOBOX_BACKGROUND = C'34,139,34'; // Forest Green + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'173,255,47'; // Light Green + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,255,240'; // Ivory + CONTROL_BACK_BACGROUND = C'107,142,35'; // Olive Green + CONTROL_BORDER_BACKGROUND = C'0,100,0'; // Dark Green + CONTROL_CLINET = C'255,255,255'; // White + CONTROL_CLINET_BACKGROUND = C'34,139,34'; // Forest Green + CONTROL_CAPTION_TEXT = C'255,255,240'; // Ivory + CONTROL_CAPTION_BACKGROUND = C'34,139,34'; // Forest Green + CONTROL_CAPTION_BORDERP = C'0,100,0'; + } + break; + + case Sunset_Orange: + { + CONTROLS_BUTTON_TEXT = C'255,255,255'; // White + CONTROLS_BUTTON_ENABLE = C'255,69,0'; // Orange Red + CONTROLS_BUTTON_DISABLE = C'139,0,0'; // Dark Red + CONTROLS_LABEL_TEXT = C'255,228,181'; // Light Beige + CONTROLS_LABEL_TEXT_ARM = C'255,255,0'; + CONTROLS_LABEL_LOG_TEXT = C'179,163,114'; + CONTROLS_LABEL_TEXT_ANSWER = C'252,213,147'; + CONTROLS_LABEL_BACKGROUND = C'255,140,0'; // Dark Orange + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,165,0'; // Orange + CONTROLS_LABEL_TEXT_TITLE = C'255,255,0'; // Bright Yellow + CONTROLS_LABEL_TITLE_BACKGROUND = C'255,140,0'; // Dark Orange + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'255,69,0'; // Orange Red + CONTROL_EDIT_BACKGROUND = C'139,0,0'; // Dark Red + CONTROL_COMBOBOX_BACKGROUND = C'255,140,0'; // Dark Orange + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,255,0'; // Bright Yellow + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,228,181'; // Light Beige + CONTROL_BACK_BACGROUND = C'255,69,0'; // Orange Red + CONTROL_BORDER_BACKGROUND = C'139,0,0'; // Dark Red + CONTROL_CLINET = C'255,255,255'; // White + CONTROL_CLINET_BACKGROUND = C'255,140,0'; // Dark Orange + CONTROL_CAPTION_TEXT = C'255,255,255'; // White + CONTROL_CAPTION_BACKGROUND = C'255,140,0'; // Dark Orange + CONTROL_CAPTION_BORDERP = C'255,69,0'; + } + break; + + case Calm_Pastel: + { + CONTROLS_BUTTON_TEXT = C'0,0,0'; // Black + CONTROLS_BUTTON_ENABLE = C'255,182,193'; // Light Pink + CONTROLS_BUTTON_DISABLE = C'176,224,230'; // Powder Blue + CONTROLS_LABEL_TEXT = C'19,80,248'; // Medium Aquamarine + CONTROLS_LABEL_TEXT_ARM = C'250,128,114'; + CONTROLS_LABEL_LOG_TEXT = C'137,250,114'; + CONTROLS_LABEL_TEXT_ANSWER = C'97,138,250'; + CONTROLS_LABEL_BACKGROUND = C'255,228,196'; // Pastel Peach + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,218,185'; // Peach Puff + CONTROLS_LABEL_TEXT_TITLE = C'250,128,114'; // Salmon + CONTROLS_LABEL_TITLE_BACKGROUND = C'255,228,196'; // Pastel Peach + CONTROL_EDIT_TEXT = C'0,0,0'; // Black + CONTROL_EDIT_BORDER = C'139,182,231'; // Powder Blue + CONTROL_EDIT_BACKGROUND = C'255,228,196'; // Pastel Peach + CONTROL_COMBOBOX_BACKGROUND = C'255,228,196'; // Pastel Peach + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,218,185'; // Peach Puff + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'102,205,170'; // Medium Aquamarine + CONTROL_BACK_BACGROUND = C'255,228,196'; // Pastel Peach + CONTROL_BORDER_BACKGROUND = C'255,182,193'; // Light Pink + CONTROL_CLINET = C'0,0,0'; // Black + CONTROL_CLINET_BACKGROUND = C'255,228,196'; // Pastel Peach + CONTROL_CAPTION_TEXT = C'0,0,0'; // Black + CONTROL_CAPTION_BACKGROUND = C'255,228,196'; // Pastel Peach + CONTROL_CAPTION_BORDERP = C'255,182,193'; + } + break; + + case Ocean_Breeze: + { + CONTROLS_BUTTON_TEXT = C'255,255,255'; // White + CONTROLS_BUTTON_ENABLE = C'0,105,148'; // Deep Sea Blue + CONTROLS_BUTTON_DISABLE = C'100,149,237'; // Cornflower Blue + CONTROLS_LABEL_TEXT = C'240,255,255'; // Azure + CONTROLS_LABEL_TEXT_ARM = C'173,216,230'; + CONTROLS_LABEL_LOG_TEXT = C'173,216,230'; + CONTROLS_LABEL_TEXT_ANSWER = C'117,255,225'; + CONTROLS_LABEL_BACKGROUND = C'70,130,180'; // Steel Blue + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,255,240'; // Ivory + CONTROLS_LABEL_TEXT_TITLE = C'173,216,230'; // Light Blue + CONTROLS_LABEL_TITLE_BACKGROUND = C'0,105,148'; // Deep Sea Blue + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'100,149,237'; // Cornflower Blue + CONTROL_EDIT_BACKGROUND = C'0,105,148'; // Deep Sea Blue + CONTROL_COMBOBOX_BACKGROUND = C'70,130,180'; // Steel Blue + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'173,216,230'; // Light Blue + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'240,255,255'; // Azure + CONTROL_BACK_BACGROUND = C'0,105,148'; // Deep Sea Blue + CONTROL_BORDER_BACKGROUND = C'70,130,180'; // Steel Blue + CONTROL_CLINET = C'255,255,255'; // White + CONTROL_CLINET_BACKGROUND = C'0,105,148'; // Deep Sea Blue + CONTROL_CAPTION_TEXT = C'255,255,255'; // White + CONTROL_CAPTION_BACKGROUND = C'0,105,148'; // Deep Sea Blue + CONTROL_CAPTION_BORDERP = C'100,149,237'; + } + break; + + case Desert_Sand: + { + CONTROLS_BUTTON_TEXT = C'139,69,19'; // Saddle Brown + CONTROLS_BUTTON_ENABLE = C'210,180,140'; // Tan + CONTROLS_BUTTON_DISABLE = C'244,164,96'; // Sandy Brown + CONTROLS_LABEL_TEXT = C'255,228,181'; // Moccasin + CONTROLS_LABEL_TEXT_ARM = C'82,80,78'; + CONTROLS_LABEL_LOG_TEXT = C'183,189,129'; + CONTROLS_LABEL_TEXT_ANSWER = C'253,244,227'; + CONTROLS_LABEL_BACKGROUND = C'210,180,140'; // Tan + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,235,205'; // Blanched Almond + CONTROLS_LABEL_TEXT_TITLE = C'82,80,78'; // Sandy Brown + CONTROLS_LABEL_TITLE_BACKGROUND = C'139,69,19'; // Saddle Brown + CONTROL_EDIT_TEXT = C'139,69,19'; // Saddle Brown + CONTROL_EDIT_BORDER = C'117,113,110'; // Sandy Brown + CONTROL_EDIT_BACKGROUND = C'255,228,181'; // Moccasin + CONTROL_COMBOBOX_BACKGROUND = C'210,180,140'; // Tan + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,235,205'; // Blanched Almond + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'244,164,96'; // Sandy Brown + CONTROL_BACK_BACGROUND = C'139,69,19'; // Saddle Brown + CONTROL_BORDER_BACKGROUND = C'210,180,140'; // Tan + CONTROL_CLINET = C'139,69,19'; // Saddle Brown + CONTROL_CLINET_BACKGROUND = C'210,180,140'; // Tan + CONTROL_CAPTION_TEXT = C'54,100,228'; // Moccasin + CONTROL_CAPTION_BACKGROUND = C'210,180,140'; // Tan + CONTROL_CAPTION_BORDERP = C'244,164,96'; + } + break; + + case Crimson_Rose: + { + CONTROLS_BUTTON_TEXT = C'255,255,255'; // White + CONTROLS_BUTTON_ENABLE = C'220,20,60'; // Crimson + CONTROLS_BUTTON_DISABLE = C'216,141,182'; // Light Pink + CONTROLS_LABEL_TEXT = C'255,240,245'; // Lavender Blush + CONTROLS_LABEL_TEXT_ARM = C'255,69,0'; + CONTROLS_LABEL_LOG_TEXT = C'0,217,255'; + CONTROLS_LABEL_TEXT_ANSWER = C'250,201,217'; + CONTROLS_LABEL_BACKGROUND = C'255,105,180'; // Hot Pink + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,182,193'; // Light Pink + CONTROLS_LABEL_TEXT_TITLE = C'255,69,0'; // Orange Red + CONTROLS_LABEL_TITLE_BACKGROUND = C'220,20,60'; // Crimson + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'255,105,180'; // Hot Pink + CONTROL_EDIT_BACKGROUND = C'255,69,0'; // Orange Red + CONTROL_COMBOBOX_BACKGROUND = C'220,20,60'; // Crimson + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,182,193'; // Light Pink + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,240,245'; // Lavender Blush + CONTROL_BACK_BACGROUND = C'255,69,0'; // Orange Red + CONTROL_BORDER_BACKGROUND = C'255,105,180'; // Hot Pink + CONTROL_CLINET = C'255,255,255'; // White + CONTROL_CLINET_BACKGROUND = C'255,105,180'; // Hot Pink + CONTROL_CAPTION_TEXT = C'255,255,255'; // White + CONTROL_CAPTION_BACKGROUND = C'255,69,0'; // Orange Red + CONTROL_CAPTION_BORDERP = C'220,20,60'; + } + break; + + case Cool_Mint: + { + CONTROLS_BUTTON_TEXT = C'0,100,0'; // Dark Green + CONTROLS_BUTTON_ENABLE = C'0,245,0'; // Pale Green + CONTROLS_BUTTON_DISABLE = C'0,250,154'; // Medium Spring Green + CONTROLS_LABEL_TEXT = C'165,84,46'; // Mint Cream + CONTROLS_LABEL_TEXT_ARM = C'25,106,199'; + CONTROLS_LABEL_LOG_TEXT = C'25,199,63'; + CONTROLS_LABEL_TEXT_ANSWER = C'165,84,46'; + CONTROLS_LABEL_BACKGROUND = C'152,251,152'; // Pale Green + CONTROLS_LABEL_TEXT_TOOLTIP = C'245,255,250'; // Mint Cream + CONTROLS_LABEL_TEXT_TITLE = C'25,106,199'; // Green + CONTROLS_LABEL_TITLE_BACKGROUND = C'0,250,154'; // Medium Spring Green + CONTROL_EDIT_TEXT = C'0,100,0'; // Dark Green + CONTROL_EDIT_BORDER = C'70,100,89'; // Medium Spring Green + CONTROL_EDIT_BACKGROUND = C'245,255,250'; // Mint Cream + CONTROL_COMBOBOX_BACKGROUND = C'152,251,152'; // Pale Green + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'0,250,154'; // Medium Spring Green + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'0,100,0'; // Dark Green + CONTROL_BACK_BACGROUND = C'0,250,154'; // Medium Spring Green + CONTROL_BORDER_BACKGROUND = C'152,251,152'; // Pale Green + CONTROL_CLINET = C'0,100,0'; // Dark Green + CONTROL_CLINET_BACKGROUND = C'152,251,152'; // Pale Green + CONTROL_CAPTION_TEXT = C'0,100,0'; // Dark Green + CONTROL_CAPTION_BACKGROUND = C'152,251,152'; // Pale Green + CONTROL_CAPTION_BORDERP = C'0,250,154'; + } + break; + + case Black_Theme: + { + CONTROLS_BUTTON_TEXT = C'255,255,255'; // White + CONTROLS_BUTTON_ENABLE = C'50,50,50'; // Dark Gray + CONTROLS_BUTTON_DISABLE = C'128,128,128'; // Gray + CONTROLS_LABEL_TEXT = C'255,255,255'; // White + CONTROLS_LABEL_TEXT_ARM = C'255,215,0'; + CONTROLS_LABEL_LOG_TEXT = C'255,166,0'; + CONTROLS_LABEL_TEXT_ANSWER = C'252,204,204'; + CONTROLS_LABEL_BACKGROUND = C'0,0,0'; // Black + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,69,0'; // Red Orange + CONTROLS_LABEL_TEXT_TITLE = C'255,215,0'; // Gold + CONTROLS_LABEL_TITLE_BACKGROUND = C'50,50,50'; // Dark Gray + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'128,128,128'; // Gray + CONTROL_EDIT_BACKGROUND = C'30,30,30'; // Darker Gray + CONTROL_COMBOBOX_BACKGROUND = C'50,50,50'; // Dark Gray + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'180,171,171'; // Darker Gray + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'255,255,255'; // White + CONTROL_BACK_BACGROUND = C'128,128,128'; // Black + CONTROL_BORDER_BACKGROUND = C'128,128,128'; // Gray + CONTROL_CLINET = C'50,50,50'; // Dark Gray + CONTROL_CLINET_BACKGROUND = C'30,30,30'; // Darker Gray + CONTROL_CAPTION_TEXT = C'255,255,255'; // White + CONTROL_CAPTION_BACKGROUND = C'0,0,0'; // Black + CONTROL_CAPTION_BORDERP = C'255,215,0'; // Gold + } + break; + + case Brown_Theme: + { + CONTROLS_BUTTON_TEXT = C'255,255,255'; // White + CONTROLS_BUTTON_ENABLE = C'139,69,19'; // Saddle Brown + CONTROLS_BUTTON_DISABLE = C'218,161,76'; // Sienna + CONTROLS_LABEL_TEXT = C'255,228,181'; // Moccasin + CONTROLS_LABEL_BACKGROUND = C'139,69,19'; // Saddle Brown + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,140,0'; // Dark Orange + CONTROLS_LABEL_TEXT_TITLE = C'92,94,205'; // Indian Red + CONTROLS_LABEL_TITLE_BACKGROUND = C'210,105,30'; // Chocolate + CONTROL_EDIT_TEXT = C'255,255,255'; // White + CONTROL_EDIT_BORDER = C'205,133,63'; // Peru + CONTROL_EDIT_BACKGROUND = C'139,69,19'; // Saddle Brown + CONTROL_COMBOBOX_BACKGROUND = C'210,105,30'; // Chocolate + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,228,181'; // Moccasin + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'139,69,19'; // Saddle Brown + CONTROL_BACK_BACGROUND = C'160,82,45'; // Sienna + CONTROL_BORDER_BACKGROUND = C'205,133,63'; // Peru + CONTROL_CLINET = C'255,245,238'; // Seashell + CONTROL_CLINET_BACKGROUND = C'210,105,30'; // Chocolate + CONTROL_CAPTION_TEXT = C'255,255,255'; // White + CONTROL_CAPTION_BACKGROUND = C'139,69,19'; // Saddle Brown + CONTROL_CAPTION_BORDERP = C'205,92,92'; // Indian Red + } + break; + + case White_Theme_1: + { + CONTROLS_BUTTON_TEXT = C'0,0,0'; // Black + CONTROLS_BUTTON_ENABLE = C'220,220,220'; // Light Gray + CONTROLS_BUTTON_DISABLE = C'192,192,192'; // Gray + CONTROLS_LABEL_TEXT = C'0,0,0'; // Black + CONTROLS_LABEL_TEXT_ARM = C'0,102,204'; + CONTROLS_LABEL_LOG_TEXT = C'0,180,204'; + CONTROLS_LABEL_TEXT_ANSWER = C'83,82,82'; + CONTROLS_LABEL_BACKGROUND = C'255,255,255'; // White + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,69,0'; // Red Orange + CONTROLS_LABEL_TEXT_TITLE = C'0,102,204'; // Dodger Blue + CONTROLS_LABEL_TITLE_BACKGROUND = C'220,220,220'; // Light Gray + CONTROL_EDIT_TEXT = C'0,0,0'; // Black + CONTROL_EDIT_BORDER = C'192,192,192'; // Gray + CONTROL_EDIT_BACKGROUND = C'255,255,255'; // White + CONTROL_COMBOBOX_BACKGROUND = C'220,220,220'; // Light Gray + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,255,255'; // White + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'0,0,0'; // Black + CONTROL_BACK_BACGROUND = C'255,255,255'; // White + CONTROL_BORDER_BACKGROUND = C'192,192,192'; // Gray + CONTROL_CLINET = C'255,250,205'; // Lemon Chiffon + CONTROL_CLINET_BACKGROUND = C'255,255,255'; // White + CONTROL_CAPTION_TEXT = C'0,0,0'; // Black + CONTROL_CAPTION_BACKGROUND = C'220,220,220'; // Light Gray + CONTROL_CAPTION_BORDERP = C'255,69,0'; // Red Orange + } + break; + + case White_Theme_2: + { + CONTROLS_BUTTON_TEXT = C'0,0,0'; // Black + CONTROLS_BUTTON_ENABLE = C'240,240,240'; // Very Light Gray + CONTROLS_BUTTON_DISABLE = C'192,192,192'; // Gray + CONTROLS_LABEL_TEXT = C'0,0,0'; // Black + CONTROLS_LABEL_TEXT_ARM = C'0,102,204'; + CONTROLS_LABEL_LOG_TEXT = C'240,113,176'; + CONTROLS_LABEL_TEXT_ANSWER = C'83,82,82'; + CONTROLS_LABEL_BACKGROUND = C'255,255,255'; // White + CONTROLS_LABEL_TEXT_TOOLTIP = C'255,140,0'; // Dark Orange + CONTROLS_LABEL_TEXT_TITLE = C'0,102,204'; // Dodger Blue + CONTROLS_LABEL_TITLE_BACKGROUND = C'240,240,240'; // Very Light Gray + CONTROL_EDIT_TEXT = C'0,0,0'; // Black + CONTROL_EDIT_BORDER = C'192,192,192'; // Gray + CONTROL_EDIT_BACKGROUND = C'255,255,255'; // White + CONTROL_COMBOBOX_BACKGROUND = C'240,240,240'; // Very Light Gray + CONTROL_COMBOBOX_BACKGROUND_ITEM = C'255,255,255'; // White + CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL = C'0,0,0'; // Black + CONTROL_BACK_BACGROUND = C'255,255,255'; // White + CONTROL_BORDER_BACKGROUND = C'192,192,192'; // Gray + CONTROL_CLINET = C'240,248,255'; // Alice Blue + CONTROL_CLINET_BACKGROUND = C'255,255,255'; // White + CONTROL_CAPTION_TEXT = C'0,0,0'; // Black + CONTROL_CAPTION_BACKGROUND = C'240,240,240'; // Very Light Gray + CONTROL_CAPTION_BORDERP = C'255,140,0'; // Dark Orange + } + break; + + } + + } +}; + +// Function to adjust brightness of a color +color CThemes::AdjustBrightness(color baseColor, double factor) { + // Extract the RGB components using bitwise operations + int r = int(((baseColor >> 16) & 0xFF) * factor); + int g = int(((baseColor >> 8) & 0xFF) * factor); + int b = int((baseColor & 0xFF) * factor); + + // Ensure the color values are within the valid range (0-255) + r = MathMin(r, 255); + g = MathMin(g, 255); + b = MathMin(b, 255); + + // Combine the adjusted RGB values back into a color + return (color)((r << 16) | (g << 8) | b); +} + +// Example usage +/* +void CThemes::ApplyThemeBrightness(bool isDarkMode) { + + double factor = isDarkMode ? 0.8 : 1.2; // Adjust factor for dark/light mode + // Adjust brightness for each color attribute + CONTROLS_BUTTON_TEXT = AdjustBrightness(CONTROLS_BUTTON_TEXT, factor); + CONTROLS_BUTTON_ENABLE = AdjustBrightness(CONTROLS_BUTTON_ENABLE, factor); + CONTROLS_BUTTON_DISABLE = AdjustBrightness(CONTROLS_BUTTON_DISABLE, factor); + CONTROLS_LABEL_TEXT = AdjustBrightness(CONTROLS_LABEL_TEXT, factor); + CONTROLS_LABEL_BACKGROUND = AdjustBrightness(CONTROLS_LABEL_BACKGROUND, factor); + CONTROLS_LABEL_TEXT_TOOLTIP = AdjustBrightness(CONTROLS_LABEL_TEXT_TOOLTIP, factor); + CONTROLS_LABEL_TEXT_TITLE = AdjustBrightness(CONTROLS_LABEL_TEXT_TITLE, factor); + CONTROLS_LABEL_TITLE_BACKGROUND = AdjustBrightness(CONTROLS_LABEL_TITLE_BACKGROUND, factor); + CONTROL_EDIT_TEXT = AdjustBrightness(CONTROL_EDIT_TEXT, factor); + CONTROL_EDIT_BACKGROUND = AdjustBrightness(CONTROL_EDIT_BACKGROUND, factor); + CONTROL_EDIT_BORDER = AdjustBrightness(CONTROL_EDIT_BORDER, factor); + CONTROL_COMBOBOX_BACKGROUND = AdjustBrightness(CONTROL_COMBOBOX_BACKGROUND, factor); + CONTROL_COMBOBOX_BACKGROUND_ITEM = AdjustBrightness(CONTROL_COMBOBOX_BACKGROUND_ITEM, factor); + CONTROL_BACK_BACGROUND = AdjustBrightness(CONTROL_BACK_BACGROUND, factor); + CONTROL_BORDER_BACKGROUND = AdjustBrightness(CONTROL_BORDER_BACKGROUND, factor); + CONTROL_CLINET = AdjustBrightness(CONTROL_CLINET, factor); + CONTROL_CLINET_BACKGROUND = AdjustBrightness(CONTROL_CLINET_BACKGROUND, factor); + CONTROL_CAPTION_TEXT = AdjustBrightness(CONTROL_CAPTION_TEXT, factor); + CONTROL_CAPTION_BACKGROUND = AdjustBrightness(CONTROL_CAPTION_BACKGROUND, factor); + CONTROL_CAPTION_BORDERP = AdjustBrightness(CONTROL_CAPTION_BORDERP, factor); + + Print("Theme brightness adjusted for ", isDarkMode ? "dark mode" : "light mode"); +} \ No newline at end of file diff --git a/Retrace/ComboBox_New.mqh b/Retrace/ComboBox_New.mqh new file mode 100644 index 0000000..02f4ff1 --- /dev/null +++ b/Retrace/ComboBox_New.mqh @@ -0,0 +1,332 @@ +//+------------------------------------------------------------------+ +//| ComboBox_New.mqh | +//| Copyright 2000-2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#include +#include +#include +#include "ListView_New.mqh" + +//+------------------------------------------------------------------+ +//| Resources | +//+------------------------------------------------------------------+ +//--- Can not place the same file into resource twice +#resource "res\\DropOn.bmp" // image file +#resource "res\\DropOff.bmp" // image file +//+------------------------------------------------------------------+ +//| Class CComboBox | +//| Usage: drop-down list | +//+------------------------------------------------------------------+ +class CComboBox : public CWndContainer + { +private: + //--- dependent controls + CEdit m_edit; // the entry field object + CBmpButton m_drop; // the button object + CListView m_list; // the drop-down list object + //--- set up + int m_item_height; // height of visible row + int m_view_items; // number of visible rows in the drop-down list + bool flage; + +public: + CComboBox(void); + ~CComboBox(void); + //--- create + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); + //--- chart event handler + virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); + //--- fill + bool AddItem(const string item,const long value=0); + //--- set up + void ListViewItems(const int value) { m_view_items=value; } + //--- data + virtual bool ItemAdd(const string item,const long value=0) { return(m_list.ItemAdd(item,value)); } + virtual bool ItemInsert(const int index,const string item,const long value=0) { return(m_list.ItemInsert(index,item,value)); } + virtual bool ItemUpdate(const int index,const string item,const long value=0) { return(m_list.ItemUpdate(index,item,value)); } + virtual bool ItemDelete(const int index) { return(m_list.ItemDelete(index)); } + virtual bool ItemsClear(void) { return(m_list.ItemsClear()); } + bool CheckShowHide(void) {return flage;} + //--- data + string Select(void) { return(m_edit.Text()); } + bool Select(const int index); + bool SelectByText(const string text); + bool SelectByValue(const long value); + //--- data (read only) + long Value(void) { return(m_list.Value()); } + //--- state + virtual bool Show(void); + //--- methods for working with files + virtual bool Save(const int file_handle); + virtual bool Load(const int file_handle); + +protected: + //--- create dependent controls + virtual bool CreateEdit(void); + virtual bool CreateButton(void); + virtual bool CreateList(void); + //--- handlers of the dependent controls events + virtual bool OnClickEdit(void); + virtual bool OnClickButton(void); + virtual bool OnChangeList(void); + //--- show drop-down list + bool ListShow(void); + bool ListHide(void); + void CheckListHide(const int id,int x,int y); + }; +//+------------------------------------------------------------------+ +//| Common handler of chart events | +//+------------------------------------------------------------------+ +EVENT_MAP_BEGIN(CComboBox) + ON_EVENT(ON_CLICK,m_edit,OnClickEdit) + ON_EVENT(ON_CLICK,m_drop,OnClickButton) + ON_EVENT(ON_CHANGE,m_list,OnChangeList) +CheckListHide(id,(int)lparam,(int)dparam); +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +EVENT_MAP_END(CWndContainer) +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CComboBox::CComboBox(void) : m_item_height(CONTROLS_COMBO_ITEM_HEIGHT), + m_view_items(CONTROLS_COMBO_ITEMS_VIEW) + + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CComboBox::~CComboBox(void) + { + } +//+------------------------------------------------------------------+ +//| Create a control | +//+------------------------------------------------------------------+ +bool CComboBox::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) + { +//--- check height + if(y2-y1 +#include +#include +#include +#include +#include +#include "Colors.mqh" +#include "Font.mqh" +#include "Setting.mqh" + +//+------------------------------------------------------------------+ +//| Resources | +//+------------------------------------------------------------------+ +#resource "res\\Close_Panel.bmp" +#resource "res\\Up_Panel.bmp" +#resource "res\\Down_Panel.bmp" +#resource "res\\Sun_Panel.bmp" +#resource "res\\Moon_Panel.bmp" +#resource "res\\Close_PanelRED.bmp" +//+------------------------------------------------------------------+ +//| Class CDialog | +//| Usage: base class to create dialog boxes | +//| and indicator panels | +//+------------------------------------------------------------------+ +class CDialog : public CWndContainer + { +private: + //--- dependent controls + CThemes m_Themes; + CPanel m_white_border; // the "white border" object + CPanel m_background; // the background object + CEdit m_caption; // the window title object + CBmpButton m_button_close; // the "Close" button object + CWndClient m_client_area; // the client area object + +protected: + //--- flags + bool m_panel_flag; // the "panel in a separate window" flag + //--- flags + bool m_minimized; // "create in minimized state" flag + bool m_moon; // "create in moonsuned state" flag + bool m_sun; + bool is_hover_close; + //--- additional areas + CRect m_min_rect; // minimal area coordinates + CRect m_norm_rect; // normal area coordinates + +public: + CDialog(void); + ~CDialog(void); + //--- create + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); + //--- chart event handler + virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); + virtual void HandleCloseButtonHover(int mouse_x, int mouse_y); + //--- set up + string Caption(void) const { return(m_caption.Text()); } + bool Caption(const string text) { return(m_caption.Text(text)); } + bool IsSunMode(void) const {return m_sun; } + + //--- fill + bool Add(CWnd *control); + bool Add(CWnd &control); + //--- methods for working with files + virtual bool Save(const int file_handle); + virtual bool Load(const int file_handle); + + +protected: + //--- create dependent controls + virtual bool CreateWhiteBorder(void); + virtual bool CreateBackground(void); + virtual bool CreateCaption(void); + virtual bool CreateButtonClose(void); + virtual bool CreateClientArea(void); + //--- handlers of the dependent controls events + virtual void OnClickCaption(void); + virtual void OnClickButtonClose(void); + //--- access properties of caption + void CaptionAlignment(const int flags,const int left,const int top,const int right,const int bottom) + { m_caption.Alignment(flags,left,top,right,bottom); } + //--- access properties of client area + bool ClientAreaVisible(const bool visible) { return(m_client_area.Visible(visible)); } + int ClientAreaLeft(void) const { return(m_client_area.Left()); } + int ClientAreaTop(void) const { return(m_client_area.Top()); } + int ClientAreaRight(void) const { return(m_client_area.Right()); } + int ClientAreaBottom(void) const { return(m_client_area.Bottom()); } + int ClientAreaWidth(void) const { return(m_client_area.Width()); } + int ClientAreaHeight(void) const { return(m_client_area.Height()); } + //--- handlers of drag + virtual bool OnDialogDragStart(void); + virtual bool OnDialogDragProcess(void); + virtual bool OnDialogDragEnd(void); + }; +//+------------------------------------------------------------------+ +//| Common handler of events | +//+------------------------------------------------------------------+ +EVENT_MAP_BEGIN(CDialog) + ON_EVENT(ON_CLICK,m_button_close,OnClickButtonClose) + ON_EVENT(ON_CLICK,m_caption,OnClickCaption) + ON_EVENT(ON_DRAG_START,m_caption,OnDialogDragStart) + ON_EVENT_PTR(ON_DRAG_PROCESS,m_drag_object,OnDialogDragProcess) + ON_EVENT_PTR(ON_DRAG_END,m_drag_object,OnDialogDragEnd) +EVENT_MAP_END(CWndContainer) +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CDialog::CDialog(void) : m_panel_flag(false), + m_minimized(false), + m_sun(false) + + { + m_Themes.ApplyTheme((int)Sets.Themes); + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CDialog::~CDialog(void) + { + } +//+------------------------------------------------------------------+ +//| Create a control | +//+------------------------------------------------------------------+ +bool CDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) + { +//--- call method of parent class + if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2)) + return(false); +//--- create dependent controls + if(!m_panel_flag && !CreateWhiteBorder()) + return(false); + if(!CreateBackground()) + return(false); + if(!CreateCaption()) + return(false); + if(!CreateButtonClose()) + return(false); + if(!CreateClientArea()) + return(false); +//--- set up additional areas + m_norm_rect.SetBound(m_rect); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Add control to the client area (by pointer) | +//+------------------------------------------------------------------+ +bool CDialog::Add(CWnd *control) + { + return(m_client_area.Add(control)); + } +//+------------------------------------------------------------------+ +//| Add control to the client area (by reference) | +//+------------------------------------------------------------------+ +bool CDialog::Add(CWnd &control) + { + return(m_client_area.Add(control)); + } +//+------------------------------------------------------------------+ +//| Save | +//+------------------------------------------------------------------+ +bool CDialog::Save(const int file_handle) + { +//--- check + if(file_handle==INVALID_HANDLE) + return(false); +//--- save + FileWriteStruct(file_handle,m_norm_rect); + FileWriteInteger(file_handle,m_min_rect.left); + FileWriteInteger(file_handle,m_min_rect.top); + FileWriteInteger(file_handle,m_minimized); + FileWriteInteger(file_handle,m_sun); +//--- result + return(CWndContainer::Save(file_handle)); + } +//+------------------------------------------------------------------+ +//| Load | +//+------------------------------------------------------------------+ +bool CDialog::Load(const int file_handle) + { + if(file_handle==INVALID_HANDLE) + return(false); +//--- load + if(!FileIsEnding(file_handle)) + { + FileReadStruct(file_handle,m_norm_rect); + int left=FileReadInteger(file_handle); + int top=FileReadInteger(file_handle); + m_min_rect.Move(left,top); + m_minimized=FileReadInteger(file_handle); + m_sun=FileReadInteger(file_handle); + } +//--- result + return(CWndContainer::Load(file_handle)); + } +//+------------------------------------------------------------------+ +//| Create "white border" | +//+------------------------------------------------------------------+ +bool CDialog::CreateWhiteBorder(void) + { +//--- coordinates + int x1=0; + int y1=0; + int x2=Width(); + int y2=Height(); +//--- create + if(!m_white_border.Create(m_chart_id,m_name+"Border",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_white_border.ColorBackground(CONTROLS_DIALOG_COLOR_BG)) + return(false); + if(!m_white_border.ColorBorder(m_Themes.CONTROL_BORDER_BACKGROUND)) + return(false); + if(!CWndContainer::Add(m_white_border)) + return(false); + m_white_border.Alignment(WND_ALIGN_CLIENT,0,0,0,0); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create background | +//+------------------------------------------------------------------+ +bool CDialog::CreateBackground(void) + { + int off=(m_panel_flag) ? 0:CONTROLS_BORDER_WIDTH; +//--- coordinates + int x1=off; + int y1=off; + int x2=Width()-off; + int y2=Height()-off; +//--- create + if(!m_background.Create(m_chart_id,m_name+"Back",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_background.ColorBackground(m_Themes.CONTROL_BACK_BACGROUND)) + return(false); + color border=(m_panel_flag) ? CONTROLS_DIALOG_COLOR_BG : CONTROLS_DIALOG_COLOR_BORDER_DARK; + if(!m_background.ColorBorder(border)) + return(false); + if(!CWndContainer::Add(m_background)) + return(false); + m_background.Alignment(WND_ALIGN_CLIENT,off,off,off,off); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create window title | +//+------------------------------------------------------------------+ +bool CDialog::CreateCaption(void) + { + int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH; +//--- coordinates + int x1=off; + int y1=off; + int x2=Width()-off - 3*(CONTROLS_BUTTON_SIZE) - 3*(CUSTOM_SPACING); + int y2=y1+CONTROLS_DIALOG_CAPTION_HEIGHT; +//--- create + if(!m_caption.Create(m_chart_id,m_name+"Caption",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_caption.Color(m_Themes.CONTROL_CAPTION_TEXT)) + return(false); + if(!m_caption.ColorBackground(m_Themes.CONTROL_CAPTION_BACKGROUND)) + return(false); + if(!m_caption.ColorBorder(m_Themes.CONTROL_CAPTION_BORDERP)) + return(false); + if(!m_caption.ReadOnly(true)) + return(false); + if(!m_caption.Text(m_name)) + return(false); + if(!CWndContainer::Add(m_caption)) + return(false); + m_caption.Alignment(WND_ALIGN_WIDTH,off,0,off,0); + if(!m_panel_flag) + m_caption.PropFlags(WND_PROP_FLAG_CAN_DRAG); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "Close" button | +//+------------------------------------------------------------------+ +bool CDialog::CreateButtonClose(void) + { + int off=(m_panel_flag) ? 0 : 2*CONTROLS_BORDER_WIDTH; +//--- coordinates + int x1=Width()-off-(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF); + int y1=off+CONTROLS_DIALOG_BUTTON_OFF; + int x2=x1+CONTROLS_BUTTON_SIZE; + int y2=y1+CONTROLS_BUTTON_SIZE; + +//--- create + if(!m_button_close.Create(m_chart_id,m_name+"Close",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_button_close.BmpNames("::res\\Close_Panel.bmp","::res\\Close_PanelRED.bmp")) + return(false); + // m_button_close.Color(clrRed); + if(!CWndContainer::Add(m_button_close)) + return(false); + m_button_close.Alignment(WND_ALIGN_RIGHT,0,0,off+CONTROLS_DIALOG_BUTTON_OFF,0); +//--- change caption + CaptionAlignment(WND_ALIGN_WIDTH,off,0,off+(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF),0); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create client area | +//+------------------------------------------------------------------+ +bool CDialog::CreateClientArea(void) + { + int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH; +//--- coordinates + int x1=off+CONTROLS_DIALOG_CLIENT_OFF; + int y1=off+CONTROLS_DIALOG_CAPTION_HEIGHT; + int x2=Width()-(off+CONTROLS_DIALOG_CLIENT_OFF); + int y2=Height()-(off+CONTROLS_DIALOG_CLIENT_OFF); +//--- create + if(!m_client_area.Create(m_chart_id,m_name+"Client",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_client_area.ColorBackground(m_Themes.CONTROL_CLINET_BACKGROUND)) + return(false); + if(!m_client_area.ColorBorder(m_Themes.CONTROL_CLINET)) + return(false); + CWndContainer::Add(m_client_area); + m_client_area.Alignment(WND_ALIGN_CLIENT,x1,y1,x1,x1); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Handler of click on the window title | +//+------------------------------------------------------------------+ +void CDialog::OnClickCaption(void) + { + } +//+------------------------------------------------------------------+ +//| Handler of click on the "Close" button | +//+------------------------------------------------------------------+ +void CDialog::OnClickButtonClose(void) + { + Visible(false); + } +//+------------------------------------------------------------------+ +//| Start dragging the dialog box | +//+------------------------------------------------------------------+ +bool CDialog::OnDialogDragStart(void) + { + if(m_drag_object==NULL) + { + m_drag_object=new CDragWnd; + if(m_drag_object==NULL) + return(false); + } +//--- calculate coordinates + int x1=Left()-CONTROLS_DRAG_SPACING; + int y1=Top()-CONTROLS_DRAG_SPACING; + int x2=Right()+CONTROLS_DRAG_SPACING; + int y2=Bottom()+CONTROLS_DRAG_SPACING; +//--- create + m_drag_object.Create(m_chart_id,"",m_subwin,x1,y1,x2,y2); + m_drag_object.PropFlags(WND_PROP_FLAG_CAN_DRAG); +//--- constraints + CChart chart; + chart.Attach(m_chart_id); + m_drag_object.Limits(-CONTROLS_DRAG_SPACING,-CONTROLS_DRAG_SPACING, + chart.WidthInPixels()+CONTROLS_DRAG_SPACING, + chart.HeightInPixels(m_subwin)+CONTROLS_DRAG_SPACING); + chart.Detach(); +//--- set mouse params + m_drag_object.MouseX(m_caption.MouseX()); + m_drag_object.MouseY(m_caption.MouseY()); + m_drag_object.MouseFlags(m_caption.MouseFlags()); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Continue dragging the dialog box | +//+------------------------------------------------------------------+ +bool CDialog::OnDialogDragProcess(void) + { +//--- checking + if(m_drag_object==NULL) + return(false); +//--- calculate coordinates + int x=m_drag_object.Left()+50; + int y=m_drag_object.Top()+50; +//--- move dialog + Move(x,y); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| End dragging the dialog box | +//+------------------------------------------------------------------+ +bool CDialog::OnDialogDragEnd(void) + { + if(m_drag_object!=NULL) + { + m_caption.MouseFlags(m_drag_object.MouseFlags()); + delete m_drag_object; + m_drag_object=NULL; + } +//--- set up additional areas + if(m_minimized) + m_min_rect.SetBound(m_rect); + else + m_norm_rect.SetBound(m_rect); +//--- succeed + return(true); + } + +void CDialog::HandleCloseButtonHover(int mouse_x, int mouse_y) +{ + bool hover_close = m_button_close.OnMouseEvent(mouse_x, mouse_y, 0); + + if (hover_close && !is_hover_close) + { + m_button_close.BmpOffName("::res\\Close_PanelRED.bmp"); // Set to hover icon + is_hover_close = true; + } + else if (!hover_close && is_hover_close) + { + m_button_close.BmpOffName("::res\\Close_Panel.bmp"); // Reset to default icon + is_hover_close = false; + } +} +//+------------------------------------------------------------------+ +//| Class CAppDialog | +//| Usage: main dialog box of MQL5 application | +//+------------------------------------------------------------------+ +class CAppDialog : public CDialog + { +private: + //--- dependent controls + CDialog m_Dialog; + CBmpButton m_button_minmax; // the "Minimize/Maximize" button object + CBmpButton m_button_moonsun; + //--- variables + string m_program_name; // name of program + string m_instance_id; // unique string ID + ENUM_PROGRAM_TYPE m_program_type; // type of program + string m_indicator_name; + int m_deinit_reason; + //--- for mouse + int m_subwin_Yoff; // subwindow Y offset + CWnd* m_focused_wnd; // pointer to object that has mouse focus + CWnd* m_top_wnd; // pointer to object that has priority over mouse events handling + +protected: + CChart m_chart; // object to access chart + +public: + CAppDialog(void); + ~CAppDialog(void); + //--- main application dialog creation and destroy + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2,const int x_minmiz); + virtual void Destroy(const int reason=REASON_PROGRAM); + //--- chart event handler + virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); + virtual void HandleChartChange(const double &dparam, const string &sparam); + bool IsPressedSunMode(void) const {return m_button_moonsun.Pressed();} + //--- dialog run + bool Run(void); + //--- chart events processing + void ChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam); + void ChartEvent2(const int id,const long &lparam,const double &dparam,const string &sparam); + //--- set up + void Minimized(const bool flag) { m_minimized=flag; } + //--- to save/restore state + void IniFileSave(void); + void IniFileLoad(void); + virtual string IniFileName(void) const; + virtual string IniFileExt(void) const { return(".dat"); } + virtual bool Load(const int file_handle); + virtual bool Save(const int file_handle); + +private: + bool CreateCommon(const long chart,const string name,const int subwin); + bool CreateExpert(const int x1,const int y1,const int x2,const int y2, const int x_minmiz); + bool CreateIndicator(const int x1,const int y1,const int x2,const int y2,const int x_minmiz); + +protected: + //--- create dependent controls + virtual bool CreateButtonMinMax(void); + virtual bool CreateButtonMoonSun(void); + //--- handlers of the dependent controls events + virtual void OnClickButtonClose(void); + virtual void OnClickButtonMinMax(void); + virtual void OnClickButtonMoonsun(void); + //--- external event handlers + virtual void OnAnotherApplicationClose(const long &lparam,const double &dparam,const string &sparam); + //--- methods + virtual bool Rebound(const CRect &rect); + virtual void Minimize(void); + virtual void Maximize(void); + virtual void Moon(void); + virtual void Sun(void); + string CreateInstanceId(void); + string ProgramName(void) const { return(m_program_name); } + void SubwinOff(void); + }; +//+------------------------------------------------------------------+ +//| Common handler of events | +//+------------------------------------------------------------------+ +EVENT_MAP_BEGIN(CAppDialog) +ON_EVENT(ON_CLICK,m_button_minmax,OnClickButtonMinMax) +ON_EVENT(ON_CLICK,m_button_moonsun,OnClickButtonMoonsun) +ON_EXTERNAL_EVENT(ON_APP_CLOSE,OnAnotherApplicationClose) +EVENT_MAP_END(CDialog) +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CAppDialog::CAppDialog(void) : m_program_type(WRONG_VALUE), + m_deinit_reason(WRONG_VALUE), + m_subwin_Yoff(0), + m_focused_wnd(NULL), + m_top_wnd(NULL) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CAppDialog::~CAppDialog(void) + { + } +//+------------------------------------------------------------------+ +//| Application dialog initialization function | +//+------------------------------------------------------------------+ +bool CAppDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2,const int x_minmiz) + { + if(!CreateCommon(chart,name,subwin)) + return(false); +//--- + switch(m_program_type) + { + case PROGRAM_EXPERT: + if(!CreateExpert(x1,y1,x2,y2,x_minmiz)) + return(false); + break; + case PROGRAM_INDICATOR: + if(!CreateIndicator(x1,y1,x2,y2,x_minmiz)) + return(false); + break; + default: + Print("CAppDialog: invalid program type"); + return(false); + } +//--- Title of dialog window + if(!Caption(m_program_name)) + return(false); +//--- create dependent controls + if(!CreateButtonMinMax()) + return(false); + if(!CreateButtonMoonSun()) + return(false); +//--- get subwindow offset + SubwinOff(); +//--- if flag is set, minimize the dialog + if(m_minimized) + { + Minimize(); + m_button_moonsun.Hide(); + } + if(m_sun) {Sun();} + // else if(m_sun) {Sun();} + +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Initialize common area | +//+------------------------------------------------------------------+ +bool CAppDialog::CreateCommon(const long chart,const string name,const int subwin) + { +//--- save parameters + m_chart_id =chart; + m_name =name; + m_subwin =subwin; + m_program_name =name; + m_deinit_reason=WRONG_VALUE; +//--- get unique ID + m_instance_id=CreateInstanceId(); +//--- initialize chart object + m_chart.Attach(chart); +//--- determine type of program + m_program_type=(ENUM_PROGRAM_TYPE)MQL5InfoInteger(MQL5_PROGRAM_TYPE); +//--- specify object and mouse events + if(!m_chart.EventObjectCreate() || !m_chart.EventObjectDelete() || !m_chart.EventMouseMove()) + { + Print("CAppDialog: object events specify error"); + m_chart.Detach(); + return(false); + } +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Initialize in Expert Advisor | +//+------------------------------------------------------------------+ +bool CAppDialog::CreateExpert(const int x1,const int y1,const int x2,const int y2,const int x_minmiz) + { +//--- EA works only in main window + m_subwin=0; +//--- geometry for the minimized state + m_min_rect.SetBound(CONTROLS_DIALOG_MINIMIZE_LEFT, + CONTROLS_DIALOG_MINIMIZE_TOP, + CONTROLS_DIALOG_MINIMIZE_LEFT+x_minmiz, + CONTROLS_DIALOG_MINIMIZE_TOP+CONTROLS_DIALOG_MINIMIZE_HEIGHT); +//--- call method of the parent class + if(!CDialog::Create(m_chart.ChartId(),m_instance_id,m_subwin,x1,y1,x2,y2)) + { + Print("CAppDialog: expert dialog create error"); + m_chart.Detach(); + return(false); + } +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Initialize in Indicator | +//+------------------------------------------------------------------+ +bool CAppDialog::CreateIndicator(const int x1,const int y1,const int x2,const int y2,const int x_minmiz) + { + int width=m_chart.WidthInPixels(); +//--- geometry for the minimized state + m_min_rect.LeftTop(0,0); + m_min_rect.Width(width); + m_min_rect.Height(CONTROLS_DIALOG_MINIMIZE_HEIGHT-2*CONTROLS_BORDER_WIDTH); +//--- determine subwindow + m_subwin=ChartWindowFind(); + if(m_subwin==-1) + { + Print("CAppDialog: find subwindow error"); + m_chart.Detach(); + return(false); + } +//--- + int total=ChartIndicatorsTotal(m_chart.ChartId(),m_subwin); + m_indicator_name=ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1); +//--- if subwindow number is 0 (main window), then our program is +//--- not an indicator panel, but is an indicator with built-in settings dialog +//--- dialog of such an indicator should behave as an Expert Advisor dialog + if(m_subwin==0) + return(CreateExpert(x1,y1,x2,y2,x_minmiz)); +//--- if subwindow number is not 0, then our program is an indicator panel +//--- check if subwindow is not occupied by other indicators + if(total!=1) + { + Print("CAppDialog: subwindow busy"); + ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1)); + m_chart.Detach(); + return(false); + } +//--- resize subwindow by dialog height + if(!IndicatorSetInteger(INDICATOR_HEIGHT,(y2-y1)+1)) + { + Print("CAppDialog: subwindow resize error"); + ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1)); + m_chart.Detach(); + return(false); + } +//--- indicator short name + m_indicator_name=m_program_name+IntegerToString(m_subwin); + if(!IndicatorSetString(INDICATOR_SHORTNAME,m_indicator_name)) + { + Print("CAppDialog: shortname error"); + ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1)); + m_chart.Detach(); + return(false); + } +//--- set flag + m_panel_flag=true; +//--- call method of the parent class + if(!CDialog::Create(m_chart.ChartId(),m_instance_id,m_subwin,0,0,width,y2-y1)) + { + Print("CAppDialog: indicator dialog create error"); + ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1)); + m_chart.Detach(); + return(false); + } +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Application dialog deinitialization function | +//+------------------------------------------------------------------+ +void CAppDialog::Destroy(const int reason) + { +//--- destroyed already? + if(m_deinit_reason!=WRONG_VALUE) + return; +//--- + m_deinit_reason=reason; + IniFileSave(); +//--- detach chart object from chart + m_chart.Detach(); +//--- call parent destroy + CDialog::Destroy(); +//--- + if(reason==REASON_PROGRAM) + { + if(m_program_type==PROGRAM_EXPERT) + ExpertRemove(); + if(m_program_type==PROGRAM_INDICATOR) + ChartIndicatorDelete(m_chart_id,m_subwin,m_indicator_name); + } +//--- send message + EventChartCustom(CONTROLS_SELF_MESSAGE,ON_APP_CLOSE,m_subwin,0.0,m_program_name); + } +//+------------------------------------------------------------------+ +//| Calculate subwindow offset | +//+------------------------------------------------------------------+ +void CAppDialog::SubwinOff(void) + { + m_subwin_Yoff=m_chart.SubwindowY(m_subwin); + } +//+------------------------------------------------------------------+ +//| Create the "Minimize/Maximize" button | +//+------------------------------------------------------------------+ +bool CAppDialog::CreateButtonMinMax(void) + { + int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH; +//--- coordinates + int x1=Width()-off-2*(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF)-CUSTOM_SPACING; + int y1=off+CONTROLS_DIALOG_BUTTON_OFF; + int x2=x1+CONTROLS_BUTTON_SIZE; + int y2=y1+CONTROLS_BUTTON_SIZE; +//--- create + if(!m_button_minmax.Create(m_chart_id,m_name+"MinMax",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_button_minmax.BmpNames("::res\\Up_Panel.bmp","::res\\Down_Panel.bmp")) + return(false); + if(!CWndContainer::Add(m_button_minmax)) + return(false); + m_button_minmax.Locking(true); + m_button_minmax.Alignment(WND_ALIGN_RIGHT,0,0,off+(CONTROLS_BUTTON_SIZE+2*CONTROLS_DIALOG_BUTTON_OFF)+CUSTOM_SPACING,0); +//--- change caption + CaptionAlignment(WND_ALIGN_WIDTH,off,0,off+2*(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF)+CUSTOM_SPACING,0); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "Moon/Sun" button | +//+------------------------------------------------------------------+ +bool CAppDialog::CreateButtonMoonSun(void) + { + int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH; +//--- coordinates + int x1=Width()-off-3*(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF)-2*CUSTOM_SPACING; + int y1=off+CONTROLS_DIALOG_BUTTON_OFF; + int x2=x1+CONTROLS_BUTTON_SIZE; + int y2=y1+CONTROLS_BUTTON_SIZE; +//--- create + if(!m_button_moonsun.Create(m_chart_id,m_name+"MoonSun",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_button_moonsun.BmpNames("::res\\Moon_Panel.bmp","::res\\Sun_Panel.bmp")) + return(false); + if(!CWndContainer::Add(m_button_moonsun)) + return(false); + m_button_moonsun.Locking(true); + m_button_moonsun.Alignment(WND_ALIGN_RIGHT,0,0,off+2*(CONTROLS_BUTTON_SIZE+2*CONTROLS_DIALOG_BUTTON_OFF+CUSTOM_SPACING)-CONTROLS_DIALOG_BUTTON_OFF,0); +//--- change caption + CaptionAlignment(WND_ALIGN_WIDTH,off,0,off+3*(CONTROLS_BUTTON_SIZE+2*CONTROLS_DIALOG_BUTTON_OFF)+2*CUSTOM_SPACING,0); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Charts event processing | +//+------------------------------------------------------------------+ +void CAppDialog::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) +{ + int mouse_x = (int)lparam; + int mouse_y = (int)dparam - m_subwin_Yoff; + + static bool is_hover_minmax = false; + static bool is_hover_moonsun = false; + + switch (id) + { + case CHARTEVENT_CHART_CHANGE: + break; + + case CHARTEVENT_OBJECT_CLICK: + return; + + case CHARTEVENT_CUSTOM + ON_MOUSE_FOCUS_SET: + if (CheckPointer(m_focused_wnd) != POINTER_INVALID) + { + if (!m_focused_wnd.MouseFocusKill(lparam)) + return; + } + m_focused_wnd = ControlFind(lparam); + return; + + case CHARTEVENT_CUSTOM + ON_BRING_TO_TOP: + m_top_wnd = ControlFind(lparam); + return; + + case CHARTEVENT_MOUSE_MOVE: + { + if (CheckPointer(m_top_wnd) != POINTER_INVALID) + { + if (m_top_wnd.OnMouseEvent(mouse_x, mouse_y, (int)StringToInteger(sparam))) + { + m_chart.Redraw(); + return; + } + } + HandleCloseButtonHover(mouse_x, mouse_y); + // Handle hover effect for m_button_minmax + bool hover_minmax = m_button_minmax.OnMouseEvent(mouse_x, mouse_y, (int)StringToInteger(sparam)); + bool hover_moonsun = m_button_moonsun.OnMouseEvent(mouse_x, mouse_y, (int)StringToInteger(sparam)); + + if (m_minimized) + { + // Minimized state icons for minmax button + if (hover_minmax && !is_hover_minmax) + { + m_button_minmax.BmpOnName("::res\\Up_Panel.bmp"); // Minimized Hover icon Close_PanelRED + is_hover_minmax = true; + } + else if (!hover_minmax && is_hover_minmax) + { + m_button_minmax.BmpOnName("::res\\Down_Panel.bmp"); // Default icon + is_hover_minmax = false; + } + } + else // Not minimized + { + // Normal state icons for minmax button + if (hover_minmax && !is_hover_minmax) + { + m_button_minmax.BmpOffName("::res\\Down_Panel.bmp"); // Normal Hover icon + is_hover_minmax = true; + } + else if (!hover_minmax && is_hover_minmax) + { + m_button_minmax.BmpOffName("::res\\Up_Panel.bmp"); // Default icon + is_hover_minmax = false; + } + + // Sun/Moon mode icons for moonsun button + if (m_sun) + { + if (hover_moonsun && !is_hover_moonsun) + { + m_button_moonsun.BmpOnName("::res\\Moon_Panel.bmp"); // Hover icon for Sun mode + is_hover_moonsun = true; + } + else if (!hover_moonsun && is_hover_moonsun) + { + m_button_moonsun.BmpOnName("::res\\Sun_Panel.bmp"); // Default icon for Sun mode + is_hover_moonsun = false; + } + } + else // Moon mode + { + if (hover_moonsun && !is_hover_moonsun) + { + m_button_moonsun.BmpOffName("::res\\Sun_Panel.bmp"); // Hover icon for Moon mode + is_hover_moonsun = true; + } + else if (!hover_moonsun && is_hover_moonsun) + { + m_button_moonsun.BmpOffName("::res\\Moon_Panel.bmp"); // Default icon for Moon mode + is_hover_moonsun = false; + } + } + } + + + m_chart.Redraw(); + return; + } + + default: + if (OnEvent(id, lparam, dparam, sparam)) + m_chart.Redraw(); + return; + } + + if (id == CHARTEVENT_CHART_CHANGE) + { + if (m_subwin != 0 && m_subwin != ChartWindowFind()) + { + long fiction = 1; + OnAnotherApplicationClose(fiction, dparam, sparam); + } + if (m_chart.HeightInPixels(m_subwin) < Height() + CONTROLS_BORDER_WIDTH) + { + m_button_minmax.Pressed(true); + Minimize(); + m_chart.Redraw(); + } + if (m_chart.WidthInPixels() != Width() && m_subwin != 0) + { + Width(m_chart.WidthInPixels()); + m_chart.Redraw(); + } + SubwinOff(); + return; + } +} + + +//+------------------------------------------------------------------+ +//| Run application | +//+------------------------------------------------------------------+ +bool CAppDialog::Run(void) + { +//--- redraw chart for dialog invalidate + m_chart.Redraw(); +//--- here we begin to assign IDs to controls + if(Id(m_subwin*CONTROLS_MAXIMUM_ID)>CONTROLS_MAXIMUM_ID) + { + Print("CAppDialog: too many objects"); + return(false); + } +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Stop application | +//+------------------------------------------------------------------+ +void CAppDialog::OnClickButtonClose(void) + { +//--- destroy application + Destroy(); + } +//+------------------------------------------------------------------+ +//| Handler of click on the "Minimize/Maximize" button | +//+------------------------------------------------------------------+ +void CAppDialog::OnClickButtonMinMax(void) + { + if(m_button_minmax.Pressed()) + { + Minimize(); + m_button_moonsun.Hide(); + } + else + { + Maximize(); + m_button_moonsun.Show(); + } +//--- get subwindow offset + SubwinOff(); + } +//+------------------------------------------------------------------+ +//| Handler of click on the "Moon/Sun" button | +//+------------------------------------------------------------------+ +void CAppDialog::OnClickButtonMoonsun(void) + { + if(m_button_moonsun.Pressed()) { Sun();} + else {Moon();} + + + SubwinOff(); + IniFileSave(); + } +//+------------------------------------------------------------------+ +//| Resize | +//+------------------------------------------------------------------+ +bool CAppDialog::Rebound(const CRect &rect) + { + if(!Move(rect.LeftTop())) + return(false); + if(!Size(rect.Size())) + return(false); +//--- resize subwindow + if(m_program_type==PROGRAM_INDICATOR && !IndicatorSetInteger(INDICATOR_HEIGHT,rect.Height()+1)) + { + Print("CAppDialog: subwindow resize error"); + return(false); + } +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Minimize dialog window | +//+------------------------------------------------------------------+ +void CAppDialog::Minimize(void) + { + int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH; + CaptionAlignment(WND_ALIGN_WIDTH,off,0,off+2*(CONTROLS_BUTTON_SIZE+2*CONTROLS_DIALOG_BUTTON_OFF)+CUSTOM_SPACING,0); +//--- set flag + m_minimized=true; + m_button_moonsun.Hide(); +//--- resize + Rebound(m_min_rect); +//--- hide client area + ClientAreaVisible(false); + } +//+------------------------------------------------------------------+ +//| Restore dialog window | +//+------------------------------------------------------------------+ +void CAppDialog::Maximize(void) + { + int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH; + CaptionAlignment(WND_ALIGN_WIDTH,off,0,off+3*(CONTROLS_BUTTON_SIZE+2*CONTROLS_DIALOG_BUTTON_OFF)+2*CUSTOM_SPACING,0); +//--- reset flag + m_minimized=false; + m_button_moonsun.Show(); +//--- resize + Rebound(m_norm_rect); +//--- show client area + ClientAreaVisible(true); + } +//+------------------------------------------------------------------+ +//| dialoge moon | +//+------------------------------------------------------------------+ +void CAppDialog::Moon(void) +{ + m_sun = false; +} +//+------------------------------------------------------------------+ +//| dialoge sun | +//+------------------------------------------------------------------+ +void CAppDialog::Sun(void) +{ + m_sun = true; +} +//+------------------------------------------------------------------+ +//| Create unique prefix for object names | +//+------------------------------------------------------------------+ +string CAppDialog::CreateInstanceId(void) + { + return(IntegerToString(rand(),5,'0')); + } +//+------------------------------------------------------------------+ +//| Handler of the ON_APP_CLOSE external event | +//+------------------------------------------------------------------+ +void CAppDialog::OnAnotherApplicationClose(const long &lparam,const double &dparam,const string &sparam) + { +//--- exit if we are in the main window + if(m_subwin==0) + return; +//--- exit if external program was closed in main window + if(lparam==0) + return; +//--- get subwindow offset + SubwinOff(); +//--- exit if external program was closed in subwindow with greater number + if(lparam>=m_subwin) + return; +//--- after all the checks we must change the subwindow +//--- get the new number of subwindow + m_subwin=ChartWindowFind(); +//--- change short name + m_indicator_name=m_program_name+IntegerToString(m_subwin); + IndicatorSetString(INDICATOR_SHORTNAME,m_indicator_name); +//--- change dialog title + Caption(m_program_name); +//--- reassign IDs + Run(); + } +//+------------------------------------------------------------------+ +//| Save the current state of the program | +//+------------------------------------------------------------------+ +void CAppDialog::IniFileSave(void) + { + string filename=IniFileName()+IniFileExt(); + int handle=FileOpen(filename,FILE_WRITE|FILE_BIN|FILE_ANSI); +//--- + if(handle!=INVALID_HANDLE) + { + Save(handle); + FileClose(handle); + } + } +//+------------------------------------------------------------------+ +//| Read the previous state of the program | +//+------------------------------------------------------------------+ +void CAppDialog::IniFileLoad(void) + { + string filename=IniFileName()+IniFileExt(); + int handle=FileOpen(filename,FILE_READ|FILE_BIN|FILE_ANSI); +//--- + if(handle!=INVALID_HANDLE) + { + Load(handle); + FileClose(handle); + } + + } +//+------------------------------------------------------------------+ +//| Generate the filename | +//+------------------------------------------------------------------+ +string CAppDialog::IniFileName(void) const + { + string name; +//--- + name=(m_indicator_name!=NULL) ? m_indicator_name : m_program_name; +//--- + name+="_"+Symbol(); + name+="_Ini"; +//--- + return(name); + } +//+------------------------------------------------------------------+ +//| Load data | +//+------------------------------------------------------------------+ +bool CAppDialog::Load(const int file_handle) + { + if(CDialog::Load(file_handle)) + { + if(m_minimized) + { + m_button_minmax.Pressed(true); + Minimize(); + } + else + { + m_button_minmax.Pressed(false); + Maximize(); + } + if(m_sun) + { + m_button_moonsun.Pressed(true); + Sun(); + } + else + { + m_button_moonsun.Pressed(false); + Moon(); + } + int prev_deinit_reason=FileReadInteger(file_handle); + if(prev_deinit_reason==REASON_CHARTCLOSE || prev_deinit_reason==REASON_CLOSE) + { + //--- if the previous time program ended after closing the chart window, + //--- delete object left since the last start of the program + string prev_instance_id=IntegerToString(FileReadInteger(file_handle),5,'0'); + if(prev_instance_id!=m_instance_id) + { + long chart_id=m_chart.ChartId(); + int total=ObjectsTotal(chart_id,m_subwin); + for(int i=total-1;i>=0;i--) + { + string obj_name=ObjectName(chart_id,i,m_subwin); + if(StringFind(obj_name,prev_instance_id)==0) + ObjectDelete(chart_id,obj_name); + } + } + } + return(true); + } +//--- failure + return(false); + } +//+------------------------------------------------------------------+ +//| Save data | +//+------------------------------------------------------------------+ +bool CAppDialog::Save(const int file_handle) + { + if(CDialog::Save(file_handle)) + { + FileWriteInteger(file_handle,m_deinit_reason); + FileWriteInteger(file_handle,(int)StringToInteger(m_instance_id)); + FileWriteInteger(file_handle, m_sun); // Save sun state + return(true); + } +//--- failure + return(false); + } +//+------------------------------------------------------------------+ diff --git a/Retrace/FileSave.mqh b/Retrace/FileSave.mqh new file mode 100644 index 0000000..67ccdd1 --- /dev/null +++ b/Retrace/FileSave.mqh @@ -0,0 +1,111 @@ +//+------------------------------------------------------------------+ +//| FileSave.mqh | +//| Copyright 2023, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2023, MetaQuotes Ltd." +#property link "https://www.mql5.com" + +class CFileSaving +{ +private: + MqlDateTime m_date; + string m_mqlName; + string m_path; + string m_expertRunLogPath; +public: + CFileSaving(void); + ~CFileSaving(void); + + void IniFileSave(string errortxt, bool symbol); + void IniFileSaveRun(string errortxt, bool symbol); + string IniFileName(); + bool Save(const int file_handle, string errortxt, bool symbol); + virtual string DirectoryLogFile() {return (m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) + "\\"+IntegerToString(GenerateMagicNumbers())+ "\\Log\\Log.txt");} + +}; + +CFileSaving::CFileSaving(void) +{ + // FileDelete(m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) + "\\Log\\Log.txt"); + m_mqlName = MQLInfoString(MQL_PROGRAM_NAME); + TimeToStruct(TimeCurrent(), m_date); + string logFile = StringFormat("%04d%02d%02d", m_date.year, m_date.mon, m_date.day) + ".txt"; + m_path = m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) + "\\" + IntegerToString(GenerateMagicNumbers())+ "\\Log\\" + logFile; + m_expertRunLogPath = m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) + "\\"+ IntegerToString(GenerateMagicNumbers())+ "\\Log\\Log.txt"; +} + +CFileSaving::~CFileSaving(void) +{ +} + + +void CFileSaving::IniFileSave(string errortxt, bool symbol) +{ + string filename=m_path; + int handle=FileOpen(filename,FILE_READ|FILE_WRITE|FILE_CSV); + if(handle!=INVALID_HANDLE) + { + Save(handle,errortxt,symbol); + FileClose(handle); + } +} + +void CFileSaving::IniFileSaveRun(string errortxt, bool symbol) +{ + string filename=m_expertRunLogPath; + int handle=FileOpen(filename,FILE_READ|FILE_WRITE|FILE_CSV); + if(handle!=INVALID_HANDLE) + { + Save(handle,errortxt,symbol); + FileClose(handle); + } +} + + +string CFileSaving::IniFileName() +{ + string name; + + name=m_mqlName; + name+="_Log"; + name+="_Ini.txt"; + + return(name); +} + +bool CFileSaving::Save(const int file_handle, string errortxt, bool symbol) +{ + datetime currentTime = TimeCurrent(); + string dateTimeStr = TimeToString(currentTime, TIME_DATE | TIME_MINUTES); + string str = symbol ? " " + Symbol() : " " ; + + FileSeek(file_handle,0,SEEK_END); + bool success = FileWriteString(file_handle,dateTimeStr + str + errortxt + "\n"); + return success; +} + +long GenerateMagicNumbers() +{ + string expNames = MQLInfoString(MQL_PROGRAM_NAME); + string symbol = Symbol(); // Get the current symbol (e.g., "EURUSD") + // string expName = MQLInfoString(MQL_PROGRAM_NAME); // Get the expert name + int baseMagicNumber = 10000; // Base magic number + + // Calculate a unique number for the symbol + int symbolCode = 0; + for (int i = 0; i < StringLen(symbol); i++) + { + symbolCode += StringGetCharacter(symbol, i); // Sum the ASCII values of the symbol's characters + } + + // Calculate a unique number for the expert name + int expNameCode = 0; + for (int i = 0; i < StringLen(expNames); i++) + { + expNameCode += StringGetCharacter(expNames, i); // Sum the ASCII values of the expert name's characters + } + + // Combine base magic number, symbol code, and expert name code + return baseMagicNumber + symbolCode + expNameCode; +} \ No newline at end of file diff --git a/Retrace/Font.mqh b/Retrace/Font.mqh new file mode 100644 index 0000000..7ab76d2 --- /dev/null +++ b/Retrace/Font.mqh @@ -0,0 +1,63 @@ +//+------------------------------------------------------------------+ +//| Enumeration for Windows fonts indices storage | +//+------------------------------------------------------------------+ + + +class CFont +{ +private: + string m_fonts[]; + +public: + CFont(void); + ~CFont(void); + int FontsTotal(void) const { return(::ArraySize(m_fonts)); } + string FontsByIndex(const uint index); + +private: + void InitializeFontsArray(void); +}; + +CFont::CFont(void) +{ + InitializeFontsArray(); +} + +CFont::~CFont(void) +{ + ::ArrayFree(m_fonts); +} + + + +string CFont::FontsByIndex(const uint index) +{ + uint array_size=FontsTotal(); + uint i=(index>=array_size)? array_size-1 : index; + return(m_fonts[i]); +} + + +void CFont::InitializeFontsArray(void) +{ + ::ArrayResize(m_fonts,15); + m_fonts[0]="Arial"; + m_fonts[1]="Comic Sans MS"; + m_fonts[2]="Courier"; + m_fonts[3]="Courier New"; + m_fonts[4]="Georgia"; + m_fonts[5]="Lucida Console Bold"; + m_fonts[6]="Palatino Linotype"; + m_fonts[7]="Small Fonts"; + m_fonts[8]="Tahoma"; + m_fonts[9]="Times New Roman"; + m_fonts[10]="Trebuchet MS"; + m_fonts[11]="Verdana"; + m_fonts[12]="Consolas"; + m_fonts[13]="Simplified Arabic Fixed"; + m_fonts[14]="Sitka Small"; +} + + + + diff --git a/Retrace/History copy.mqh b/Retrace/History copy.mqh new file mode 100644 index 0000000..87bbbb6 --- /dev/null +++ b/Retrace/History copy.mqh @@ -0,0 +1,467 @@ +#include +#include +#include +#include "FileSave.mqh" +#include "Translations/English.mqh" + +enum deal_result +{ + NO_VALUE=0, + WIN=1, + LOSS +}; +enum ENUM_HISTORY_SORT +{ + HISTORY_SORT_OPENTIME, // Open time + HISTORY_SORT_CLOSETIME // Close time +}; + +class CHistory +{ +private: + CFileSaving m_FileSave; + CDealInfo m_deal; + CArrayDouble m_profit_data; + CArrayDouble m_balance_data; + CArrayDouble m_sharp_balance; + CArrayDouble m_balance_line; + + double m_max_lot; + double m_initial_deposit; + double m_withdrawal; + double m_volume; + double m_swap; + double m_commission; + double m_profit; + double m_gross_profit; + double m_gross_loss; + + double m_profit_factor; + + double m_expected_payoff; + + double m_balance; + double m_maxdraw_MDD; + double m_maxdraw_percent; + // double m_balance_min; + // double m_balance_dd; + // double m_balance_dd_percent; + // double m_balance_dd_relative; + // double m_balance_dd_relative_percent; + // double m_balance_dd_absolute; + + double m_min_peak; + double m_max_peak; + + long arr_Positions[]; + long m_type; + long m_magic; + + int m_deals; + int m_trades; + int m_profit_trades; + double m_profit_trades_percent; + int m_loss_trades; + + string m_symbol; + string m_comment; + string m_openTime_str; + string m_closeTime_str; + + datetime m_openTime_dt; + datetime m_closeTime_dt; + + string m_mqlName; + +public: + CHistory(void); + ~CHistory(void); + + + bool Calculate(const string Symbl,const long Mgc,datetime time_start,datetime time_end); + double MaxLots() {return(m_max_lot);} + // double InitialDeposit() {return(m_initial_deposit);} + // double Withdrawal() {return(m_withdrawal);} + double Profit() {return(m_profit);}; + double GrossProfit() {return(m_gross_profit);} + double GrossLoss() {return(m_gross_loss);} + double MDD() {return(m_maxdraw_MDD);} + double ProfitFactor() {return(m_profit_factor);} + int Trades() {return(m_trades);} + int ProfitTrades() {return(m_profit_trades);}; + double ExpectedPayoff() {return(m_expected_payoff);} + + string OpenTime() {return(m_openTime_str);} + string CloseTime() {return(m_closeTime_str);} + + double Percent(double value,double divider); + + bool AppendDataToCSV(datetime open_time, string symbol, ulong magic, string posType, double volume, double openPric, double Sl, double Tp, double closePrice, datetime close_time, double Commis, double Swp, double profit); + bool CheckIsFileBot() {return(FileIsExist(m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) +"\\"+ IntegerToString(GenerateMagicNumbers())+"\\AnalysisOutput\\"+"Transaction11209.csv"));} + string AnalyzePathFile() {return(m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) +"\\"+ IntegerToString(GenerateMagicNumbers())+"\\AnalysisOutput\\"+"Transaction11209.csv");} + +protected: + bool HistorySelectByPositionProcess(const long position_id); + +}; +//m_withdrawal(0.0), m_max_lot(0.0), m_symbol(NULL), m_type(-1), m_magic(-1), m_volume(0.0), +// m_openTime_str("-"), m_closeTime_str("-"), m_profit(0.0), m_gross_loss(0.0), m_gross_profit(0.0) +CHistory::CHistory(void) : m_max_lot(0.0), m_openTime_str("-"), m_closeTime_str("-"), m_balance(0.0), m_max_peak(0.0), m_min_peak(0.0), m_trades(0), + m_expected_payoff(0.0) +{ + m_mqlName = MQLInfoString(MQL_PROGRAM_NAME); + // datetime timestart = D'2024.12.24'; + // if(!CheckIsFileBot()) + // { + // Calculate(Symbol(), GenerateMagicNumbers(), timestart, TimeCurrent()); + // AppendDataToCSV(OpenTime(), Symbol(), GenerateMagicNumbers(), ) + // } +} + +CHistory::~CHistory(void) +{ +} + +bool CHistory::Calculate(const string Symbl, const long Mgc,datetime time_start,datetime time_end) +{ + deal_result result = NO_VALUE; + + int sort_by = HISTORY_SORT_OPENTIME; + + datetime first_entry_time = 0; + datetime overall_first_entry_time = 0; + + m_profit=0; + m_gross_profit=0; + m_gross_loss=0; + + if(!HistorySelect(time_start,time_end)) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_HISTORY_GET_TRADE + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(false); + } + + int deals_total = HistoryDealsTotal(); + + if(sort_by==HISTORY_SORT_OPENTIME) + { + for(int i = 0; i < deals_total && !IsStopped(); i++) + if(m_deal.SelectByIndex(i)) + if(m_deal.Entry()==DEAL_ENTRY_IN) + if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) + { + if(m_deal.Symbol() != Symbl) + continue; + if(m_deal.Magic() != Mgc) + continue; + //--- save position ids to the array + long position_id=m_deal.PositionId(); + int arr_size=ArraySize(arr_Positions); + if(ArrayResize(arr_Positions,arr_size+1)==arr_size+1) + arr_Positions[arr_size]=position_id; + + m_trades++; + + if (first_entry_time == 0 || m_deal.Time() < first_entry_time) {first_entry_time = m_deal.Time();} + } + } + if(sort_by==HISTORY_SORT_CLOSETIME) + { + //--- define a hashset to collect position IDs (with no duplicates) + CHashSethashset; + + //--- handle the case when a position has multiple deals out. + for(int i = deals_total-1; i >= 0 && !IsStopped(); i--) + if(m_deal.SelectByIndex(i)) + if(m_deal.Entry()==DEAL_ENTRY_OUT || m_deal.Entry()==DEAL_ENTRY_OUT_BY) + if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) + { + if(m_deal.Symbol() != Symbl) + continue; + if(m_deal.Magic() != Mgc) + continue; + + hashset.Add(m_deal.PositionId()); + } + + + //--- copy the elements from the set to a compatible one-dimensional array + hashset.CopyTo(arr_Positions,0); + //ArrayReverse(arr_Positions); + ArraySetAsSeries(arr_Positions,true); + } + + deals_total = ArraySize(arr_Positions); + for(int i=0; i 0) + { + if (overall_first_entry_time == 0 || first_entry_time < overall_first_entry_time) + { + overall_first_entry_time = first_entry_time; + m_openTime_dt = overall_first_entry_time; + m_openTime_str = TimeToString(overall_first_entry_time, TIME_DATE); + } + } + + return true; +} + + +//+------------------------------------------------------------------+ +//| Select history of orders and deals by position ID and | +//| prints a list of orders and deals for the position in the journal| +//+------------------------------------------------------------------+ +bool CHistory::HistorySelectByPositionProcess(const long position_id) +{ + + + double profit=0, profit_close=0; + m_profit_factor = 0; + + + datetime last_exit_time = 0; + datetime overall_last_exit_time = 0; + + if(!HistorySelectByPosition(position_id)) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_HISTORY_SELECTPOSITION_ERR + "(#"+IntegerToString(position_id,0)+") " + TRANSLATION_HISTORY_SELECTPOSITION_FAILED + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(false); + } + + int orders_total=HistoryOrdersTotal(); + for(int i=0; i= 0.0) {m_gross_profit += profit;} + else {m_gross_loss += profit;} + + // Print(dealprofit," |in| ",dealswap," |in| ",dealcomision); + + if(dealvolume > m_max_lot) {m_max_lot = dealvolume;} + + if (last_exit_time < dealtimeClose) {last_exit_time = dealtimeClose;} + } + + if(deal_entry == DEAL_ENTRY_OUT || deal_entry == DEAL_ENTRY_OUT_BY || deal_entry == DEAL_ENTRY_IN || deal_entry == DEAL_ENTRY_INOUT) + { + profit_close = NormalizeDouble(dealprofit + dealswap + dealcomision,2); + m_balance += profit_close; + // m_trades++; + // Print(dealprofit," |out| ",dealswap," |out| ",dealcomision); + + if(profit >= 0.0) + { + m_profit_trades++; + } + + } + + + } + if (last_exit_time > 0) + { + if (overall_last_exit_time == 0 || last_exit_time > overall_last_exit_time) + { + overall_last_exit_time = last_exit_time; + m_closeTime_dt = overall_last_exit_time; + m_closeTime_str = TimeToString(overall_last_exit_time, TIME_DATE); + } + } + if (m_balance > max_balance) + { + max_balance = m_balance; + } + drawdown = NormalizeDouble(max_balance - m_balance, 2); + if(drawdown > m_maxdraw_MDD) {m_maxdraw_MDD = drawdown;} + // Print("balance ",m_balance," | ",max_balance," | ",drawdown," | ",m_maxdraw_MDD); + m_profit = m_gross_profit+m_gross_loss; + + if(MathAbs(m_gross_loss) > FLT_EPSILON) {m_profit_factor = MathAbs(m_gross_profit/m_gross_loss);} + + if(m_trades > 0) + { + m_expected_payoff=m_profit/m_trades; + m_profit_trades_percent = (double)m_profit_trades / m_trades * 100; + } + return true; +} + +double CHistory::Percent(double value,double divider) +{ + if(MathAbs(value)<=FLT_EPSILON) + return(0); + return(100*value/divider); +} + +bool CHistory::AppendDataToCSV(datetime open_time, string symbol, ulong magic, string posType, double volume, double openPric, double Sl, double Tp, double closePrice, datetime close_time, double Commis, double Swp, double profit) +{ + + int fh; + // Save to new format only. + fh = FileOpen(AnalyzePathFile(), FILE_WRITE|FILE_CSV|FILE_ANSI,','); + if (fh == INVALID_HANDLE) + { + ResetLastError(); + string txt = TRANSLATION_FILED_TO_OPEN_FILE_WRITING + AnalyzePathFile() + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSaveRun(txt,false); + m_FileSave.IniFileSave(__FUNCTION__+":: "+ txt, false); + return false; + } + FileWrite(fh, "Open Time", "Symbol", "Magic Number", "Type", "Volume", "Open Price", "S/L", "T/P", "Close Price", "Close Time", "Commission", "Swap", "Profit"); + FileWrite(fh, open_time, symbol, magic, posType, volume, openPric, Sl, Tp, closePrice, close_time, Commis, Swp, profit); + + FileClose(fh); + + + + return true; +} +//--- global variable +double max_balance = -DBL_MAX; +double drawdown = 0.0; +/* +bool CHistory::Calculate(const string Symbl, const long Mgc,datetime time_start,datetime time_end,double initial_deposit=0.0) +{ + + if(!HistorySelect(time_start,time_end)) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_HISTORY_GET_TRADE + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(false); + } + for(int i = HistoryDealsTotal()-1; i >=0; i--) + { + // deals + ulong dealticket = HistoryDealGetTicket(i); + if (dealticket <= 0) { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_DEAL_ERROR_TICKT + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(false); + } + datetime first_entry_time = 0; + datetime last_exit_time = 0; + datetime overall_first_entry_time = 0; + datetime overall_last_exit_time = 0; + + long dealID = 0; + double dealprice = HistoryDealGetDouble(dealticket,DEAL_PRICE); + double dealvolume = HistoryDealGetDouble(dealticket,DEAL_VOLUME); + double dealprofit = HistoryDealGetDouble(dealticket,DEAL_PROFIT); + double dealcommision = HistoryDealGetDouble(dealticket,DEAL_COMMISSION); + double dealswap = HistoryDealGetDouble(dealticket,DEAL_SWAP); + ulong dealmagic = HistoryDealGetInteger(dealticket,DEAL_MAGIC); + string dealcomment = HistoryDealGetString(dealticket,DEAL_COMMENT); + datetime dealtimed = (datetime)HistoryDealGetInteger(dealticket, DEAL_TIME); + string dealDate = TimeToString(dealtimed, TIME_DATE|TIME_MINUTES|TIME_SECONDS); + string dealsymbol = HistoryDealGetString(dealticket,DEAL_SYMBOL); + ENUM_DEAL_ENTRY dealentry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(dealticket,DEAL_ENTRY); + ENUM_DEAL_TYPE dealtype = (ENUM_DEAL_TYPE)HistoryDealGetInteger(dealticket,DEAL_TYPE); + long dealreason = HistoryDealGetInteger(dealticket,DEAL_REASON); + + long posID = 0; + + // orders + ulong orderticket = HistoryDealGetInteger(dealticket,DEAL_ORDER); + long orderID = HistoryOrderGetInteger(orderticket, ORDER_POSITION_ID); + double orderprice = HistoryOrderGetDouble(orderticket,ORDER_PRICE_OPEN); + double ordervolume = HistoryOrderGetDouble(dealticket,ORDER_VOLUME_INITIAL); + datetime ordertimed = (datetime)HistoryOrderGetInteger(orderticket,ORDER_TIME_DONE); + string orderDate = TimeToString(ordertimed, TIME_DATE|TIME_MINUTES|TIME_SECONDS); + string ordersymbol = HistoryOrderGetString(orderticket,ORDER_SYMBOL); + ENUM_ORDER_TYPE ordertype = (ENUM_ORDER_TYPE)HistoryOrderGetInteger(orderticket,ORDER_TYPE); + + if((dealsymbol == Symbl) && (dealmagic == Mgc)) + { + if(dealentry == DEAL_ENTRY_IN) + { + if(dealvolume > m_max_lot) {m_max_lot = dealvolume;} + if (first_entry_time == 0 || dealtimed < first_entry_time) {first_entry_time = dealtimed;} + + dealID = HistoryDealGetInteger(dealticket,DEAL_POSITION_ID); + posID = dealID; + // Print(dealsymbol," in| ",dealcommision," | ",dealprofit," | ",dealmagic," | ",dealticket," | ",dealvolume," |id| ",dealID); + // Print(ordersymbol," in| ",0," | ",0," | ",0," | ",orderticket," | ",ordervolume," |id| ",orderID); + + } + // else if (dealentry == DEAL_ENTRY_OUT) + // { + // if(orderticket == dealID) + // { + // Print("tick ",dealticket, " | ",orderticket); + // } + // // Print(dealsymbol," | ",dealcommision," | ",dealprofit," | ",dealmagic," | ",dealticket," | ",dealvolume); + // // Print(ordersymbol," | ",0," | ",0," | ",0," | ",orderticket," | ",ordervolume); + // } + + // Print(dealsymbol," in| ",dealcommision," | ",dealprofit," | ",dealmagic," | ",dealticket," | ",dealvolume," |id| ",dealID); + // Print(ordersymbol," in| ",0," | ",0," | ",0," | ",orderticket," | ",ordervolume," |id| ",orderID); + } + + if(dealticket == posID) + { + Print(dealticket," | ",orderticket); + // Print(dealsymbol," in| ",dealcommision," | ",dealprofit," | ",dealmagic," | ",dealticket," | ",dealvolume," |id| ",dealID); + // Print(ordersymbol," in| ",0," | ",0," | ",0," | ",orderticket," | ",ordervolume," |id| ",orderID); + } + + + // if(dealID == posID) + // { + // Print(dealsymbol," in| ",dealcommision," | ",dealprofit," | ",dealmagic," | ",dealticket," | ",dealvolume," |id| ",dealID); + // Print(ordersymbol," in| ",0," | ",0," | ",0," | ",orderticket," | ",ordervolume," |id| ",orderID); + // } + if (first_entry_time > 0) + { + if (overall_first_entry_time == 0 || first_entry_time < overall_first_entry_time) + { + overall_first_entry_time = first_entry_time; + m_openTime_str = TimeToString(overall_first_entry_time, TIME_DATE); + } + } + } + + + // Print("maxlot ",m_max_lot," open time ",m_openTime_str," close time ",m_closeTime_str); + return true; +} \ No newline at end of file diff --git a/Retrace/History.mqh b/Retrace/History.mqh new file mode 100644 index 0000000..dd0a6ec --- /dev/null +++ b/Retrace/History.mqh @@ -0,0 +1,787 @@ +#include +#include +#include +#include +#include + +enum deal_result +{ + NO_VALUE=0, + WIN=1, + LOSS +}; +enum ENUM_HISTORY_SORT +{ + HISTORY_SORT_OPENTIME, // Open time + HISTORY_SORT_CLOSETIME // Close time +}; + +class CHistory +{ +private: + CDealInfo m_deal; + CFileSaving m_FileSave; + CArrayDouble m_profit_data; + CArrayDouble m_balance_data; + CArrayDouble m_sharp_balance; + CArrayDouble m_balance_line; + + double m_max_lot; + double m_initial_deposit; + double m_withdrawal; + double m_volume; + double m_swap; + double m_commission; + double m_profit; + double m_gross_profit; + double m_gross_loss; + + double m_profit_factor; + + double m_expected_payoff; + + double m_balance; + double m_maxdraw_MDD; + double m_maxdraw_percent; + // double m_balance_min; + // double m_balance_dd; + // double m_balance_dd_percent; + // double m_balance_dd_relative; + // double m_balance_dd_relative_percent; + // double m_balance_dd_absolute; + + double m_min_peak; + double m_max_peak; + + long arr_Positions[]; + long m_type; + long m_magic; + + int m_deals; + int m_trades; + int m_profit_trades; + double m_profit_trades_percent; + int m_loss_trades; + + string m_symbol; + string m_comment; + string m_openTime_str; + string m_closeTime_str; + + datetime m_openTime_dt; + datetime m_closeTime_dt; + + string m_mqlName; + + // only to save file CSV + datetime c_opTime; + datetime c_clTime; + string c_type; + long c_magic; + double c_volume; + double c_opPrice; + double c_sl; + double c_tp; + double c_clPrice; + double c_commission; + double c_swap; + double c_profit; + double c_profitPoint; + string c_duration; + string c_opComment; + string c_clComment; + +public: + CHistory(void); + ~CHistory(void); + + bool ExportHistoryPositions(const string Cmment); + double MaxLots() {return(m_max_lot);} + // double InitialDeposit() {return(m_initial_deposit);} + // double Withdrawal() {return(m_withdrawal);} + double Profit() {return(m_profit);}; + double GrossProfit() {return(m_gross_profit);} + double GrossLoss() {return(m_gross_loss);} + double MDD() {return(m_maxdraw_MDD);} + double ProfitFactor() {return(m_profit_factor);} + int Trades() {return(m_trades);} + int ProfitTrades() {return(m_profit_trades);}; + double ExpectedPayoff() {return(m_expected_payoff);} + + string OpenTime() {return(m_openTime_str);} + string CloseTime() {return(m_closeTime_str);} + + + double Percent(double value,double divider); + + int CountRowsInCSV(); + bool AppendDataToCSV(); + bool CheckIsFileBot() {return(FileIsExist(m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) +"\\"+ "Trade_Transaction.csv"));} + string AnalyzePathFile() {return(m_mqlName + " EA" + "\\" + AccountInfoString(ACCOUNT_COMPANY) +"\\"+"Trade_Transaction.csv");} + + bool Calculate(const string Symbl,const long Mgc,datetime time_start,datetime time_end); + bool HistorySelectByPositionProcess(const long position_id, const bool saveCsv); + string GetExpertNameWithSum(); + +}; + +CHistory::CHistory(void) +{ + m_mqlName = MQLInfoString(MQL_PROGRAM_NAME); + c_magic = 1; + +} + +CHistory::~CHistory(void) +{ +} + + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CHistory::ExportHistoryPositions(const string Cmment) +{ + datetime time_start = D'2024.12.24'; + int handle= FileOpen(AnalyzePathFile(),FILE_WRITE|FILE_CSV|FILE_ANSI,',');// |FILE_ANSI,',' + if(handle == INVALID_HANDLE) + { + ResetLastError(); + string txt = TRANSLATION_FILED_TO_OPEN_FILE_WRITING + AnalyzePathFile() + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSaveRun(txt,false); + m_FileSave.IniFileSave(__FUNCTION__+":: "+ txt, false); + return false; + } + + FileWrite(handle, "Open Time", "Symbol", "Magic Number", "Type", "Volume", "Open Price", "S/L", "T/P", "Close Price", "Close Time", "Commission", "Swap", "Profit", + "Profit Points", "Duration", "Open Comment", "Close Comment"); + + ulong s_time=GetMicrosecondCount(); + double Balanc=0; + + + if(!HistorySelect(time_start,TimeCurrent())) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_HISTORY_GET_TRADE + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(false); + } + + int deals = HistoryDealsTotal(); + int sort_by = HISTORY_SORT_CLOSETIME; + + if(sort_by==HISTORY_SORT_OPENTIME) + { + for(int i = 0; i < deals && !IsStopped(); i++) + { + if(m_deal.SelectByIndex(i)) + if(m_deal.Entry()==DEAL_ENTRY_IN) + { + if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) + { + //--- save position ids to the array + long position_id=m_deal.PositionId(); + int arr_size=ArraySize(arr_Positions); + ArrayResize(arr_Positions,arr_size+1,100); + arr_Positions[arr_size]=position_id; + } + } + } + } + //--- + if(sort_by==HISTORY_SORT_CLOSETIME) + { + //--- define a hashset to collect position IDs (with no duplicates) + CHashSethashset; + + //--- handle the case when a position has multiple deals out. + for(int i = deals-1; i >= 0 && !IsStopped(); i--) + if(m_deal.SelectByIndex(i)) + { + if(m_deal.Entry() == DEAL_ENTRY_IN && StringFind(m_deal.Comment(), Cmment) != -1) + { + if(m_deal.DealType() == DEAL_TYPE_BUY || m_deal.DealType() == DEAL_TYPE_SELL) + { + hashset.Add(m_deal.PositionId()); + } + } + // if(m_deal.Entry()==DEAL_ENTRY_OUT || m_deal.Entry()==DEAL_ENTRY_OUT_BY) + // if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) + // hashset.Add(m_deal.PositionId()); + } + //--- copy the elements from the set to a compatible one-dimensional array + hashset.CopyTo(arr_Positions,0); + //ArrayReverse(arr_Positions); + ArraySetAsSeries(arr_Positions,true); + } + + //--- now process the list of positions stored in the array + int positions=ArraySize(arr_Positions); + for(int i=0; i1) + { + //--- now process the list of received deals for the specified position + deals=HistoryDealsTotal(); + for(int j=0; j0.00001) + continue; + + //--- Closed position is reconstructed + StringTrimLeft(pos_close_comment); + StringTrimRight(pos_close_comment); + + //--- sums + Balanc+=pos_profit+pos_swap+pos_commission; + + //--- + SymbolSelect(pos_symbol,true); + int digits=(int)SymbolInfoInteger(pos_symbol,SYMBOL_DIGITS); + double point=SymbolInfoDouble(pos_symbol,SYMBOL_POINT); + + FileWrite(handle, + (string)pos_open_time, + pos_symbol, + pos_magic, + (pos_type==DEAL_TYPE_BUY) ? "buy" : (pos_type==DEAL_TYPE_SELL) ? "sell" : "other", + DoubleToString(pos_close_volume,2), + DoubleToString(pos_open_price,digits), + (pos_sl ? DoubleToString(pos_sl,digits) : ""), + (pos_tp ? DoubleToString(pos_tp,digits) : ""), + DoubleToString(pos_close_price,(deals==2 ? digits : digits+3)), + (string)pos_close_time, + DoubleToString(pos_commission,2), + DoubleToString(pos_swap,2), + DoubleToString(pos_profit,2), + MathRound((pos_type == DEAL_TYPE_BUY ? pos_close_price - pos_open_price : pos_open_price - pos_close_price) / point), + // + // (sort_by == HISTORY_SORT_CLOSETIME ? DoubleToString(Balanc,2) : ""), + // + + TimeElapsedToString(pos_close_time - pos_open_time), + pos_open_comment, + pos_close_comment + ); + + } + } + + FileClose(handle); + + + return true; +} + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +string TimeElapsedToString(const datetime pElapsedSeconds) +{ + const long days = pElapsedSeconds / PeriodSeconds(PERIOD_D1); + + return((days ? (string)days + "d " : "") + TimeToString(pElapsedSeconds,TIME_SECONDS)); +} + +bool CHistory::Calculate(const string Symbl, const long Mgc,datetime time_start,datetime time_end) +{ + deal_result result = NO_VALUE; + + int sort_by = HISTORY_SORT_OPENTIME; + + datetime first_entry_time = 0; + datetime overall_first_entry_time = 0; + + datetime open_times[]; + + m_profit=0; + m_gross_profit=0; + m_gross_loss=0; + + + if(!HistorySelect(time_start,time_end)) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_HISTORY_GET_TRADE + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(false); + } + + int deals_total = HistoryDealsTotal(); + + if(sort_by==HISTORY_SORT_OPENTIME) + { + for(int i = 0; i < deals_total && !IsStopped(); i++) + { + if(m_deal.SelectByIndex(i)) + if(m_deal.Entry()==DEAL_ENTRY_IN) + { + if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) + { + if(m_deal.Symbol() != Symbl) + continue; + if(m_deal.Magic() != Mgc) + continue; + //--- save position ids to the array + long position_id=m_deal.PositionId(); + int arr_size=ArraySize(arr_Positions); + if(ArrayResize(arr_Positions,arr_size+1)==arr_size+1) + arr_Positions[arr_size]=position_id; + + + m_trades++; + if (first_entry_time == 0 || m_deal.Time() < first_entry_time) {first_entry_time = m_deal.Time();} + } + } + } + + } + + if(sort_by==HISTORY_SORT_CLOSETIME) + { + //--- define a hashset to collect position IDs (with no duplicates) + CHashSethashset; + + //--- handle the case when a position has multiple deals out. + for(int i = deals_total-1; i >= 0 && !IsStopped(); i--) + if(m_deal.SelectByIndex(i)) + if(m_deal.Entry()==DEAL_ENTRY_OUT || m_deal.Entry()==DEAL_ENTRY_OUT_BY) + if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL) + { + if(m_deal.Symbol() != Symbl) + continue; + if(m_deal.Magic() != Mgc) + continue; + + hashset.Add(m_deal.PositionId()); + } + + + //--- copy the elements from the set to a compatible one-dimensional array + hashset.CopyTo(arr_Positions,0); + //ArrayReverse(arr_Positions); + ArraySetAsSeries(arr_Positions,true); + } + + deals_total = ArraySize(arr_Positions); + for(int i=0; i 0) + { + if (overall_first_entry_time == 0 || first_entry_time < overall_first_entry_time) + { + overall_first_entry_time = first_entry_time; + m_openTime_dt = overall_first_entry_time; + m_openTime_str = TimeToString(overall_first_entry_time, TIME_DATE); + } + } + + return true; +} + + +//+------------------------------------------------------------------+ +//| Select history of orders and deals by position ID and | +//| prints a list of orders and deals for the position in the journal| +//+------------------------------------------------------------------+ +bool CHistory::HistorySelectByPositionProcess(const long position_id, const bool saveCsv) +{ + + + double profit=0, profit_close=0; + m_profit_factor = 0; + c_commission = 0.0; + + datetime last_exit_time = 0; + datetime overall_last_exit_time = 0; + + if(!HistorySelectByPosition(position_id)) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_HISTORY_SELECTPOSITION_ERR + "(#"+IntegerToString(position_id,0)+") " + TRANSLATION_HISTORY_SELECTPOSITION_FAILED + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(false); + } + + int orders_total=HistoryOrdersTotal(); + for(int i=0; i= 0.0) {m_gross_profit += profit;} + else {m_gross_loss += profit;} + + + if(dealvolume > m_max_lot) {m_max_lot = dealvolume;} + + if (last_exit_time < dealtimeClose) {last_exit_time = dealtimeClose;} + } + + if(deal_entry == DEAL_ENTRY_OUT || deal_entry == DEAL_ENTRY_OUT_BY || deal_entry == DEAL_ENTRY_IN || deal_entry == DEAL_ENTRY_INOUT) + { + profit_close = NormalizeDouble(dealprofit + dealswap + dealcomision,2); + m_balance += profit_close; + + if(profit >= 0.0) + { + m_profit_trades++; + } + + } + + + } + if (last_exit_time > 0) + { + if (overall_last_exit_time == 0 || last_exit_time > overall_last_exit_time) + { + overall_last_exit_time = last_exit_time; + m_closeTime_dt = overall_last_exit_time; + m_closeTime_str = TimeToString(overall_last_exit_time, TIME_DATE); + } + } + if (m_balance > max_balance) + { + max_balance = m_balance; + } + drawdown = NormalizeDouble(max_balance - m_balance, 2); + if(drawdown > m_maxdraw_MDD) {m_maxdraw_MDD = drawdown;} + // Print("balance ",m_balance," | ",max_balance," | ",drawdown," | ",m_maxdraw_MDD); + m_profit = m_gross_profit+m_gross_loss; + + if(MathAbs(m_gross_loss) > FLT_EPSILON) {m_profit_factor = MathAbs(m_gross_profit/m_gross_loss);} + + if(m_trades > 0) + { + m_expected_payoff=m_profit/m_trades; + m_profit_trades_percent = (double)m_profit_trades / m_trades * 100; + } + + // Print("c_optime: ", TimeToString(c_opTime, TIME_DATE | TIME_MINUTES | TIME_SECONDS), + // " c_type: ", c_type, + // " c_volume: ", c_volume, + // " c_opPrice: ", c_opPrice, + // " c_sl: ", c_sl, + // " c_tp: ", c_tp, + // " c_clPrice: ", c_clPrice,"\n", + // " c_clTime: ", TimeToString(c_clTime, TIME_DATE | TIME_MINUTES | TIME_SECONDS), + // " commis: " ,c_commission, + // " swap: ", c_swap, + // " profit: ", c_profit,"\n", + // " profit point: ", c_profitPoint, + // " duration: ", c_duration, + // " opcoment: ", c_opComment," cclcom ",c_clComment); + if(saveCsv) {AppendDataToCSV();} + return true; +} + +double CHistory::Percent(double value,double divider) +{ + if(MathAbs(value)<=FLT_EPSILON) + return(0); + return(100*value/divider); +} + +bool CHistory::AppendDataToCSV() +{ + int retryCount = 0; // Initialize the retry counter + const int maxRetries = 3; // Maximum allowed retries + + while (retryCount < maxRetries) + { + int handle = FileOpen(AnalyzePathFile(), FILE_READ | FILE_WRITE | FILE_CSV|FILE_ANSI,','); // | FILE_ANSI, ',' + if (handle != INVALID_HANDLE) + { + // File opened successfully, append data + FileSeek(handle, 0, SEEK_END); + FileWrite(handle, + c_opTime, Symbol(), c_magic, c_type, c_volume, c_opPrice, c_sl, c_tp, + c_clPrice, c_clTime, c_commission, c_swap, c_profit, c_profitPoint, + c_duration, c_opComment, c_clComment); + FileClose(handle); + + return true; // Successfully written to the file + } + else + { + // Handle the file open error + retryCount++; + ResetLastError(); + string errorDetails = TRANSLATION_FILED_TO_OPEN_FILE_WRITING + AnalyzePathFile() + + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSaveRun(errorDetails, false); + m_FileSave.IniFileSave(__FUNCTION__ + ":: " + errorDetails, false); + + // Prepare warning message for the user + string caption = TRANSLATION_FILED_TO_OPEN_FILE_WRITING2; + string warning = StringFormat( + "%s\n%s\n\n%s\n%s (%d/%d)%s%d%s", + TRANSLATION_SAVE_ERR_MESSAG_FILE, AnalyzePathFile(), + TRANSLATION_SAVE_ERR_MESSAG_FILE_OPEN, TRANSLATION_SAVE_ERR_MESSAG_ATTEMPT, + retryCount, maxRetries, TRANSLATION_SAVE_ERR_MESSAG_WILL, maxRetries, + TRANSLATION_SAVE_ERR_MESSAG_ATTEMPTS + ); + + // Show the warning message + int ret = MessageBox(warning, caption, MB_OK | MB_ICONWARNING); + if (ret == IDOK) + { + ExportHistoryPositions("Break EA 651"); // GetExpertNameWithSum() + // continue; // User clicked OK, retry file access + } + } + } + + // Final warning after maximum retries exceeded + string finalWarning = StringFormat( + "%s\n%s\n\n%s%d%s\n%s", + TRANSLATION_SAVE_ERR_MESSAG_FILE, AnalyzePathFile(), + TRANSLATION_SAVE_ERR_MESSAG_AFFTER, maxRetries, + TRANSLATION_SAVE_ERR_MESSAG_ATTEMPTS, TRANSLATION_SAVE_ERR_MESSAG_STOP + ); + MessageBox(finalWarning, "Error", MB_OK | MB_ICONERROR); + + ExpertRemove(); // Stop the expert after exceeding retries + + return false; +} + +string CHistory::GetExpertNameWithSum() +{ + string result; + string expName = MQLInfoString(MQL_PROGRAM_NAME); + int totalSum = 0; + + // Loop through each character in the expert name + for (int i = 0; i < StringLen(expName); i++) + { + int charValue = StringGetCharacter(expName, i); + totalSum += charValue; + } + + result = expName +" EA_"+ IntegerToString(totalSum); + + return result; +} + + +string baseSymbol = ""; + + +void GetMatchingSymbols(string &matchingSymbols[]) +{ + string currentSymbol = Symbol(); // Get the current chart symbol + + if (baseSymbol == "") + { + baseSymbol = currentSymbol; // Set base symbol globally + ArrayResize(matchingSymbols, 1); + matchingSymbols[0] = currentSymbol; // Store the first matching symbol + Print("Base symbol initialized: ", baseSymbol); + return; // Return early with the base symbol + } + + int minLength = MathMin(StringLen(baseSymbol), StringLen(currentSymbol)); + int commonLength = 0; + + for (int i = 0; i < minLength; i++) + { + if (StringGetCharacter(baseSymbol, i) == StringGetCharacter(currentSymbol, i)) + commonLength++; + else + break; + } + + string baseCore = StringSubstr(baseSymbol, 0, commonLength); + string currentCore = StringSubstr(currentSymbol, 0, commonLength); + + if (baseCore != currentCore) + { + baseSymbol = currentSymbol; + ArrayResize(matchingSymbols, 1); + matchingSymbols[0] = currentSymbol; + Print("Symbol change detected: Previous Base = ", baseSymbol, ", New Core = ", currentCore); + } + else + { + ArrayResize(matchingSymbols, ArraySize(matchingSymbols) + 1); + matchingSymbols[ArraySize(matchingSymbols) - 1] = currentSymbol; + } +} + +// Function to count rows in a CSV file +int CHistory::CountRowsInCSV() { + int row_count = 0; + string filename = AnalyzePathFile(); + int file_handle = FileOpen(filename, FILE_READ | FILE_CSV | FILE_ANSI); + + if (file_handle == INVALID_HANDLE) { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_FILED_TO_OPEN_FILE_WRITING3 + AnalyzePathFile() + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_FileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_FileSave.IniFileSaveRun(txt,false); + return(-1); + } + + // Read the file line by line + while (!FileIsEnding(file_handle)) // Loop until the end of the file + { + string firstColumn = FileReadString(file_handle); // Read the first column + if (firstColumn != "") // If the first column is not empty, increment the row count + { + row_count++; + } + // Skip the rest of the columns in the current row + while (!FileIsLineEnding(file_handle) && !FileIsEnding(file_handle)) + { + FileReadString(file_handle); // Read and discard the remaining columns + } + } + + + FileClose(file_handle); // Close the file + return row_count - 1; +} + + + +//--- global variable +double max_balance = -DBL_MAX; +double drawdown = 0.0; + + + + + + + + diff --git a/Retrace/License.mqh b/Retrace/License.mqh new file mode 100644 index 0000000..f131d54 --- /dev/null +++ b/Retrace/License.mqh @@ -0,0 +1,633 @@ +//+------------------------------------------------------------------+ +//| License.mqh | +//| Copyright 2015, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property strict +#define LICENSED_TRADE_MODES {ACCOUNT_TRADE_MODE_DEMO,ACCOUNT_TRADE_MODE_REAL}//{ACCOUNT_TRADE_MODE_CONTEST,ACCOUNT_TRADE_MODE_DEMO} +#define LICENSED_PRIVATE_KEY "Activation Key E" +#define LICENSED_EXPIRY_DAYS 30 + +#include "Setting.mqh" +#include "FileSave.mqh" +#include "Translations/English.mqh" +long InpUserId = 123456; +datetime InpExpiry = D'2020.01.01'; + +class License +{ +private: + CFileSaving m_fileSave; + string g_logMessages; +protected: + string m_mqlName; + string m_account; + string m_userid; + string m_expiry; + + + + + +public: + License(); + ~License(); + + void Initialization(); + bool CheckTradeModes(); + bool VerifyLicenseWeb(); + bool CheckAccountMarginMode(); +private: + string IniFileName(const bool Log) const; + bool IniFileDelete(void) {return FileDelete(m_fileSave.DirectoryLogFile());} + string LoadPathSetting() {return ("Licence\\"+m_mqlName+"\\" +IniFileName(false));} + bool SaveSettingsOnDisk(); + bool LoadSettingsFromDisk(); + bool FileGen(); + string Hash(string data); + string KeyGen( string data ); + bool CheckIsFile() { return FileIsExist(LicencePath());} + bool CreateLicenseFile(); + bool VerifyLicenseFile(); + string LicencePath(); + bool LoadDataFile( string &data ); + string SanitizeFileName(string fileName); + long Current_Account_Mode() {return AccountInfoInteger(ACCOUNT_TRADE_MODE);} + bool LoadDataServer( string &data ); + + +}; + +License::License() +{ +} + +License::~License() +{ +} + + +void License::Initialization() +{ + m_mqlName = MQLInfoString(MQL_PROGRAM_NAME); + m_account = IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)); + IniFileDelete(); + string txt = "\n"+__FUNCTION__+":: "+TRANSLATION_EXPERT_START; + m_fileSave.IniFileSave(txt,false); + m_fileSave.IniFileSaveRun(TRANSLATION_EXPERT_START,false); + if (!LoadSettingsFromDisk()) {SaveSettingsOnDisk();} +} + +string License::IniFileName(const bool Log) const +{ + string name; + + name=m_mqlName; + + if(Log) {name+="_Log";} + else {name+="_Setttings";} + name+="_Ini.txt"; + + return(name); +} + +bool License::SaveSettingsOnDisk() +{ + Sets.LoginUserID = IntegerToString(InpUserId); + Sets.LoginExpiry = TimeToString(InpExpiry,TIME_DATE); + + ResetLastError(); + string txt = TRANSLATION_TRYING_TO_SAVE_FILE + IniFileName(false)+TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+ txt,false); + m_fileSave.IniFileSaveRun(txt,false); + int fh; + // Save to new format only. + fh = FileOpen(LoadPathSetting(), FILE_CSV | FILE_WRITE); + if (fh == INVALID_HANDLE) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_LICENSE_FILED_TO_OPEN_ + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return false; + } + + //--- Sets + FileWrite(fh, "LoginUserID"); + FileWrite(fh, Sets.LoginUserID); + FileWrite(fh, "LoginExpiry"); + FileWrite(fh, Sets.LoginExpiry); + + + FileClose(fh); + + ResetLastError(); + txt = TRANSLATION_SAVE_DONE + IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+ txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return true; +} + +bool License::LoadSettingsFromDisk() +{ + ResetLastError(); + string txt = TRANSLATION_LICENSE_TRYING_TO_LOAD + IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+ txt,false); + m_fileSave.IniFileSaveRun(txt,false); + int fh; + if (!FileIsExist(LoadPathSetting())) + { + ResetLastError(); + string txt = " ⚠ "+ TRANSLATION_LICENSE_NO_SETTINGS + IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return false; + } + fh = FileOpen(LoadPathSetting(), FILE_CSV | FILE_READ); + if (fh == INVALID_HANDLE) + { + ResetLastError(); + string txt =" ⚠ "+ TRANSLATION_LICENSE_FAILED_TO_OPEN_FILE_READING+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return false; + } + while (!FileIsEnding(fh)) + { + string var_name = FileReadString(fh); + string var_content = FileReadString(fh); + + if (var_name == "LoginUserID") + Sets.LoginUserID = (var_content); + else if (var_name == "LoginExpiry") + Sets.LoginExpiry = (var_content); + } + FileClose(fh); + + ResetLastError(); + txt = TRANSLATION_LICENSE_LOADED_DONE + IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+ txt,false); + m_fileSave.IniFileSaveRun(txt,false); + + return true; +} + +string License::Hash(string data) +{ + uchar dataCharArray[]; + StringToCharArray(data, dataCharArray); + + uchar combinedCharArray[]; + int combinedSize = ArraySize(dataCharArray); + ArrayResize(combinedCharArray, combinedSize); + ArrayCopy(combinedCharArray, dataCharArray, 0, 0, ArraySize(dataCharArray)); + + // Generate SHA-256 hash + uchar hashResult[]; + if (!CryptEncode(CRYPT_HASH_SHA256, combinedCharArray, combinedCharArray, hashResult)) { + ResetLastError(); + string txt = TRANSLATION_LICENSE_ERROR_HASH + TRANSLATION_MESSAGE_ERROR +IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return ""; + } + + // Base64 encode the hash result + uchar base64Result[]; + if (!CryptEncode(CRYPT_BASE64, hashResult, hashResult, base64Result)) { + ResetLastError(); + string txt = TRANSLATION_LICENSE_ERROR_BASE + TRANSLATION_MESSAGE_ERROR +IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return ""; + } + + // Convert Base64 result to string for the final passcode + string result = CharArrayToString(base64Result); + + return result; +} + +string License::KeyGen( string data ) { + string keyString = data + m_mqlName; + return Hash( keyString ); +} + +bool License::FileGen() { + // Step 1: Ensure directory structure exists by creating a dummy file temporarily. + string licenceDirPath = "Licence\\"+m_mqlName+"\\dummy.txt"; + int dummyHandle = FileOpen(licenceDirPath, FILE_WRITE | FILE_ANSI); + if (dummyHandle == INVALID_HANDLE) { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_CREATE_DIRECTORY+m_mqlName+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return false; + } + FileClose(dummyHandle); + FileDelete(licenceDirPath); // Delete the dummy file afterward + + // Step 2: Proceed to create the actual licence file + string licencePath = LicencePath(); + int handle = FileOpen(licencePath, FILE_WRITE | FILE_BIN | FILE_ANSI); + if (handle == INVALID_HANDLE) { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_NO_CREATE_FILE+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return false; + } + + // Combine signature and data into one line + string data_hash = Hash(m_account + "_" + Sets.LoginExpiry + "_" + Sets.LoginUserID + "_" + m_mqlName + "_" + LICENSED_PRIVATE_KEY); + string signature = KeyGen(data_hash); + string contents = signature + data_hash + "\n" + Sets.LoginExpiry; + // Print(licencePath); // show name file + // Print(contents); // show hahs + FileWriteString(handle, contents); + FileFlush(handle); + FileClose(handle); + + ResetLastError(); + string txt = TRANSLATION_LICENSE_CREATE_LICENSE_FILE+TRANSLATION_MESSAGE_ERROR+ IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + return true; +} + +bool License::CreateLicenseFile() +{ + // Check if the file exists and verify if it matches current inputs + if(CheckIsFile()) + { + if(VerifyLicenseFile()) {return true;} + else + { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_RETRY+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + FileDelete(LicencePath()); + Alert(TRANSLATION_LICENSE_RETRY+"."); + return false; + } + } + + if(FileGen()) + { + if(CheckIsFile()) + { + ResetLastError(); + string txt =TRANSLATION_LICENSE_TO_CREATE+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + + return true; + } + } + + return false; +} + +bool License::VerifyLicenseFile() +{ + string licencePath = LicencePath(); + int maxAttempts = 2; // Allow one retry + int attempt = 0; + + while (attempt < maxAttempts) + { + attempt++; + + // Attempt to open the file + int handle = FileOpen(licencePath, FILE_READ | FILE_BIN | FILE_ANSI); + if (handle == INVALID_HANDLE) + { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_FAILET_TO_OPEN_FILE+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt, false); + m_fileSave.IniFileSaveRun(txt, false); + Alert(TRANSLATION_LICENSE_FAILET_TO_OPEN_FILE+"."); + return false; // Cannot open file, no retry possible + } + + // Read the file contents + string fileContents = FileReadString(handle); + FileClose(handle); + + // Generate the expected data hash + string data_hash = Hash(m_account + "_" + Sets.LoginExpiry + "_" + Sets.LoginUserID + "_" + m_mqlName + "_" + LICENSED_PRIVATE_KEY); + string signature = KeyGen(data_hash); + string expectedContents = signature + data_hash + "\n" + Sets.LoginExpiry; + + // Check if the file contents match the expected format and data + if (fileContents == expectedContents) + { + return true; // Verification succeeded + } + + // Log the error for this attempt + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_NO_VERIFY_INPUTS+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt, false); + m_fileSave.IniFileSaveRun(txt, false); + + // Retry if more attempts are allowed + if (attempt < maxAttempts) + { + ResetLastError(); + string txt =" ⚠ "+TRANSLATION_LICENSE_FAILED_RETRY_CREATE+IntegerToString(attempt+1)+TRANSLATION_LICENSE_FAILED_RETRY_CREATE+ + IntegerToString(maxAttempts)+")"+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt, false); + m_fileSave.IniFileSaveRun(txt, false); + Sleep(500); // Add a small delay before retrying + continue; + } + + // After maximum attempts, show alert and fail + ResetLastError(); + txt = " ⚠ "+TRANSLATION_LICENSE_FAILED_RETRY_ERROR1+"\n"+TRANSLATION_LICENSE_FAILED_RETRY_ERROR2+"\n"+ + TRANSLATION_LICENSE_FAILED_RETRY_ERROR3+"\n"+TRANSLATION_LICENSE_FAILED_RETRY_ERROR4+"\n"+TRANSLATION_LICENSE_ERROR_404_2+ + TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt, false); + m_fileSave.IniFileSaveRun(txt, false); + Alert(TRANSLATION_LICENSE_FAILED_RETRY_ERROR1+"\n"+TRANSLATION_LICENSE_FAILED_RETRY_ERROR2+"\n"+ + TRANSLATION_LICENSE_FAILED_RETRY_ERROR3+"\n"+TRANSLATION_LICENSE_FAILED_RETRY_ERROR4+"\n"+TRANSLATION_LICENSE_ERROR_404_2+"."); + return false; + } + + return false; +} + +// bool License::VerifyLicenseFile() +// { + + + +// string licencePath = LicencePath(); +// int handle = FileOpen(licencePath, FILE_READ | FILE_BIN | FILE_ANSI); +// if(handle == INVALID_HANDLE) +// { +// ResetLastError(); +// string txt = __FUNCTION__+":: ⚠ "+TRANSLATION_LICENSE_FAILET_TO_OPEN_FILE+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); +// m_fileSave.IniFileSave(txt,false); +// m_fileSave.IniFileSaveRun(txt,false); +// Alert(TRANSLATION_LICENSE_FAILET_TO_OPEN_FILE+"."); +// return false; +// } + +// // Read the file contents +// string fileContents = FileReadString(handle); +// FileClose(handle); + +// // Generate the expected data hash +// string data_hash = Hash(m_account + "_" + Sets.LoginExpiry + "_" + Sets.LoginUserID + "_" + m_mqlName + "_" + LICENSED_PRIVATE_KEY); +// string signature = KeyGen(data_hash); +// string expectedContents = signature + data_hash + "\n" + Sets.LoginExpiry; + +// // Check if the file contents match the expected format and data +// if (fileContents == expectedContents) {return true;} +// ResetLastError(); +// string txt = __FUNCTION__+":: ⚠ "+TRANSLATION_LICENSE_NO_VERIFY_INPUTS+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); +// m_fileSave.IniFileSave(txt,false); +// m_fileSave.IniFileSaveRun(txt,false); +// Alert(TRANSLATION_LICENSE_NO_VERIFY_INPUTS+"."); +// return false; +// } + +bool License::LoadDataFile( string &data ) { + + string licencePath = LicencePath(); + int handle = FileOpen( licencePath, FILE_READ | FILE_BIN | FILE_ANSI ); + if ( handle == INVALID_HANDLE ) { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_NO_OPEN_FILE+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Alert(TRANSLATION_LICENSE_NO_OPEN_FILE+"."); + return ( false ); + } + + int len = ( int )FileSize( handle ); + data = FileReadString( handle, len ); + FileClose( handle ); + return true; +} + +string License::LicencePath() +{ + string rawHash = Hash(m_mqlName + "_" + m_account); + string sanitizedHash = SanitizeFileName(rawHash); + return ("Licence\\" + m_mqlName + "\\" + sanitizedHash + ".lic"); +} + +string License::SanitizeFileName(string fileName) +{ + // List of invalid characters to replace/remove + string invalidChars = "\\/:*?\"<>|"; + + // Replace invalid characters with an underscore (_) + for (int i = 0; i < StringLen(invalidChars); i++) { + // Extract each invalid character as a string + string invalidChar = StringSubstr(invalidChars, i, 1); + // Update fileName directly + StringReplace(fileName, invalidChar, "_"); + } + + return fileName; +} + +// -- check trade mode user +bool License::CheckTradeModes(){ + int validModes[] = LICENSED_TRADE_MODES; + for (int i = ArraySize(validModes) - 1; i >= 0; i--) { + if (Current_Account_Mode() == validModes[i]) { + return true; + } + } + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_AUTHORIZED+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Alert(TRANSLATION_LICENSE_AUTHORIZED+"."); + return false; // Return false if no valid mode was found +} + +bool License::LoadDataServer( string &data ) +{ + string headers = ""; + char postData[]; + char resultData[]; + string resultHeaders; + int timeout = 10000; // 10 seconds standard timeout + int delayThreshold = 5000; + + string rawHash = Hash(m_mqlName + "_" + m_account); + string mRegistration = SanitizeFileName(rawHash); + + + string url = "https://raw.githubusercontent.com"; + // string api = StringFormat( "%s/amirghadiri1987/License/blob/main/%s.txt", url, mRegistration ); + string api = StringFormat( "%s/amirghadiri1987/License/refs/heads/main/%s.lic", url, mRegistration ); + + // Start tracking the time for feedback + datetime startTime = TimeLocal(); + + ResetLastError(); + int response = WebRequest( "GET", api, headers, timeout, postData, resultData, resultHeaders ); + + // Add this code to handle 303 redirect but it creates more problems + // if (response==303) { + // int locStart = StringFind(resultHeaders, "Location: ", 0)+10; + // int locEnd = StringFind(resultHeaders, "\r", locStart); + // api = StringSubstr(resultHeaders, locStart, locEnd-locStart); + // ResetLastError(); + // response = WebRequest( "GET", api, headers, timeout, postData, resultData, resultHeaders ); + // errorCode = GetLastError(); + //} + + if ((TimeLocal() - startTime) > delayThreshold / 1000) { + Comment("The license check is taking longer than expected. Please wait..."); + } + + data = CharArrayToString( resultData ); + + switch ( response ) { + case -1: + { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_ERROR_RESPONSE+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + ResetLastError(); + txt = " ⚠ "+TRANSLATION_LICENSE_ADD_URL + url + TRANSLATION_LICENSE_ADD_URL2+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Alert(TRANSLATION_LICENSE_ADD_URL + url + TRANSLATION_LICENSE_ADD_URL2+"."); + Comment(""); + return false; + } + break; + case 200: + //--- Success + Comment(""); + return true; + break; + case 404: + { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_ERROR_404+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Alert(TRANSLATION_LICENSE_ERROR_404+"\n"+TRANSLATION_LICENSE_ERROR_404_2+"."); + Comment(""); + return false; + } + break; + default: + { + ResetLastError(); + string txt = TRANSLATION_LICENSE_ERROE_UNEXPECTED+ IntegerToString(response)+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+":: "+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Comment(""); + return false; + } + break; + } + + Comment(""); // Clear any comment on exit + return false; +} + +bool License::VerifyLicenseWeb() +{ + // Check if license file creation was successful + if (!CreateLicenseFile()) + { + return false; + } + + // Load data from server and file + string data_server, data_file; + if (!LoadDataServer(data_server)) + { + return false; + } + if (!LoadDataFile(data_file)) + { + return false; + } + + // Parse server data + int pos_Server = StringFind(data_server, "\n"); + if (pos_Server <= 0) + { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_INVALID_LICENSE_SERVER+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Alert(TRANSLATION_LICENSE_INVALID_LICENSE_SERVER+"."); + return false; + } + + // Parse file data + int pos_File = StringFind(data_file, "\n"); + if (pos_File <= 0) + { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_INVALID_LICENSE_FILE+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Alert(TRANSLATION_LICENSE_INVALID_LICENSE_FILE+"."); + return false; + } + + string signature_Server = StringSubstr( data_server, 0, pos_Server ); + string expiry_Server = StringSubstr( data_server, pos_Server + 1 ); + + string signature_File = StringSubstr( data_file, 0, pos_File ); + string expiry_File = StringSubstr( data_file, pos_File + 1 ); + Sets.SHowExpiry = expiry_Server; + // Validate signatures and expiry dates + if (signature_Server != signature_File || expiry_Server != expiry_File) { + ResetLastError(); + string txt = " ⚠ "+TRANSLATION_LICENSE_VERIFY_LICENSE+TRANSLATION_MESSAGE_ERROR+IntegerToString(GetLastError()); + m_fileSave.IniFileSave(__FUNCTION__+"::"+txt,false); + m_fileSave.IniFileSaveRun(txt,false); + Alert(TRANSLATION_LICENSE_VERIFY_LICENSE); + return false; + } + + // All checks passed + return true; +} + +bool License::CheckAccountMarginMode() +{ + if(AccountInfoInteger(ACCOUNT_MARGIN_MODE)!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) + { + ResetLastError(); + string txt = TRANSLATION_TERMINAL_MARGIN_MODE_HEDGE + TRANSLATION_MESSAGE_ERROR + IntegerToString(GetLastError()); + m_fileSave.IniFileSaveRun(txt,false); + m_fileSave.IniFileSave(__FUNCTION__+":: "+ txt, false); + Alert(TRANSLATION_TERMINAL_MARGIN_MODE_HEDGE+"."); + return false; + + } + return true; +} + + + + + + + + + + + + + diff --git a/Retrace/ListView_New.mqh b/Retrace/ListView_New.mqh new file mode 100644 index 0000000..bb019e5 --- /dev/null +++ b/Retrace/ListView_New.mqh @@ -0,0 +1,564 @@ +//+------------------------------------------------------------------+ +//| ListView_New.mqh | +//| Copyright 2000-2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#include +#include +#include +#include +#include "Colors.mqh" +#include "Setting.mqh" + +//+------------------------------------------------------------------+ +//| Class CListView | +//| Usage: display lists | +//+------------------------------------------------------------------+ +class CListView : public CWndClient + { +private: + CThemes m_Themes; + //--- dependent controls + // CThemes m_Themes; + CEdit m_rows[]; // array of the row objects + //--- set up + int m_offset; // index of first visible row in array of rows + int m_total_view; // number of visible rows + int m_item_height; // height of visible row + bool m_height_variable; // ������� ���������� ������ ������ + //--- data + CArrayString m_strings; // array of rows + CArrayLong m_values; // array of values + int m_current; // index of current row in array of rows + + +public: + CListView(void); + ~CListView(void); + color m_BgGround_Item, m_BgGround_Item_TextSel; + //--- create + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); + virtual void Destroy(const int reason=0); + //--- chart event handler + virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); + //--- set up + bool TotalView(const int value); + //--- fill + virtual bool AddItem(const string item,const long value=0); + //--- data + virtual bool ItemAdd(const string item,const long value=0); + virtual bool ItemInsert(const int index,const string item,const long value=0); + virtual bool ItemUpdate(const int index,const string item,const long value=0); + virtual bool ItemDelete(const int index); + virtual bool ItemsClear(void); + //--- data + int Current(void) { return(m_current); } + string Select(void) { return(m_strings.At(m_current)); } + bool Select(const int index); + bool SelectByText(const string text); + bool SelectByValue(const long value); + //--- data (read only) + long Value(void) { return(m_values.At(m_current)); } + void SetBackGroundItem(const color BgGroundItem, const color BgGroundItemTextSel); + + //--- state + virtual bool Show(void); + +protected: + //--- create dependent controls + bool CreateRow(const int index); + //--- event handlers + virtual bool OnResize(void); + //--- handlers of the dependent controls events + virtual bool OnVScrollShow(void); + virtual bool OnVScrollHide(void); + virtual bool OnScrollLineDown(void); + virtual bool OnScrollLineUp(void); + virtual bool OnItemClick(const int index); + //--- redraw + bool Redraw(void); + bool RowState(const int index,const bool select); + bool CheckView(void); + }; +//+------------------------------------------------------------------+ +//| Common handler of chart events | +//+------------------------------------------------------------------+ +EVENT_MAP_BEGIN(CListView) + ON_INDEXED_EVENT(ON_CLICK,m_rows,OnItemClick) +EVENT_MAP_END(CWndClient) +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CListView::CListView(void) : m_offset(0), + m_total_view(0), + m_item_height(CONTROLS_LIST_ITEM_HEIGHT), + m_current(CONTROLS_INVALID_INDEX), + m_height_variable(false) + { + m_Themes.ApplyTheme((int)Sets.Themes); + m_BgGround_Item = m_Themes.CONTROL_COMBOBOX_BACKGROUND_ITEM; + m_BgGround_Item_TextSel = m_Themes.CONTROL_COMBOBOX_BACKGROUND_ITEM_TEXT_SELL; + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CListView::~CListView(void) + { + } +//+------------------------------------------------------------------+ +//| Create a control | +//+------------------------------------------------------------------+ +bool CListView::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) + { + int y=y2; +//--- if the number of visible rows is previously determined, adjust the vertical size + if(!TotalView((y2-y1)/m_item_height)) + y=m_item_height+y1+2*CONTROLS_BORDER_WIDTH; +//--- check the number of visible rows + if(m_total_view<1) + return(false); +//--- call method of the parent class + if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y)) + return(false); +//--- set up + if(!m_background.ColorBackground(CONTROLS_LIST_COLOR_BG)) + return(false); + if(!m_background.ColorBorder(CONTROLS_LIST_COLOR_BORDER)) + return(false); +//--- create dependent controls + ArrayResize(m_rows,m_total_view); + for(int i=0;i0) + m_rows[i].Hide(); + } +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Delete group of controls | +//+------------------------------------------------------------------+ +void CListView::Destroy(const int reason) + { +//--- call of the method of the parent class + CWndClient::Destroy(reason); +//--- clear items + m_strings.Clear(); + m_values.Clear(); +//--- + m_offset =0; + m_total_view=0; + } +//+------------------------------------------------------------------+ +//| Set parameter | +//+------------------------------------------------------------------+ +bool CListView::TotalView(const int value) + { +//--- if parameter is not equal to 0, modifications are not possible + if(m_total_view!=0) + { + m_height_variable=true; + return(false); + } +//--- save value + m_total_view=value; +//--- parameter has been changed + return(true); + } +//+------------------------------------------------------------------+ +//| Makes the control visible | +//+------------------------------------------------------------------+ +bool CListView::Show(void) + { +//--- call of the method of the parent class + CWndClient::Show(); +//--- number of items + int total=m_strings.Total(); +//--- + if(total==0) + total=1; +//--- + if(m_height_variable && total=m_strings.Total()) + return(false); + if(index<0 && index!=CONTROLS_INVALID_INDEX) + return(false); +//--- unselect + if(m_current!=CONTROLS_INVALID_INDEX) + RowState(m_current-m_offset,false); +//--- select + if(index!=CONTROLS_INVALID_INDEX) + RowState(index-m_offset,true); +//--- save value + m_current=index; +//--- succeed + return(CheckView()); + } +//+------------------------------------------------------------------+ +//| Set current item (by text) | +//+------------------------------------------------------------------+ +bool CListView::SelectByText(const string text) + { +//--- find text + int index=m_strings.SearchLinear(text); +//--- if text is not found, exit without changing the selection + if(index==CONTROLS_INVALID_INDEX) + return(false); +//--- change selection + return(Select(index)); + } +//+------------------------------------------------------------------+ +//| Set current item (by value) | +//+------------------------------------------------------------------+ +bool CListView::SelectByValue(const long value) + { +//--- find value + int index=m_values.SearchLinear(value); +//--- if value is not found, exit without changing the selection + if(index==CONTROLS_INVALID_INDEX) + return(false); +//--- change selection + return(Select(index)); + } +//+------------------------------------------------------------------+ +//| Redraw | +//+------------------------------------------------------------------+ +bool CListView::Redraw(void) + { +//--- loop by "rows" + for(int i=0;i=ArraySize(m_rows)) + return(true); +//--- determine colors + color text_color=(select) ? m_BgGround_Item_TextSel : CONTROLS_LISTITEM_COLOR_TEXT; // CONTROLS_LISTITEM_COLOR_TEXT + color back_color=(select) ? CONTROLS_LISTITEM_COLOR_BG_SEL : m_BgGround_Item; +//--- get pointer + CEdit *item=GetPointer(m_rows[index]); +//--- recolor the "row" + return(item.Color(text_color) && item.ColorBackground(back_color) && item.ColorBorder(back_color)); + } +//+------------------------------------------------------------------+ +//| Check visibility of selected row | +//+------------------------------------------------------------------+ +bool CListView::CheckView(void) + { +//--- check visibility + if(m_current>=m_offset && m_currentm_total_view) ? m_current : total-m_total_view; +//--- adjust the scrollbar + m_scroll_v.CurrPos(m_offset); +//--- redraw + return(Redraw()); + } +//+------------------------------------------------------------------+ +//| Handler of resizing | +//+------------------------------------------------------------------+ +bool CListView::OnResize(void) + { +//--- call of the method of the parent class + if(!CWndClient::OnResize()) + return(false); +//--- set up the size of "row" + if(VScrolled()) + OnVScrollShow(); + else + OnVScrollHide(); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Handler of the "Show vertical scrollbar" event | +//+------------------------------------------------------------------+ +bool CListView::OnVScrollShow(void) + { +//--- loop by "rows" + for(int i=0;i