From e829dab822196c3e26d04051f17a2e412db4a03a Mon Sep 17 00:00:00 2001 From: amirghadiri1987 <144431373+amirghadiri1987@users.noreply.github.com> Date: Fri, 7 Feb 2025 19:13:59 +0330 Subject: [PATCH] Add files via upload --- OLAP/CSVcube.mqh | Bin 0 -> 10376 bytes OLAP/GUI/OLAPGUI.mqh | Bin 0 -> 30940 bytes OLAP/GUI/OLAPGUI_Opts.mqh | Bin 0 -> 9262 bytes OLAP/GUI/OLAPGUI_Trades.mqh | Bin 0 -> 11600 bytes OLAP/GroupReportInputs.mqh | Bin 0 -> 568 bytes OLAP/HTMLcube.mqh | Bin 0 -> 4744 bytes OLAP/OLAPCommon.mqh | Bin 0 -> 94238 bytes OLAP/OLAPOpts.mqh | Bin 0 -> 20954 bytes OLAP/OLAPQuotes.mqh | Bin 0 -> 16312 bytes OLAP/OLAPTrades.mqh | Bin 0 -> 30332 bytes OLAP/OLAPTradesCustom.mqh | Bin 0 -> 6718 bytes OLAP/PairArray.mqh | Bin 0 -> 8656 bytes OLAP/ReportCubeBase.mqh | Bin 0 -> 19670 bytes OLAP/TSTcube.mqh | Bin 0 -> 7004 bytes OpenCL/Element.mqh | 27 + OpenCL/OpenCL.mqh | 659 ++++++++++++ Orchard/LicenceCheck/LicenceFileCheck.mqh | 124 +++ Orchard/LicenceCheck/LicenceWebCheck.mqh | 97 ++ Orchard/LicenceCheck/WebLicenceTest.mqh | 76 ++ PairPlot/Histogram.mqh | Bin 0 -> 19282 bytes PairPlot/PairPlot.mqh | Bin 0 -> 31922 bytes PairPlot/PairPlotDemo.mqh | Bin 0 -> 6350 bytes PairPlot/Plot.mqh | Bin 0 -> 47460 bytes PairPlot/PlotBase.mqh | 163 +++ PairPlot/Scatter.mqh | 66 ++ Panel/ElButton.mqh | Bin 0 -> 6094 bytes Panel/ElChart.mqh | Bin 0 -> 32658 bytes Panel/Events/Event.mqh | Bin 0 -> 3404 bytes Panel/Events/EventChart.mqh | Bin 0 -> 3268 bytes Panel/Events/EventChartEndEdit.mqh | Bin 0 -> 956 bytes Panel/Events/EventChartObjClick.mqh | Bin 0 -> 974 bytes Panel/Events/EventRefresh.mqh | Bin 0 -> 1256 bytes Panel/Node.mqh | Bin 0 -> 13044 bytes ProgressBars/Colors.mqh | 805 ++++++++++++++ ProgressBars/Defines.mqh | 21 + ProgressBars/Element.mqh | 243 +++++ ProgressBars/Enums.mqh | Bin 0 -> 2168 bytes ProgressBars/Objects.mqh | 306 ++++++ ProgressBars/Window.mqh | Bin 0 -> 94624 bytes ProgressBars/WndContainer.mqh | Bin 0 -> 11420 bytes ProgressBars/WndEvents.mqh | Bin 0 -> 24646 bytes Retrace/Button.mqh | 152 +++ Retrace/Colors.mqh | 685 ++++++++++++ Retrace/ComboBox_New.mqh | 332 ++++++ Retrace/Dialog.mqh | 1164 +++++++++++++++++++++ Retrace/FileSave.mqh | 111 ++ Retrace/Font.mqh | 63 ++ Retrace/History copy.mqh | 467 +++++++++ Retrace/History.mqh | 787 ++++++++++++++ Retrace/License.mqh | 633 +++++++++++ Retrace/ListView_New.mqh | 564 ++++++++++ Retrace/Setting.mqh | 151 +++ Retrace/Translations/Arabic.mqh | 189 ++++ Retrace/Translations/Chinese.mqh | 190 ++++ Retrace/Translations/English.mqh | 373 +++++++ Retrace/Translations/Germain.mqh | 189 ++++ Retrace/Translations/Iran.mqh | 189 ++++ Retrace/Translations/Portuguese.mqh | 189 ++++ Retrace/res/CheckBoxOff.bmp | Bin 0 -> 576 bytes Retrace/res/CheckBoxOn.bmp | Bin 0 -> 576 bytes Retrace/res/Close.bmp | Bin 0 -> 1080 bytes Retrace/res/Close_Panel.bmp | Bin 0 -> 1080 bytes Retrace/res/Close_PanelRED.bmp | Bin 0 -> 1080 bytes Retrace/res/DateDropOff.bmp | Bin 0 -> 2104 bytes Retrace/res/DateDropOn.bmp | Bin 0 -> 2104 bytes Retrace/res/Down.bmp | Bin 0 -> 824 bytes Retrace/res/DownTransp.bmp | Bin 0 -> 1080 bytes Retrace/res/Down_Panel.bmp | Bin 0 -> 1080 bytes Retrace/res/DropOff.bmp | Bin 0 -> 1080 bytes Retrace/res/DropOn.bmp | Bin 0 -> 1080 bytes Retrace/res/Expand2.bmp | Bin 0 -> 1078 bytes Retrace/res/Left.bmp | Bin 0 -> 824 bytes Retrace/res/LeftTransp.bmp | Bin 0 -> 1080 bytes Retrace/res/MaximizableAppDialog.mqh | 340 ++++++ Retrace/res/Moon_Panel.bmp | Bin 0 -> 1080 bytes Retrace/res/RadioButtonOff.bmp | Bin 0 -> 632 bytes Retrace/res/RadioButtonOn.bmp | Bin 0 -> 632 bytes Retrace/res/Restore.bmp | Bin 0 -> 1080 bytes Retrace/res/Right.bmp | Bin 0 -> 824 bytes Retrace/res/RightTransp.bmp | Bin 0 -> 1080 bytes Retrace/res/SpinDec.bmp | Bin 0 -> 568 bytes Retrace/res/SpinInc.bmp | Bin 0 -> 568 bytes Retrace/res/Sun_Panel.bmp | Bin 0 -> 1080 bytes Retrace/res/ThumbHor.bmp | Bin 0 -> 1144 bytes Retrace/res/ThumbVert.bmp | Bin 0 -> 1112 bytes Retrace/res/Turn.bmp | Bin 0 -> 1080 bytes Retrace/res/Up.bmp | Bin 0 -> 824 bytes Retrace/res/UpTransp.bmp | Bin 0 -> 1080 bytes Retrace/res/Up_Panel.bmp | Bin 0 -> 1080 bytes Retrace/res/size10.bmp | Bin 0 -> 1078 bytes Retrace/res/size6.bmp | Bin 0 -> 1078 bytes 91 files changed, 9355 insertions(+) create mode 100644 OLAP/CSVcube.mqh create mode 100644 OLAP/GUI/OLAPGUI.mqh create mode 100644 OLAP/GUI/OLAPGUI_Opts.mqh create mode 100644 OLAP/GUI/OLAPGUI_Trades.mqh create mode 100644 OLAP/GroupReportInputs.mqh create mode 100644 OLAP/HTMLcube.mqh create mode 100644 OLAP/OLAPCommon.mqh create mode 100644 OLAP/OLAPOpts.mqh create mode 100644 OLAP/OLAPQuotes.mqh create mode 100644 OLAP/OLAPTrades.mqh create mode 100644 OLAP/OLAPTradesCustom.mqh create mode 100644 OLAP/PairArray.mqh create mode 100644 OLAP/ReportCubeBase.mqh create mode 100644 OLAP/TSTcube.mqh create mode 100644 OpenCL/Element.mqh create mode 100644 OpenCL/OpenCL.mqh create mode 100644 Orchard/LicenceCheck/LicenceFileCheck.mqh create mode 100644 Orchard/LicenceCheck/LicenceWebCheck.mqh create mode 100644 Orchard/LicenceCheck/WebLicenceTest.mqh create mode 100644 PairPlot/Histogram.mqh create mode 100644 PairPlot/PairPlot.mqh create mode 100644 PairPlot/PairPlotDemo.mqh create mode 100644 PairPlot/Plot.mqh create mode 100644 PairPlot/PlotBase.mqh create mode 100644 PairPlot/Scatter.mqh create mode 100644 Panel/ElButton.mqh create mode 100644 Panel/ElChart.mqh create mode 100644 Panel/Events/Event.mqh create mode 100644 Panel/Events/EventChart.mqh create mode 100644 Panel/Events/EventChartEndEdit.mqh create mode 100644 Panel/Events/EventChartObjClick.mqh create mode 100644 Panel/Events/EventRefresh.mqh create mode 100644 Panel/Node.mqh create mode 100644 ProgressBars/Colors.mqh create mode 100644 ProgressBars/Defines.mqh create mode 100644 ProgressBars/Element.mqh create mode 100644 ProgressBars/Enums.mqh create mode 100644 ProgressBars/Objects.mqh create mode 100644 ProgressBars/Window.mqh create mode 100644 ProgressBars/WndContainer.mqh create mode 100644 ProgressBars/WndEvents.mqh create mode 100644 Retrace/Button.mqh create mode 100644 Retrace/Colors.mqh create mode 100644 Retrace/ComboBox_New.mqh create mode 100644 Retrace/Dialog.mqh create mode 100644 Retrace/FileSave.mqh create mode 100644 Retrace/Font.mqh create mode 100644 Retrace/History copy.mqh create mode 100644 Retrace/History.mqh create mode 100644 Retrace/License.mqh create mode 100644 Retrace/ListView_New.mqh create mode 100644 Retrace/Setting.mqh create mode 100644 Retrace/Translations/Arabic.mqh create mode 100644 Retrace/Translations/Chinese.mqh create mode 100644 Retrace/Translations/English.mqh create mode 100644 Retrace/Translations/Germain.mqh create mode 100644 Retrace/Translations/Iran.mqh create mode 100644 Retrace/Translations/Portuguese.mqh create mode 100644 Retrace/res/CheckBoxOff.bmp create mode 100644 Retrace/res/CheckBoxOn.bmp create mode 100644 Retrace/res/Close.bmp create mode 100644 Retrace/res/Close_Panel.bmp create mode 100644 Retrace/res/Close_PanelRED.bmp create mode 100644 Retrace/res/DateDropOff.bmp create mode 100644 Retrace/res/DateDropOn.bmp create mode 100644 Retrace/res/Down.bmp create mode 100644 Retrace/res/DownTransp.bmp create mode 100644 Retrace/res/Down_Panel.bmp create mode 100644 Retrace/res/DropOff.bmp create mode 100644 Retrace/res/DropOn.bmp create mode 100644 Retrace/res/Expand2.bmp create mode 100644 Retrace/res/Left.bmp create mode 100644 Retrace/res/LeftTransp.bmp create mode 100644 Retrace/res/MaximizableAppDialog.mqh create mode 100644 Retrace/res/Moon_Panel.bmp create mode 100644 Retrace/res/RadioButtonOff.bmp create mode 100644 Retrace/res/RadioButtonOn.bmp create mode 100644 Retrace/res/Restore.bmp create mode 100644 Retrace/res/Right.bmp create mode 100644 Retrace/res/RightTransp.bmp create mode 100644 Retrace/res/SpinDec.bmp create mode 100644 Retrace/res/SpinInc.bmp create mode 100644 Retrace/res/Sun_Panel.bmp create mode 100644 Retrace/res/ThumbHor.bmp create mode 100644 Retrace/res/ThumbVert.bmp create mode 100644 Retrace/res/Turn.bmp create mode 100644 Retrace/res/Up.bmp create mode 100644 Retrace/res/UpTransp.bmp create mode 100644 Retrace/res/Up_Panel.bmp create mode 100644 Retrace/res/size10.bmp create mode 100644 Retrace/res/size6.bmp diff --git a/OLAP/CSVcube.mqh b/OLAP/CSVcube.mqh new file mode 100644 index 0000000000000000000000000000000000000000..e34891abd7a9f3bdb96a627d75eea65a253312d1 GIT binary patch literal 10376 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 ams8KlHJ-N5(sD*+?uOWdoL<^KaY&^X5c literal 0 HcmV?d00001 diff --git a/OLAP/GUI/OLAPGUI_Trades.mqh b/OLAP/GUI/OLAPGUI_Trades.mqh new file mode 100644 index 0000000000000000000000000000000000000000..c91d56c940b1fbdee1d0da1747888b21249de524 GIT binary patch literal 11600 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 literal 0 HcmV?d00001 diff --git a/OLAP/GroupReportInputs.mqh b/OLAP/GroupReportInputs.mqh new file mode 100644 index 0000000000000000000000000000000000000000..520108f88c2d8d2622e32fdd56d4081e25bef272 GIT binary patch literal 568 zcmah`%MOAt5S+7#|3LIE-hJGZcu#d$anKNp@2JIXQk(E JspBe7G@qg&TaW+% literal 0 HcmV?d00001 diff --git a/OLAP/HTMLcube.mqh b/OLAP/HTMLcube.mqh new file mode 100644 index 0000000000000000000000000000000000000000..b731550ea9f833d3c7fb48fb0529815f7dcaa253 GIT binary patch literal 4744 zcmd6qYi}Dx6o$`dB>ux~zyu^$lOzhNk><;Cat@ z?A`7zNz@3U)q2M}Gv~bL_MX|l|7uvnHtg$LaBbM9_6cYjc45hXcKvJ}+p}Fev4!<4 zwM`q^?{s;f%j#F)nRBO% zKOT?t&cQLWE%)*p(-rI;*gZxk;2biS+KAr;E2VkHc=%Cx4v;s%_7U|ZJO?)U${MeBza@qrDv?_^3&S}`MNbFgg>YH=#*jt{e z#S@;=lb2k?S<7K+Ejjif62vWWcg=AXcQ;FTuz^G|br0*Oj^%tMXKkNs6mt&o!NAd{ z_-wx94e`&A*#zznd*oYT5|6}=koD#^e(xenGN^}D$5Ql$Fp7N%w*rXq-#~rcm z4@T0cbsJoL##vp`P}HZlWqy)p-!LcLQQI?QK3{q+;*HNfou+Orx^qfIUr||OR?7z2 zUgwrPb?o~t^N@%0s@=AV6g!l2nF$fOq zsmqlvah9Ss1xW(J5TVq4q?1xYywtO`>df(~YxX^ldyZLWh*80hvUwBXSOx2NhdR@)?Df9Xqp8=AcqQO2_hkoP z9+EZx?#GyCHELB+?}AaMquRBt&Bs|ashTLqc1SKC*dubda|yn3zsN_~XaznLdSR~< zZJlmweut6lsg{+uUA!RdSq&ZXzs;?lpfi|sR7osGt@tKiajK97Qu7GcyJF6&)5dO) z=kPzT&`-pAQIb6PF85DwE@P+2aMk?OChPX$r#)iZLZ4Vs`5L}3)*N}6r9xBPO$J0l zCv|<@jLBH#-iJ&RI!@{suGd?x+GV%sqiZBy~sOH9Eb`{aYGmySqN6Y>n&punr*oITVJa@voOMdB`lt&h;sH!eQ zcCY;rI%D)mzBYtaSGg6M(buES62Y%JUx?ks_p%_IFtXJaCF-fK(9rektN4_4@5o}R zq0p1#SE_RU)b)u;ULaE^WpSSNL~L=tJfnKiS8p{FuK6ZnExyU~R+TUF*%hR`U*?>A t65}3tJA6sx&%RCKz2m2YC-AP$EBX#O;!-a@c3X5#Sx|xVE659o{sAwCbpZeX literal 0 HcmV?d00001 diff --git a/OLAP/OLAPCommon.mqh b/OLAP/OLAPCommon.mqh new file mode 100644 index 0000000000000000000000000000000000000000..1b7d589141babe45309bb0cffa7956e3f099603e GIT binary patch literal 94238 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

_MM(Z7$QPy-9rlGy^!$2kJH==tBgp}C|( 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 literal 0 HcmV?d00001 diff --git a/OLAP/OLAPQuotes.mqh b/OLAP/OLAPQuotes.mqh new file mode 100644 index 0000000000000000000000000000000000000000..3957a0dc1de943ebb88425b5c4dafe6dec41a6cb GIT binary patch literal 16312 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 literal 0 HcmV?d00001 diff --git a/OLAP/OLAPTrades.mqh b/OLAP/OLAPTrades.mqh new file mode 100644 index 0000000000000000000000000000000000000000..3a180e2026eb054239dc60267e6f2d97b7de1d1f GIT binary patch literal 30332 zcmeHQZBHCW5}wZ|-GA6@q!`DsG0vS&a=4r@U>hAa4ohNLk%er)*a~mQf*r@nf4Q&s zC-3fgy0+-5p6=P1W#Nds0AktPZQA>H{#nt#$$b1Q`B>pF7p< zYOcBq`STNhzQWbVpy#;y2^5{+X9u6pPY-dPfQDgpFG%@)#h38ASN$2Ewm{=PzT2q| z@cR@aiFt_6`{$x(4e<8B_W|JbAn^l0+k-4laBVAm?m-L3z`lhML%cY47h?~r*Z6&c z@2DTW`UdwN1=_Yi<*RVd`Q<~K>nbB^Nx0YxRLnw?cY_|U7Cm2sw`th(`Q`H$SlZY4 zxjOXR1vPi4L{FEvbqtGn2d`rcp!d=HZ=FQ}E1#|>;PeTGM_3l@bj0PI!#EQ0H`YP}i&{|4R{ zswG_A#NX-nIVj83lj?g&X|sAzt%N(4YLM0g7UEb+#t~u;Dk*pXO1=k$8yQ+QarHT5 zwG5h5I!XC+P;@`&U^3{Dm!9Ek6TGhBC$E!~=7s7ZUgZ5DI1w3Jy7S);f;8Juoxi_C z`BPA`7I>jN7a*TCV0r?&R0n)#=3=d&F5SV|cv{&hEZdGRS{T;D#0dY*Fr8*S3D7N>2yMr8ia%_U-QHTcXHEeId74@U|1pDOJ6whPW0_Tkl zXP^5)_oqQKicu+;9OnT3B=f1|PvtorW$(0$8DlX`8u|{DF9fR?7>OxFTH#Ar<_WB~ zEks6b&UB0-8awzdRz{EA8`*0e;&0VA!J6nPGG6i+`T+9)R$?0=TcyuPUc<5Z_}x5L z$2cD6nK&y(Tdnhu#&Lf?Gl=_v`#KEaN$R+_;EDb(GY_k#<1nqsK2WU|u?;fISjxuI{%)2&2jG)z!-^X|- zuOcs2>eR4AQX7YI5Eo&6YhiBA!4!zhl@9}D?O>MTzU4iQ{yEwrx18OmSK-sbiQICI z;~W`hHmeWIXB}Fd&t_<)`PxzzXYKJ;OC99w)xx6=PO?^E=YF5zMXRtG0OP}ci0_P5 zImvs7w7K;lea?qpjqJ=r)Q$!%uN}-aXjI^lOVL0I^DxW{jHfv&7a_IBc&)&G2l#Ds z4239NAZkC?Fey;`6NBB zhe*!5b^zUvoClOxUzTZ;$~w+97W%z2KBIQA-;U+v*Y&vLY2F4^5`kD})nzsr)t1sprJ1Kpbu_6wz04-1 zjj@s0lB`pR)K;Ny=GA-9ca)k~COsxvK5a3MXtstpj=sw7gJj?GSENCs!?5}hUE~+Q zK=1lk^+%a;KX`9{AF1p5ZjcT?MWT%P!1jZuirtx#^LJ2mh zQaF}>b9Up}A-(Su-pBhtII8QGEwhfFFK%B#G$J-j3WS=(O> zah-GZd1ka}#<|Pm-D)>Ko0p;$SKg&ld>OH-jIC>=iuLrTI7M$CAE(CoQq;`~VvIzJ z8Tb+-&iHIKwYqu)V*YRnFP=055jr$uE9aUQ>vd5|DtO=cwZa5UH#Da zee7D{C%!KXdqD6@EMMq~EK@*?R9b;>~N!NP8h`C&xGO zBfaEd$mi!ULL-TOZ+n0?cWYnAUY%K=QBJcoYP*kqS&SBaT%qp!XENz0R#5LEv7f&W zD9jW2c^<#hZp$)kEUjafFrKTbG188YQM`vZHZW_jkCWapkG^pGj@@_)@^$AyuoPQI zE<!G5gkc;z9hPmwat;p`-8r%W+Y%e$bPT`aAu zxc}h;t}_nJWug0uMPrkv;`bhj=Eq7#<|fS-Roc97E@((%86%g(uRdhi!%l43Cqk)F z|GT(qBOt%;!&7B6?<58rt@Gn=ggbINusK;8@iv0)NxQE$(=`kGEn$2-^Hhn|jDTG6 zU>)z*AV_)aXZ?_=;^!TAocVpX!1L4w9%oNVmaz7LU8=od;wK)G`XXcKDefjO$BlQa zV3cT`-gT7FeaCUpod>IN;X_yF$eD*{S#yR=`wzC62uyCV=>D(~H7-qQt#-DkiZR_Pv%h-Gn<^~L^gbdid}&xh?ngCGhUXcw^2A}`Q4!9{5S3niPBv~ zESG&|?Y*{K-FyBiP3>ruxX#h(;itPsINL}1Qyh{DrctwPj7Txty(P>sBHoSB96`RA zlQM&}t9_FB+&HVtZ-zWkvQrDEWP2qaOD$CRwNa6C?rX?>Da_KcN7rJsV@W-AX5;WC zqMPzfn`kS$(k_}PvqezECmD2>W(Ly5F6`c#2z4;pO_PHp8Me-u<-H9)Bd~detglP& zA+F&08QYJya~NftW*(Z;GJj;1z?^`q^|YWqUd{Im5lLRx?irsK#9TUZ?Jkvux3v4%ZM76QR$TNZ*`M$b*iW#>h&zE!FyC?|?hrrL zIpvcseor;kE6xuB}Ja=Sro5QGqOj7da+#itkw4DqAYSg zL#QIR2>Y|3b!KR*c#(I07k6{$$hrmyP3@YW^(7bv&PoIeZL7{b@5@Vo-)P2v1j%!q zk+K+oKDFUhP)i@S@*x+ji}T~6^_FBLcxhiVusy*Wd!1q%GYeR?nt%^ObQ^My<^%!j`?_WwwJ&NaitIRQRmhC{P zvhq#+KxXnEg4b|Gr_R69+N62K#IbGtK=1MW6urv#@;55yXwzkDvR)OfNoMwGSdx{l zbU`e}PxfLpntr|vd&ygoSdgE~&mVE+=}SJ*dES_7DQogP;e-8Dej?^cqprtD4#)%7 zs><=FIreDes7s?c;^yWcPhFElXk!{5KE+|~Fj74<$D+KSOfL?54XS-jFAiJy5{GSM zZsz@yyW$PJ>gr(&E#8F5qV9D2Gjer6KO3W<^T#cAK%Kc z?dd3!X3w^dCu7*>y@tF;I>qdrOZ~{&M^+DfEy8iEiC8&Gz8m9IiNCz`{QRjENnJwq zyZxP3KK^chr{+uLntTI%$$2#Efp_xB9ADOH{k5)Ldaoz1AE8s}W7H~9Vk>)JIj8+6 zu2Eea#iX&cvXD~JMkj>F8YZqusc((jUumW0rAnA(OW~Oq>O*zU%v(;KN~ya@D^Ja- z)9Sl6$`jvZjjG8ih)p6x9M2O!nAh->5}wv%zmaDztT&`QGJ1H4l)cW6^H6^@cy;xO z)biC7Kq#M5;>`5&7Idm&DZ;2xS`4%EsNvt%9+>wC3H`%eX&Z)`98I zy7Dnj%ii00J{g|~lhX!L3DM`h{f-;$`I4L|-9uRS!F1n|j|QZVT4Y=uZ{xm0-u0;q z_6eiM=reDO$+@T8+CIk_*Ymx0DBpT)<5eG_tppz6JFa^yLmpfOWM8vgzG8Q=ST$>)=Ne#QH`NUaS9jlJyHl%d!BRccSa))LUSRw!;Ef(78FKzPwHRmX_{BSA-Cs_(^21qk+({)Vo#{y=q?ghbyV}NQOX0S|7b#@#Np`tJ+Wc5cTW+-1 zcl3FGdI+iOt{G1WWfafoxCVc>G9+!f`y+o+Nb?=}lR#3bdn{aAlPDHX`be=*AL%ZH zlC0B{IwCB3oO-H1^DLgnA){qvX|$ZWk|(Fv!)P!2ORSC4 z?vHStzRzBS?Yiim_jDX(661_m+Pg4g?j-wHMdIukNN-JIs`9PhQcA}dL)!d^rrwDk zsd}>X`@OVnB+#xRjQP2zfqZR10{6g&&Eoy2@i}v;8tD3@nw4ule<#JN8yT?%+BrK@ zA6{b28krOE>HS>J>HA4}d_F%^oso*PZcy7$Ngju1uD6l5#xCu7>I0wesSI+OQfqCZ zc6}7hDLd}ul1lXnuJQyy%B!pHq@(0D$exl?8fOfp@8j9buUGi~KAeEUs>AQ}il>J# zbB_MUUB9wpAfC|5Q)8cFFAaBp$*FWaxlm4WeH6|{k`qXugU>o$q#{onzY#v8)%o3X zEM><@eax^KJ9gG*c9*8jRh;6e+S}sqgx(3%hrY-k~d>)~<-#zRGgbQBUEi z;wxMyU@u0`MPEU-$29=Tm^*ZQc6$$_b6%`)^*wTEF}1lC>ztAE6Wy-<$1DR_S%uW;=@_)baZAafkW%d)&7H@AUkQldzAZmb3gf z`KvkG^Awgl&vl4x?v%SM-Zb*ZvpZH zxhF`T5?q9@#lG_N=BBQ-Vve6Qi)5vsr?2U0;_MFX25;r_0$S(SbHdzsfBIT_?kwkw zc3jk-^<<^M>@@#;RBAhepbHs&2p&9L<e`5!s`VdXrgzo~&1&8S}A=r^b+*-09l-+>Fn&Z7lLW z7o(lj?WwlPQM-u>yN9?ET?sMrzUn_>~kS0Wo@mRUZ;M%9&}Gz+(va+ zeh#cO?=)#3KIPJtW9BQ2Ia|mpy~j*u3-&1uJ)^uUP0VvNkI<9Mr$b%(L{(SHmLRR> zC+yo=1}$I?=QcAg*(U;13TX}6%Q!`EfM+Z+qnyLD)ACfLJxASoezU#kx#w*qzS z2YYz7fSI$UT2J|xCu=myJO-ugTED5;Ru?Hn%&g%!8+4&dA{ryn}b5*o& zPx!w`zQ2RbbJrj%@L%wW?~I7kkppLr_}>T~!n^9HV4Ocx?KJ3V@?Ai4~&XTh0G@pOAIgc@yhsust zS)Jng=Ue{N(@6r+OE16vgl7N_~eFRV$M;F(pbP5w#NGj~WR|1kQ)5st_0(P>pfyh0r#6puS|= z-3(p?*dU)H%UPko$ zSnCmioUyjM&&bG-)!V!=;?ldPynAU~{^mSWuEOXUa|aGv8S)v5ATePYdXrvOrd7|$Z< zvoyL*^&Yu8%@XY_G<6@}q$WeE_O;Vd&HKvfZTC(I_HB##d$w0{Jp<_{vrakArvjc^=-0`|jlR8n&Du4_2ychbQVO zVn=QbSP`#Qj+W3?yN|M_?6m0%9pbu%mE~JLhc)8wbiHkR3%_@6x&59@w_xV3eMfeF z;8N~=M^o>J`K128&D;#!U$f#vtg4PQdDZo)R{iYq5OY~kh^r%IdWey@s+juviSscz z`CaZSbPiB*`!K+y@(OYjCRY)tJpb8wCWmM()cUqc}7RL zWaMN@#M1j~XI*-xGfRv!&6A=qAHSdAX@}jn{18GZ)wp=pcZM}s7FS7Ht3Lj*2f~~( zWPryy1!$%`-?AGbt4h+Sc;#`em`+PNSDd=+OnN)beTbFs5;|{;I9Xi4&r4$9SBOVO z_A6>5&vJOA2&uEgI)7llz=}6+2eNFxmAIz${A_i3-v>1E2JAz+!5Q~mXER<^9v*T& z61(L4iSxO^x96i`r2RrYqCIAA+0R(mgsm;^TlA$}zL%Yyu4AN5dgaPU(fa=J*l4u} z+#?cObK~_VM4!X^bJikficy{aDJykuS5z0BrGENZ@^c3+e4NqC!1S_@#dy7kX*Uf%>r~>|Eqxou z8&&-d*P=70$g^j}tPw89w6IsFKp}?zH*Z3wgO9UTOWDg{Z=8=+=2S<-A$8mq+PY3Z zQvyKDTJyC2!v4O+77Yo*v7Xckn(@{lfd`Q z@$t;;%x;{tlt{>0dv|B%T)%Uf@!x+vm8Y^Lj~~EiOFov5Ak9;`k>Ue=UP@ECGL}7D zW87cM6SAj?>K(!snA zKI8Ww4|z@@!$fwSl`n-K)weI7;;sc5FEG}T0lsILNzN18U)0L;knm#|Dj@Mpu3)zb zv>xNWh2H|#5Z@!`jhXZ@ix%el4zwKMj+R#}6tK^^vj(XQ@pcOD4dA~5zY~1ZQcZaS zIvr^{yu{oLUzF;1H%?@?L2I^HRmdC^`grch=gS#N#dwkH)ba2$jB-OZ;m?ptLk{Fi zIg-~v(VqN(aU#moXvndAhw&qf6p-relB=glBn+J8QfWyo9FJw4WaOD=WZ=A2xRz1h?eyp%1h+O%N}kc9~JTf*9l~1z9QmJVT%J?hTBGfsLeorYFkHpXC>N1 zhqno7cI6CyP}$a;blZ5ljt}K0ReMYAV|(i=TADLsx*hnOdCoX6u8*PR1>%z^i1jp% z=`2dTxs0R~0VxXVq*4@^=hC%4niWBlKr4?R;({pd!XpLrF@&emhaQX3v<`cCy<$|e zLY%u8VPghAcp$Ls}%bDKO=~Em5S^>ifqif$T{6)#wd9hBMLo?Pk{chrpUcA7EHG#F0 z6_S;2>U_h>$l3Hl3uBx!z&k!OhJ0<+YTK3H@K&p33%WJIjr{f<7o~2wmvVW`jTYI5 zc;1byX|ih#kNFgkoY|L1ZG%r<#yK=#eV;jdKgv*7JujU`tO437FuKlgwQ$i>%rV!{ zzX`4ycWwMmoYkh7MeAw@!JcZc;Md2R5FM%y(a-Kr?brv;OULyLa%xZ5#;@8?>s1$X zX#XK(q9h$qXyJQ+dva4Bnaw#Gqtdz{wO|LxpF%R$L)D0~oT6rhviiKDI5B+0RnvM4 z#>gD;Sgzxzpgc!*w!9xAGepVP4tv_Qja}yxqT=09^boWUE$flb_~s{$YTD5{h;m&^ z<2$tCkwb>|_v{}3zcyS$g^%rM2sE45ThegtYgRdDv4didPjtmuE0^&K`2-Qmd>dy% z&Hjdt&|fjlI1|RZ8LgS=UWQea`6AxU#F@eL3@Q40Z*tLQHq%?g_9!{M!re$nCC0w` zARNzeA${AmShvB5QJl|l*LHcQ+V0w!`2A7HF_ws$=JZhttx_Mv+1?(noJ?8=*=N{( zlR2?0Zyt@ITz^zpJe-rtzM3@K%Y1Cnz+df<_EF1NeR|+ObX85OlIHy~e%T$paDCrP z`Bo0mW1q@b@(R1u1Njk8d)TcWq6gqS)-CR+NiT0@jRuoR(P2-a-g74zt3GQpD=4c! z>BiNm3N3LA+}Db$`LtgC5NjRm@2{ajHI8qS`=NP|x`!HC|Cf)ZG#hw7vrA>9=lx4R z6J1wH|6vHA6f@T;-Dbn89f+q8?>$(lx$p5ZaHqnP*KVl`qcu{j@vYAl+a(MSE;+{nF;~*O&RcrL5CckF2 zxEcU2%#U}Er#0BMY-K&E;Xf(d`yXP)_qgwaej9!WPxwL<@l@vtaKM>7lfQce5h=aO zoE*~5R*qv*xz^YLwY{Uec;3J!+(>57_D`FsEgK|AHuV*)jBdgk@F{U` zIX=wHow;}KuAK;})oQ(W@0~gCZ*ykW|M~Zga3fp|*WQEI)$r@^D^YVJ{1_&`*y}H0 z8t#X$!cKSyld!7KZGAr#HT%NJ^&~tLrkDD*CwwPy>@(ec8J_CzOwYE%?z_9+ zYVJ{_&9!!-Q5T`FMP-DRjEjRv`Hk>9z0l+PMbB^F8+v{(`FyJP#mHxoIB_fuy_S{Z zb67iCx*k0augmFqpW-1g@i)=(cjPCpGs;UMa>i2da=HaeG(S zWD5L!qEDjNww@BXJ|3KT5TOv&EMi!6AD#nFvc?PLjfp5Yl~kVy&cPg9%z#?g$1s*% zae)4y%e3ZKx8~sKpZUq$nYkQ~BA3W;KF0RE#qgnv*}@c(jrJFuXF2sy^DM7nN%ORk zb9ka0y)ApbT-a8!bdP}K>Y1vFFT;BHLiNmAcpM&tzbQ`K)%Q)|G&_D3ErYy%Rjb*0%N6rPqXgpwJvB|`s;pKT1+ec zkHxSR{voS*7`?rOnzBM2zo~>gEAUCqI?(H$;+o zXpB{NRC%lkXE7q|3&M*C7mGdA)wIYVKNa7g=BKkP!*yN|w3uHPWK`%%gyHEa);&gC`xKC({;EthJCw`Y{rs)~}&>E@(p_>d`qM@*In{ zwwJESwpSIihNaNLo-)mO@NdYwpkZ?f3Owgn7Bec^TzWnDMXZE}d9CG~=fEK>dF8q& z4(BD$pKZC0iSfp7Ui}W!)6%bJ=;f*K8hJ6?Wk%2QGu<^RDXQNS#pM^WYO-g__4(+x zRW_&Qn<+mYYbM>oZWTCDKa@<y+KBbxMbmWWoHQM&YIrGm(H$d3C239Mc~(tQ z5fNjSm1WA=tPN+Xcha3Z=aA^?S&jZWQocNWWkw=zj@L2ymu$j5;p2CFEv9A5x=ALs z)@B6*Po-VvEAToNQQJ`A-~-eOU6@`Ev|!Tp`bw`FYHRe}m={(RG3h;(bIc?1wIjB* z%zndNA*a0>^H3GDeK*G9KN4?-ZCr@Smo^rVt22BIyv7%xl?!p zHo^`f`x&Pl?(6-RdhYj%1$*&rlFK8LTNFO|PmL;N>rdG~WrvqMTaGAKUgbVVIWouE zqB@s)d++9s>Rx1VCH`goLob+};5Mdta(^A8E>YO_mQzgkUWmt}6Y1CGZ{F65%{hlI zIVv9Zv!NB;Gdmymw)n=nCTW_TcJ`0B!@QD9#wN|qADhc-{^(MZmUp{x3JP*w_->Kl zgLmDeJ_**bW<2zoHq!<$>t_>1wwq_K)LX%Bo=UQ>Bw<_4K>0**!>bYB7CVw zW%boWx*#u@4{^$c(ctWIOmr^ z0Fo}Lx05NQR*c3J^eR=!Gg1@ElcqHFjby1Q;P8XDM)`4}$ z`FJ-ecd16kY297h0#vo_fhXn{@I zvTeR$+sRkjw*9_)ufpqc)T)@|vP+FX*yw zek-nZ^;VAQgOuAO5=4ewNcoty{>RCTQF*V)rlDjy$LcEkNHpZ27W@1Lhi0&gEii*a-pk%Q&&GQZm|6)anGTIMKLfkX~lSJDfj zcfQw)<9|ET=ehTn$j|K>u=GD$%Ovme+9w}1Tqj^t!}XP0ec6e{OMNY7agtaxObPy8 z$I_hE`JOxE15PQQzg%?#wlXr0%LL4;<+WIq1B{=e(rMGSY_-#dwph&qjBYMk96~Mc zMJtyU9m~L|Darj{yajb-l4pNAz1sEE@vv(eTXm0}=<3qZ9?6dB^7M3ZcT7M-b@U(VCoX-4n(F&`-a&oBNd7dY+ zi_1>Kawj(pOKiM`|DS!xO7t7My|#JUcI&7$@&D{&vgum!GTEmKBaaK`$q!?)kFWaZ zyt88C^gmIUj{42swTIhY^JSr$%lQ%>AEj#OxgB^W>T;Hk z8JCBKAdK%Jp!r3!5Oc<^^%*;ywfdj-Kk18iwq9ok>NuWSP5YB{;eBPbct@mfjh=K} z_TTNd9k*gPhF-nzj?tar4D@;X@*gyEYJ0D!Pg3Y*ehrZL%R5X%F#C1Ze$u|%!q8s1 zx4HIc$kU0=+_5ubzms~b@3|ecF!jr&p9bF(>F*2lLq!+4q;1!r^zZ(d(3W6*x4zTm zo$4Z;ZYA=!I)5dc90oCLKjs}E(evUr%cVqWDHxx2O07R`b=MQED!WZt|1W{=$`Xc8 z4$h~(T#x~-q? z{!@GOM>!E#o+~c*sp-3O>SCTP4apSgEvF4;0y+5xXVB~vZK?6`{F9H^Eq02JW1oIk zd*tba0==2^8#L?WbLIdaEBnc{SC#boxrb$`-4s4(;XDBAbo(vZ1Ks`M%*Q#ILtY(A zUmi)__t`6TN=r?nfttr!FZl}b(OGB9pi|?tPGpoCt0DTygO=pV*vAQg)~Qr-(1y;x zunTM_LN89Q@LQk%FrJ2}bL%rbekqHhZ?LO#+8*<5fB&NFZ>rPTt2#f!|4gvo!r8BO W9%uj2VoT4y(x@$YX-nFER{Xyy4KB<8 literal 0 HcmV?d00001 diff --git a/OLAP/TSTcube.mqh b/OLAP/TSTcube.mqh new file mode 100644 index 0000000000000000000000000000000000000000..98b8677256409c7ca59baf07786933acce319bad GIT binary patch literal 7004 zcmdU!ZBHXr6vxkN6Td^Pi76rvYE~1(HEgN62?~Mwf^0UV3xy?8ihW>3SU?V1aPI59^B{S)Mej@+pNn3_HuP-i_m!kM6;IwP zwj)km{c4L}Kde2`XxEPQcc8hJ9gRodYVSpmEqbl5RgdAXd2NK3T#K_H`HFp|3qL+B zdA@uy@_a4(Jk$L+_L&DKdh*bvqMS@4+VRqI$T%`DmFFqpA(;4ai2Ot4$xvB94pnVe z&kN-T@mC*V*9&C{IU6yo8W60wdtF)eyH>UW;`Nl@d!yVUikrIoqDt=9wdPPb)t+fh z8u&R~vo;=Ori?16+7;5E2`d~y z+GE-k`$RKGLSDGUILf%i5wg1@Nh|iP?wWSAf^FjXLZGs&zrOB3e2Fw)RZ(q)yU*>( zlBcr$z`n_Gb?vAL;Gc6swq@xYM-QY8n0H>X7adu5u9^Z`It3yH`!+{tSR!j84@-;u8LE|p6f<(-WPQhITd|43x}?3 zI1s1XJm|n?;c+Ryfdl!Ngz6iOw?)^zoUSWMN?cJ}Pqo@Dmc?5fFYbyF7@`WVln+k3MW#ogYQpfRzK%A22gWv@&8-dF5&WF735?oG$bcSh=`0lhq9 zQVM1BMd|zMvRcaBbSD{$#w}T|T_SUeNuUE=aYZ_i&n;QOabihhcO&=m81wq}N*;f$ ztRiQ;ySvm|%I$slm5v}QXy(|Q$C~Kz3}diKMBRq{Y`>_NJ&*(q^?h4QBkMr%-4oqx7uF<_ij)uRg}Cl(4wOn!D`J&*kJBjZNy05%kw%JXP=RXd3-USd z`TN;1V&7d>#IjBG0BD&aWa_u;oL`Beyze{)hKi_|Q&s7e*MeP+Y8jWJ-7;wo?4=|F z+w#;GM-_w`RmOvgfsNNYUTV|kH7aLe-amTbRFRk2*Ufi{(2^G9`kzARNZ6kq@Hb8`(oF*Aw&n)pw%ns z;$k;CdC$6h=lrh6vFeoxn$+~Rc;tJ%y%1qPC^sA0-3Vv*hBBcpe5u=y0a-o`QuSuQ zMz>j-HJ6Hadg@`wZ!ov3i^@T@q_5eOROEhN9DBN2vSKa7QCH^+Y(XyuGNyDh4aq64 zW6`D0At%VdQ{5mMy^H@^*E8b*(*GfZx3@BIUc%h%se2n_AT^IZ1wI^Egc}hm9X1Y1%t^{6s0@({nHWiqD7| z^U2Q_29L3dGM0$oE6O`P%lvY`*l-`*u3%B_qBg~mJSq_dLrIypj_-=vPd?54nbT}C zdXRIG8nPB+*yFbz&aa31nzo~i^K2uQXSWq-?cK(X@Ea5dd3Hlzv#(zp>TzBQeOO0U z(1(*Rv&Y#qOQG9jRHBdO+gSd*o3HeaT$~N4Ec0O0v=dFF>L({oz;Mk@Hk|fS|CIZP z(OD}6sFUd%`Nz1u%?rx^w+JZHVOFg2>Jic5?m9{S#CW;JD9S`8}do#J;pa)7RnUSkltw5pM@Q4-JI>>E3^p5BD-10B8j>c{IsBEQ%@ z^aElPtzNWW-u}~SOxpFPc9~pD)`jK`A^5hQo5J + 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 0000000000000000000000000000000000000000..c31ff172f677e722307ee1b8d0f78313b3626252 GIT binary patch literal 19282 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 +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +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 0000000000000000000000000000000000000000..a3257826b28aeae2b4d4570c6f1c0beb33bd5976 GIT binary patch literal 6094 zcmd6rQBM;=6ov1ziT`26ml71v#FrX17Ev*QVuAQbpcJUIfZG-%!e3XvGuzF~c6Xr& zn9XL%?Ci{)yZ4@R?k#_QFW7?3+4BlqbN1LC;mv|wTJ&G8RcqJ@*O9H;jvZUadNyx; z`(cNie|ZOgmauwi7ZzLB4zM=F-b-7w7xv1YF<#}YA!mNI5i5s04Vc|vywB4)Z(`;m zlbsk#^NjD}&u!u9n={=jgm;L?$T4sk1Z<%t+vwOP<85?o3l;gy zXoH#e+{+G=zuey>T7FH_K5|Kq$}V9e!pfnG`)(#9U8h+iyb z%llI$4b1bePOq7tt-;2KH+hcNz<0yGxVpDRb=u^4ZLI!brBinwJ4D2+xgaAQYEy&N zE&BiyT3BdNC0AhZGBYXClMFOKLYtoL02?RZN!e3B-g8!Kt{02#8;IzFjt(~Zyg6c& zwIfBka{5zM=CtrxDiZUJ;=*Ky5Ms8NPvyOUG7w=`3=%s--lp4+^buiNew_)Ea z^?1v@cq?z$G9AD)UsY{xZ@Acs)!FXd_Y`3kA7Wfh2KkQcW{ynDHXqaEmrq!W{CQHq zv^R_F4Vm%#^sJdsfu(rwxQDP}L^hL}s2-=s&Q1oe{uCisS(mlqwF$p(Vt4orW&BMr zcHjIJyTe!&sZQRz#K-df*T*_rr9aJWlx%1Uu|XCbiHr{ z&d#`{-RgOz-TSUXQWvd$SO33hGmb#)qzWm&`A#{E=yl_2DvSRWR;(=L*u0z0T-jeR CJKAah literal 0 HcmV?d00001 diff --git a/Panel/ElChart.mqh b/Panel/ElChart.mqh new file mode 100644 index 0000000000000000000000000000000000000000..558ab7b7c938eefbb6523e3a16d7621f7f0cc9c3 GIT binary patch literal 32658 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 VqQF009(z6g)K?VP-Ws!D;QyaZyK(>k literal 0 HcmV?d00001 diff --git a/Panel/Events/Event.mqh b/Panel/Events/Event.mqh new file mode 100644 index 0000000000000000000000000000000000000000..86a042bd6fbc0db8a5a5ef1b051530955c596591 GIT binary patch literal 3404 zcmd6o-A@xi6vgkeiT}d}Umyro6JJ10U|T<-MOsaKYT8mhw6wMKLn8d^>hH{S+1XlX z3&xPm?#|B6+`KXc1DgR@s-q{->JU?m+68P?Gu`43xQ>1mbcTub{nJB_< z3GFE}TQEDxZREORL=HS_Y1XBW11_PeaqC*`T${&rk$X7f3T zG1Nh-Vy}Q{7{y!{Uo~{$JA$zKJ|(`hn#iJyh)3$zDVg9uV#e!Uxl+uxi(v=0rR=l{ z7l|Q3qqw|Y|8+!{w&@}hs%(edc0NzwGwcCk=-iz~;v?OqPA-g6NsP+Ep5eQxG%ikS zSZHz@hkV}DkEOIKI}(f4D+HTYta?sUuUVA7y5u$K8KL(O?J~%3#xf1Z%9ul+V<}CY zMVF8#oirQ62^E#%Pt~E3k0w#M?CFI3!Jll`NGyl>5vyH%)}8hn3-O%tR~hGc*^=0< z*GcTUmd~p15$dohPm`#X4fWXc{8ne1uBtFM8^jWR-!@lbC_LYSmwF`edNz`k#8{Bp=gbou#}mc5yK+TSF8gWvw`DVU*%LL3L9_rIGys)P&s0 literal 0 HcmV?d00001 diff --git a/Panel/Events/EventChart.mqh b/Panel/Events/EventChart.mqh new file mode 100644 index 0000000000000000000000000000000000000000..2c5889735ad9d2a8fa9a5bc5f1065dd95497d8d4 GIT binary patch literal 3268 zcmd5;Yikoh6g{5{{)eGLNX6>+iXUWKw9u-UD)^~vv)eY3rjMkGNdLNe?o5VzXLdIa zLqV1{`#5vwzRtPx=l4^LFu@RG+@nGbhix3-JMSi#;RUX6i%Y(Hf-SuCSJ$1`C^6;b zP#7Bp*O$1XHHSU^-EgNfVn^IHMT+HLey1DaNA#lPs+z0hi}ROwE0*-S!YQ#8UK!LF z*Th|9s4@2zPfA8*(G}6bCy8G!u~~JXr`%t>Q~QFRHqhNMv}dQ!oV~|q9MjqXzWApT z-k;zrKJv*i6R|F*^x-FWtnr-hhdx^I%Xz=TZ`JswS?MwVnv2{y7^?ZMY6{-J&6<0`KHv3mQ{TVA!uuJNB z2kRH*R{y`O)x*4IIoBNqjArK9UHYCY*+b(@7uq{}j|^`A@~=IwdZ0S6{H~iPo7>Yq z&AGL??X;_NK5lM5LZA?x4J^$wqWuiulw6W{SO&M=t`GH1eM9O0Z#H4%=wbo&!k#=eO@`#)LvQFfdS&tLF-Cb@q`%q{4apY@t6Pr literal 0 HcmV?d00001 diff --git a/Panel/Events/EventChartEndEdit.mqh b/Panel/Events/EventChartEndEdit.mqh new file mode 100644 index 0000000000000000000000000000000000000000..f26ed74f58082ff7b57c1fa8dc29b07560ae2c82 GIT binary patch literal 956 zcma))K~KU!5QX2_#Q(6-3taS$@nEotUNAAntEsj^)wT%5i|Joizu85yZA8eXWtq;r zH}l?ne;un(r6;{RZ zRu}WdNc(g=V78dA&o%6@b#rfgUpZ4Ynyh;pFjGzUnSLwVH9}u$Q>JF7fVuK0HIsL} z*k^_j`t6gqd)DAzj5Wa9d!C8zaA2$}UFg=|Ep|yP;eAbH=sOSY1}FdW&gmRi`zi-V z+urO!F$Z6c!Yi~fwH)^u5x3a~!+Vb6wzal~PTroXPf*)2M|5otC}rZYS9 z_PsY>pXXR0#{^51n8L!~3>~~P%CW-*R(Qjlxl^3r(w#$*%*e3iF-X;nl>HetoHoQ5 zFRU$zIl(LMwfU`yJg#$LryzYe`FMBbs;2D~7&WbH4H{QdRsLl(b*vZ0vo6(9sCxyfYoJ#>Qh!>4r-5pu zv10Z0fLemyo_4gWeQgmpsg+RkN+U88WcESf9a>8O{nSF zvq+&y=UoY)ugiyNu*9=U{@H*$hA^UkG5Z)pYKV)c;n?05SIeD|V;%DyL4XfJe3m~4 z$NJ*;PA^oAf{#N-y0hLm)P=fwBKFzm!na3rhGMp(6TOie=5jM-bK~4EuNNazv4cB} zKN~rX7Fs>)(xJUA9^WI_y5#pETFy2%dtz(kb3D6}_2g&msy0zG`uUtHEH^yoy4I~u T)gsQ`ZJqJQL>=A*!?cmgMEf?FTo~5pz8{F`(50XO1Z9m18r919eNv}H%f3^q4lF^$ zkJ8a}Fv31GKN^qdHd42s=K-WLwhl9rXuktvPug)Ewphbxb`gVJ`3+}@d^?W+I^p~O z;zx&Dd*=A4PWB<*_uz5zX$O8)R!_iY2{_;a(W2PmQ$KbXUmV$c<8^XKA4uN=CVOaW zpC*t?-X0lzCI&y`_V9NC9FcP_Oq@I$OH`(3r1lWMu~harK(+{FxhqN?pzjm3R+;+j zHF`S5sN9>`Gqz6(*cj5&l=8HMv-=*@ipDLV5aEyQgiJ3uV)P1Zbvoynn&?Z{{3>pgH^FXDzO z(wE@7H^83H4%FXr|7<4mECORai?09jq=g>-m@-*@R&Y8z1>1*NVG*+djbHkepHEWllZ%Drj{84-64WtQc5-^hNQ+vxS`2%=dlt-12m^KCv~$OT6(4a++Wi zW-aP8gR5^a>uce-W>9b_TR0K}9Pj6t)jq*7j3~cSSw!rpEH~RAA8dOZ&>Z8ZOb#oy zn@DO&164!A=pJ&;OyrYnuYRqRz$OXi3al*75fQ%kvN@UK{lZvElKGp=VHn`*AOO7wG;+SlQh`E7uTjw`B*rm_n2)j8H)mr(7oS`8~L zm1Ntt$FuQpj-_uYu6aI1xLTy>e?585VmC&(V=?)Ft=qvaqT8v_5&LU{@n~!>KhM!{1%l(ku4dZ@|`!=E6-n2$2p$V?` z+n102p);1-vbO0 zJ-P?uSN1-uDW55;=yz1Brl#Qzhhxy9`NIO%_G32SKAGQp{@y|O4tGSuDr$=1eC*o0 z^~A89J;d|eIH%e79CjRnr=GVy&Oc6`=eL4a+JBcSZ=WTE3`-^S!+ zJ3n)6o4gb5tzVbJ=F-{5CaTO0%=&jR=h(pS1&&=@bH%La3!N!bl_AmpX1`8f_=MkI Xg|(KOua#w}xWe&gb*{FmCp!KGt%k9f literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..0757682bf34a9e7cb71c8bf3bf18a68f0cf65b90 GIT binary patch literal 2168 zcmdUv-%G+!6vw~MLI1deulX75IPAGx6s;@ySl>P z1@>jSF!A-FGb?9x3T~z*WU`nkF@qSxR6IpuqLQ;AyJn_1^z4LbGqV==NT$nU2K&4N zG!mO-8vheDb#A!B6s +#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 0000000000000000000000000000000000000000..d94f42bbc6e6ea8aaa1046d9679424277bdb833a GIT binary patch literal 94624 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 literal 0 HcmV?d00001 diff --git a/ProgressBars/WndEvents.mqh b/ProgressBars/WndEvents.mqh new file mode 100644 index 0000000000000000000000000000000000000000..938d75f222adee92edf5498908e603476574370d GIT binary patch literal 24646 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 +#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}tmYmvAs32IlRE5XvOf51)E-{CU5ECdAuiPlg9p>0}3OqwqO zb_}@EMX9t{#Y#=Vr0HZJ3CW~$`o6cFqOEmO$avw&$=tb|=iGDeOx~Rs^r$h8-%;QL zm%)Jg=kZ*?`zx0Y!L-xBN>AV~_%SyO27p`R8WK-|X>cDr01pA5#{laZ0j|{G^?L7^ zW?S0rwsgB)u`EkbEEY}Qbzc(RTSqlqb)yFQ8;yqKayiN8^NK>DAn|xy48xGofIkE8 zO~A7l0(~9uPuhOdG?kw{h(sc)53Io-2)u#x2DsQ)Ig%avjX(C!K7_+zRYNoyl~SqH z#nO9j`MJkzHmmLc-Mj~k>;uoD)9LKP&HH$2|G{8TVzHPc5{YB@%z3PL9NfQQ)Q`{J zz5~BU+|4un6wt>yHBD2I&yM1w1@zbJy7KcIpx2J}efZb@Z4aHPR7&;2p6eyjuj{%x ze|`feVLk9$$aUK(UnmsndEa&}`fIhCl*>Pbk-gx3;5X51Hl@{S_3XEEo+lPxNA|VM zqL7u$0+^R~WErIAM9VJ9`yAfAona69K9*)5|Jq*vAgP&0XR@_clJwlOy}rwlaOu_4 zs$Sj{QvIu&g8hC`oMmXnrK|Kl&7Y`Ee7 Hzc~*8n19Zv literal 0 HcmV?d00001 diff --git a/Retrace/res/Down.bmp b/Retrace/res/Down.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5dd180c423f190d9c70582381187e978e6f57bab GIT binary patch literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@883km8KzDaH@%k1lSg>{LRv<}? m7ND{{d-fbYd>BX))Y8(@0#vgc27qj!2r;&ds)2+60|Nkq^0+4e literal 0 HcmV?d00001 diff --git a/Retrace/res/DownTransp.bmp b/Retrace/res/DownTransp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ab50187d160e2cbabb695f09a5ece3c04cd28448 GIT binary patch literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N(}lC=(;IR tK{Tmmfb{Iyv*-We!-v5%DQ2{^w1DkgzI^$A7zXJFiIeJ%QT4PA0RRAQFhc+U literal 0 HcmV?d00001 diff --git a/Retrace/res/Down_Panel.bmp b/Retrace/res/Down_Panel.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5910ae01c8e19c8881c47b54d425db9100454bf4 GIT binary patch literal 1080 zcmbu8$qK?S6h&hd72Jr!z95dEOVOpeQWV`dfWu1v{}(*BH4sW`3B7Qdw(s4%B)qH- zi;9Uf=Q)DrkCF*_GbSM3YQ#i8;zyg|1UIuz@lJu!0wK z!79x^CisDgO>#!H)Z2;a{N4R8`Bn|p&yxB@`%$i2Uvu}M4tc7P5Q03mS2dTfZ2hAB XQ?!4J-XERm9@K|P?D@E3;{JXC<&`4@ literal 0 HcmV?d00001 diff --git a/Retrace/res/DropOff.bmp b/Retrace/res/DropOff.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ab50187d160e2cbabb695f09a5ece3c04cd28448 GIT binary patch literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N(}lC=(;IR tK{Tmmfb{Iyv*-We!-v5%DQ2{^w1DkgzI^$A7zXJFiIeJ%QT4PA0RRAQFhc+U literal 0 HcmV?d00001 diff --git a/Retrace/res/DropOn.bmp b/Retrace/res/DropOn.bmp new file mode 100644 index 0000000000000000000000000000000000000000..11b45f1e2a654eea69990f30f3aa0a1d6944a9f9 GIT binary patch literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N({;nXlZHrzhJ?F|I3#zhhq>Q yBu=b@LF)JH+4KMK;lp4W#3xoSOdUwi)~#E?Zh?uBN_Tg6lWZ@kc8sd0Bm@9)Krll9 literal 0 HcmV?d00001 diff --git a/Retrace/res/Expand2.bmp b/Retrace/res/Expand2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..40da9f2f3a3fc305b8aa763912f87f56dfb1290f GIT binary patch literal 1078 zcmZ?rHDh4_12Z700mK4O%*dbsWB~zCUWgllAp*mT?C$RVKWWmW{~#KM(fJ^8T)qaW z#U%$5$EP2k96j_C<9>W<7A#mmk^k|TO|1Xdty}jWAI4_~vObVsK>X#)m%}lLkI#=F Wc~BgJXplX~dSPsQ_QU)*lxP4tuasy2 literal 0 HcmV?d00001 diff --git a/Retrace/res/Left.bmp b/Retrace/res/Left.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1de38acff966cb748ed6f408d37c4a499405278e GIT binary patch literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@88NQ&UrGXe`^C4~^$^8&5B!v$#J{^i`7#IMbySOI+ literal 0 HcmV?d00001 diff --git a/Retrace/res/LeftTransp.bmp b/Retrace/res/LeftTransp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..dc8ed846c172b41f2d1891d102a74b46014f0529 GIT binary patch literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$O3)<)T3TBElWWm}1q=RzFgf}` z`u6PE^MCpB>FBo08cG2 ALjV8( literal 0 HcmV?d00001 diff --git a/Retrace/res/MaximizableAppDialog.mqh b/Retrace/res/MaximizableAppDialog.mqh new file mode 100644 index 0000000..3e87410 --- /dev/null +++ b/Retrace/res/MaximizableAppDialog.mqh @@ -0,0 +1,340 @@ +//+------------------------------------------------------------------+ +//| MaximizableAppDialog.mqh | +//| Copyright (c) 2019, Marketeer | +//| https://www.mql5.com/en/users/marketeer | +//+------------------------------------------------------------------+ + +// #include +// #include +#include +#include +#resource "res\\Expand2.bmp" +#resource "res\\size6.bmp" +#resource "res\\size10.bmp" + +class MaximizableAppDialog: public CAppDialog +{ + protected: + CAppDialog m_AppDialog; + CBmpButton m_button_truemax; + CBmpButton m_button_size; + bool m_maximized; + CRect m_max_rect; + CSize m_size_limit; + bool m_sizing; + + // window maximization + virtual bool CreateButtonMinMax(void) override; + virtual void OnClickButtonMinMax(void) override; + virtual void OnClickButtonTrueMax(void); + virtual void OnClickButtonSizeFixMe(void); + virtual void Expand(void); + virtual void Restore(void); + + virtual void Minimize(void) override; + + // window resizing + bool CreateButtonSize(void); + bool OnDialogSizeStart(void); + virtual bool OnDialogDragStart(void) override; + virtual bool OnDialogDragProcess(void) override; + virtual bool OnDialogDragEnd(void) override; + + virtual void SelfAdjustment(const bool minimized = false) = 0; + + public: + MaximizableAppDialog(): m_maximized(false), m_sizing(false) {} + virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) override; + virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override; + + virtual bool OnChartChange(const long &lparam, const double &dparam, const string &sparam); + + void ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam); + + void SetSizeLimit(const CSize &limit) { m_size_limit = limit; } + CSize GetSizeLimit() { return m_size_limit; } +}; + +void MaximizableAppDialog::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) +{ + if(id == CHARTEVENT_CHART_CHANGE) + { + if(OnChartChange(lparam, dparam, sparam)) return; + } + CAppDialog::ChartEvent(id, lparam, dparam, sparam); +} + +EVENT_MAP_BEGIN(MaximizableAppDialog) + ON_EVENT(ON_CLICK, m_button_truemax, OnClickButtonTrueMax) + ON_EVENT(ON_CLICK, m_button_size, OnClickButtonSizeFixMe) + ON_EVENT(ON_DRAG_START, m_button_size, OnDialogSizeStart) + ON_EVENT_PTR(ON_DRAG_PROCESS, m_drag_object, OnDialogDragProcess) + ON_EVENT_PTR(ON_DRAG_END, m_drag_object, OnDialogDragEnd) +EVENT_MAP_END(CAppDialog) + +bool MaximizableAppDialog::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) +{ + // 1 * CONTROLS_BORDER_WIDTH - stays here, because the standard control library minimizes window + // when it's height is 1 pixel smaller than the entire chart height + m_max_rect.SetBound(0, + 0, + (int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH, + (int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH); + // if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) return false; + // if(!m_AppDialog.Create(chart, name, subwin, x1, y1, x2, y2)) return false; + if(!CreateButtonSize()) return false; + m_size_limit.cx = x2 - x1; + m_size_limit.cy = y2 - y1; + if(m_size_limit.cx >= m_max_rect.Width() || m_size_limit.cy >= m_max_rect.Height()) + { + m_size_limit.cx = m_min_rect.Width() * 3; + m_size_limit.cy = m_min_rect.Height() * 7; + } + + return true; +} + +bool MaximizableAppDialog::CreateButtonMinMax(void) override +{ + if(!CAppDialog::CreateButtonMinMax()) return false; + + // add maximization button + int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH; + + int x1 = Width() - off - 3 * (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; + + if(!m_button_truemax.Create(m_chart_id, m_name + "TrueMax", m_subwin, x1, y1, x2, y2)) return false; + if(!m_button_truemax.BmpNames("::res\\Expand2.bmp", "::res\\Restore.bmp")) return false; + if(!CWndContainer::Add(m_button_truemax)) return false; + + m_button_truemax.Locking(true); + m_button_truemax.Alignment(WND_ALIGN_RIGHT, 0, 0, off + 2 * CONTROLS_BUTTON_SIZE + 2 * CONTROLS_DIALOG_BUTTON_OFF, 0); + + CaptionAlignment(WND_ALIGN_WIDTH, off, 0, off + 3 * (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF), 0); + + return true; +} + +bool MaximizableAppDialog::CreateButtonSize(void) +{ + int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH; + + int x1 = Width() - CONTROLS_BUTTON_SIZE + 1; + int y1 = Height() - CONTROLS_BUTTON_SIZE + 1; + int x2 = x1 + CONTROLS_BUTTON_SIZE - 1; + int y2 = y1 + CONTROLS_BUTTON_SIZE - 1; + + if(!m_button_size.Create(m_chart_id, m_name + "Size", m_subwin, x1, y1, x2, y2)) return false; + if(!m_button_size.BmpNames("::res\\size6.bmp", "::res\\size10.bmp")) return false; + if(!CWndContainer::Add(m_button_size)) return false; + m_button_size.Alignment(WND_ALIGN_RIGHT|WND_ALIGN_BOTTOM, 0, 0, 0, 0); + m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG); + + return true; +} + +void MaximizableAppDialog::OnClickButtonTrueMax(void) +{ + if(m_button_truemax.Pressed()) + Expand(); + else + Restore(); + + SubwinOff(); +} + +// This is a hack. It's required because in minimized state sizing button somehow "overlaps" +// the close button and intercepts clicks on it (which prevents exit from minimized app). +// This happens despite the fact that the sizing button is hidden, disabled and assigned +// with minimal Z-order (checked out, then removed). +// Looks like a bug in the standard control library, specifically: +// In CWnd::OnMouseEvent there must be a line: +// +// if(!IS_ENABLED || !IS_VISIBLE) return false; +// +// but it's not there, so invisible, disabled and even background objects are processed +// in the same manner as all other objects. Specifically in CWndContainer::OnMouseEvent +// there is a reverse loop through all objects (it does _not_ respect Z-order anyhow). + +void MaximizableAppDialog::OnClickButtonSizeFixMe(void) +{ + if(m_minimized) + { + Destroy(); + } +} + +void MaximizableAppDialog::Expand(void) +{ + m_maximized = true; + m_minimized = false; + // m_button_minmax.Pressed(false); + Rebound(m_max_rect); + m_button_size.Hide(); + m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE); + m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG); + // if(!m_panel_flag) + // { + // m_caption.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG); + // } + + ClientAreaVisible(true); + SelfAdjustment(); +} + +//+------------------------------------------------------------------+ +//| Restore dialog window | +//+------------------------------------------------------------------+ +void MaximizableAppDialog::Restore(void) +{ + m_maximized = false; + m_minimized = false; + // m_button_minmax.Pressed(false); + m_button_size.Show(); + m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE); + m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG); + CAppDialog::Maximize(); + // if(!m_panel_flag) + // { + // m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG); + // } + SelfAdjustment(); +} + +void MaximizableAppDialog::Minimize() +{ + CAppDialog::Minimize(); + m_button_size.Hide(); + m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE); + m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG); +} + +bool MaximizableAppDialog::OnChartChange(const long &lparam, const double &dparam, const string &sparam) +{ + m_max_rect.SetBound(0, 0, + (int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH, + (int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH); + if(m_maximized) + { + if(m_rect.Width() != m_max_rect.Width() || m_rect.Height() != m_max_rect.Height()) + { + Rebound(m_max_rect); + SelfAdjustment(); + m_chart.Redraw(); + } + return true; + } + return false; +} + +void MaximizableAppDialog::OnClickButtonMinMax(void) +{ + CAppDialog::OnClickButtonMinMax(); + m_button_truemax.Pressed(false); + m_maximized = false; + if(m_minimized) + { + m_button_size.Hide(); + m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE); + m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG); + } + else + { + m_button_size.Show(); + m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE); + m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG); + } + // if(!m_panel_flag) + // { + // m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG); + // } + SelfAdjustment(m_minimized); +} + +bool MaximizableAppDialog::OnDialogSizeStart(void) +{ + if(m_drag_object == NULL) + { + m_drag_object = new CDragWnd; + if(m_drag_object == NULL) return false; + } + int x1 = m_button_size.Left() - CONTROLS_DRAG_SPACING; + int y1 = m_button_size.Top() - CONTROLS_DRAG_SPACING; + int x2 = m_button_size.Right() + CONTROLS_DRAG_SPACING; + int y2 = m_button_size.Bottom() + CONTROLS_DRAG_SPACING; + + m_drag_object.Create(m_chart_id, "", m_subwin, x1, y1, x2, y2); + m_drag_object.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG); + + 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(); + + m_drag_object.MouseX(m_button_size.MouseX()); + m_drag_object.MouseY(m_button_size.MouseY()); + m_drag_object.MouseFlags(m_button_size.MouseFlags()); + + m_sizing = true; + + return true; +} + +bool MaximizableAppDialog::OnDialogDragStart(void) +{ + if(m_maximized) return false; + + return CAppDialog::OnDialogDragStart(); +} +//+------------------------------------------------------------------+ +//| Continue dragging the dialog box | +//+------------------------------------------------------------------+ +bool MaximizableAppDialog::OnDialogDragProcess(void) +{ + if(!m_sizing) return CDialog::OnDialogDragProcess(); + + if(m_drag_object == NULL) return false; + + int x = m_drag_object.Right() - Right() - CONTROLS_DRAG_SPACING; + int y = m_drag_object.Bottom() - Bottom() - CONTROLS_DRAG_SPACING; + + // resize dialog + CRect r = Rect(); + r.right += x; + r.bottom += y; + + if(r.Width() < m_size_limit.cx) r.right = r.left + m_size_limit.cx; + if(r.Height() < m_size_limit.cy) r.bottom = r.top + m_size_limit.cy; + + Rebound(r); + + SelfAdjustment(); + + return true; +} +//+------------------------------------------------------------------+ +//| End dragging the dialog box | +//+------------------------------------------------------------------+ +bool MaximizableAppDialog::OnDialogDragEnd(void) +{ + if(!m_sizing) return CDialog::OnDialogDragEnd(); + + if(m_drag_object != NULL) + { + m_button_size.MouseFlags(m_drag_object.MouseFlags()); + delete m_drag_object; + m_drag_object = NULL; + } + + m_norm_rect.SetBound(m_rect); + m_sizing = false; + + SelfAdjustment(); + + return true; +} diff --git a/Retrace/res/Moon_Panel.bmp b/Retrace/res/Moon_Panel.bmp new file mode 100644 index 0000000000000000000000000000000000000000..87221b0a943e47c4848f00ee4eb1234e4467466a GIT binary patch literal 1080 zcmb7?O-}+b5QYoUgK|Mg)Pq5|fZ|soMo}XNkdGkz6aW9&=PA3%X0yWXn>^j=Y}=XX zbh;fMg{W7?8)zofLKiE9I{#aZ9ntas(Bju4e8CLfp${jpPn;h2toTmg8-5bow6yP` z4tce4Y`{3iH}(@)N)MFr$KcsXwOAn-cMTU#P%R-&GJ}3)Z6DFv4aPEVk&HQnDJ)?D z-pMcAfq7eRQB4E<*7O3GV4kO7eb#1OejgyO5so>yXP?ZglUrad=2(nfzre&RcmIn=e+f;vz_}dYAi?+nNQ(g_tbAA@2+|are$Y}V zczy1yt|rDNZ+ANTW@qNjrcTdy74aSO^@wBd8#~G&w-hDC&-MK;2nSyP2&~uZ1IE}{ zu~;l;G8vyhHu>mG@@RJ)=R{T2LN1qsuIuo9Uw~}#rPJvGafnN?D*w;t^N8aZ@3swR zJ{SBrijX7;G))sRvIe>%S}f3I43=eKwOV1b*@!&|0&t$lBkMI9ItEV+;};X2?;;38 zB-;;cw_8L!hwHj93MMi6g7^=WAOSRbs+xjWeLM>2P3nG zx5+EqxsAZ{;PbnCy`IP+HPa0p?N$S=dKClKhRNe5!)MH<6PSa(0BI%lrG5jRLTLG4J^z~*=|P|x Xve_(XmU3Ql&TGD7{;fr)m{o}iO}^R-2w|E&=iSal`b8uC6?+G-8y>clG#Nl)(WiY&y1Nt zvqT##gkp%!>@Fy=3I;-ZutU4!Fe}T{{nz(SeiqTd^UXW&`+nc|yw5WO7e@9P@zbr= z;|lwCu*Yaukzov|x|{foIH49GMifQIs@3YPLZR@{G|fODvE-zt`{Z4(*UuD-#rL*t z6N|m?KpX&R*Q`}Xc0p*3bAs8$$%!uyp?*Ee}P5KX_VHn0I#;YK; z*wo0p*3bAs8$$O3*9>T3TBEQ)2jn1q=RzFu7(d sU%veRo;`cWHUp&p@ZrP%w{G3~zq`AeWOq<%Kc)VsH2ld8_o1f`05&`@LjV8( literal 0 HcmV?d00001 diff --git a/Retrace/res/SpinDec.bmp b/Retrace/res/SpinDec.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ad4d3d036ee90c672dcb37dc3bbf8128f033a4d6 GIT binary patch literal 568 zcmZ?rwP0cZ12Z700mK48%mKuV3<^M!fq@AqFT@SOV1Xe(ba!|EC)b$^7A*L`b?esu rAevM&KzjD<+4KMK;lp5>6f;^{TEKQLU%vc541@H8#7T7r?bQPS_02Fh literal 0 HcmV?d00001 diff --git a/Retrace/res/SpinInc.bmp b/Retrace/res/SpinInc.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ce0ae600964765232993b06d33d986be749a43b1 GIT binary patch literal 568 zcmZ?rwP0cZ12Z700mK48%mKuV3<^M!fq@AqFT@SOV1YqOw6wJRU$9`o|K-bEA@L@0w;uEVErVgZM>(;Gcx4^_mrMtVkNw$|%J1A2R0A{W*Hvj+t literal 0 HcmV?d00001 diff --git a/Retrace/res/Sun_Panel.bmp b/Retrace/res/Sun_Panel.bmp new file mode 100644 index 0000000000000000000000000000000000000000..96ff14c5693985d77966030704c668d2030d825a GIT binary patch literal 1080 zcma))Jx>EM3_!!jRt8itfW*LrfHI>paUjG%)eYEyP9VYm-+AvYMy8|%OE2fxj?b}k zGoNmkUM^TqV7IbSj?hZk#6KPl^oGBe1487#Vg>%XR#L9fJ5a*6HEdU|Pk2tN_mHnB z+8%rD_mXq&;68&HEGp`r=l0(cHEOVCbL*eLCtSjQMg0Tx8Dp$xLd<1;@$4Qfi#Bsa zT>gK=&QPYYX?(52m@Ll6KHH~PI0k#r67OS-u^qVgyt=k$F#j#I#P|i|^EvLG%^cog zoE=qf)vqi1=iKbk9lU{c#9ea#jLZGY^E=1q46MU??1w!y?*z=}8_V-sem~C0KD>ba qQr9+ukbEX=e%HOl)(# literal 0 HcmV?d00001 diff --git a/Retrace/res/ThumbHor.bmp b/Retrace/res/ThumbHor.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8c9bed398c71bc8f057cdfd614e8df0420ae50f3 GIT binary patch literal 1144 zcmZ?rtzcmQ12Z700mNcJEC9re3=%++fx!tVFT@SOU;!X;jA8&be4ZN)`ZWq^%i~zyRnrOa`)p@w#I<7yy-HGDgi0p*3bAs8$$N}z;5dwcu)rAwFoU%q@fRt%B@ WsX@_%#GzC_l2N0~(GZ|h2mk=wFFNA@ literal 0 HcmV?d00001 diff --git a/Retrace/res/Up.bmp b/Retrace/res/Up.bmp new file mode 100644 index 0000000000000000000000000000000000000000..bfea4cda288065cc9b0e702b9dd8581cb0f46ff3 GIT binary patch literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@883m+-Kub%@f&~kf!vK&C6v1x* qP|cn_dk!By3?zYU{E8v6KxJFEZY5GNL`!#fH!&uUszD0@1_l5;g}5gG literal 0 HcmV?d00001 diff --git a/Retrace/res/UpTransp.bmp b/Retrace/res/UpTransp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..11b45f1e2a654eea69990f30f3aa0a1d6944a9f9 GIT binary patch literal 1080 zcmZ?rwP0ZY12Z700mK4O%*dbsWHB%>0p*3bAs8$$N({;nXlZHrzhJ?F|I3#zhhq>Q yBu=b@LF)JH+4KMK;lp4W#3xoSOdUwi)~#E?Zh?uBN_Tg6lWZ@kc8sd0Bm@9)Krll9 literal 0 HcmV?d00001 diff --git a/Retrace/res/Up_Panel.bmp b/Retrace/res/Up_Panel.bmp new file mode 100644 index 0000000000000000000000000000000000000000..029cbdd698ccfb78d2953cb73efef49ae5936b5b GIT binary patch literal 1080 zcmbu8IS#@w5JgRdprAp(0n)G)w2+o`AP_VxVyU?Q9r!ParI8hgtbFOk6VH5mVmbLS z>$*Z~Jr`nF(Q&CF=Mv>dgOXyRe2g`m#a-OQwE=3V#e?@G_F^h#2Hq`U4i9Uv9(A$8 zLm%`zk2R~Fe*E_m#|jU7Uj)aUioR$PHL1Yk{j9YS55bxK61k_ygx%lwztsFkFot43 zo8$cK{=R;q;4N~IRBScA1Uav|{e7;dU?=Dmh?%qc=l69h1yCpN=NpJ)W&LgLPuu(3 U_W$8d90d0;gtG~uU-SQd0i|{#>i_@% literal 0 HcmV?d00001 diff --git a/Retrace/res/size10.bmp b/Retrace/res/size10.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b54a419fec6f1976d211ba076469d4177d8a3d8d GIT binary patch literal 1078 zcmZ?rHDh4_12Z700mK4O%*dbsWB~zCUWgllAp+DVySuypgD}WsV%X>|AVv?e8g%{C vQEES>`l;!cfi?>O-m7Y- literal 0 HcmV?d00001 diff --git a/Retrace/res/size6.bmp b/Retrace/res/size6.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3c6d8109e339298520fc9d17f2d6588a48e04c15 GIT binary patch literal 1078 zcmZ?rHDh4_12Z700mK4O%*dbsWB~zCUWgllAp*1|ySuypgD}VzTx@(Uz@-OS9G`w_ i$|2i{%qG?jWIf1iV)au~9i{eDs-K#E88wTt5C8xQ%|NFB literal 0 HcmV?d00001