├── .gitattributes ├── .gitignore ├── MtGuiController.sln └── MtGuiController ├── Controller.cs ├── IController.cs ├── MtGuiController.csproj └── Properties └── AssemblyInfo.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /MtGuiController.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2035 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MtGuiController", "MtGuiController\MtGuiController.csproj", "{C55DF26C-CE58-4E23-A6C5-8E2AD1D1F7B2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C55DF26C-CE58-4E23-A6C5-8E2AD1D1F7B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {C55DF26C-CE58-4E23-A6C5-8E2AD1D1F7B2}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {C55DF26C-CE58-4E23-A6C5-8E2AD1D1F7B2}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {C55DF26C-CE58-4E23-A6C5-8E2AD1D1F7B2}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {FB37DBBB-67EA-495C-BFD3-5FA442ACFF2E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /MtGuiController/Controller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | using System.Reflection; 5 | using System.IO; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace MtGuiController 10 | { 11 | /// 12 | /// Class contein not-static methods and handlers for abstract windows form 13 | /// 14 | public partial class GuiController 15 | { 16 | #region Private fileds 17 | /// 18 | /// 19 | /// 20 | private Assembly m_assembly = null; 21 | /// 22 | /// Windows form 23 | /// 24 | private Form m_form = null; 25 | /// 26 | /// 27 | /// 28 | private bool m_is_closing = false; 29 | /// 30 | /// Global events list 31 | /// 32 | private List m_events = null; 33 | /// 34 | /// Controls collection 35 | /// 36 | private Dictionary m_controls = new Dictionary(); 37 | 38 | /// 39 | /// Abstract handler of any event of win-form element 40 | /// 41 | /// 42 | private delegate void HandlerControl(Control control); 43 | #endregion 44 | #region Handlers of events 45 | 46 | /// 47 | /// This method receives a scroll event and sends it's to MetaTrader 48 | /// 49 | /// ScrollBar element 50 | /// Params of scroll 51 | private void OnScroll(object sender, EventArgs e) 52 | { 53 | Control control = (Control)sender; 54 | ScrollEventArgs scroll_args = (ScrollEventArgs)e; 55 | if (scroll_args.Type != ScrollEventType.SmallIncrement && 56 | scroll_args.Type != ScrollEventType.SmallDecrement) 57 | return; 58 | GuiEvent evnt = new GuiEvent 59 | { 60 | id = GuiEventType.ScrollChange, 61 | el_name = control.Name, 62 | lparam = scroll_args.OldValue, 63 | dparam = scroll_args.NewValue, 64 | }; 65 | m_events.Add(evnt); 66 | } 67 | /// 68 | /// This method receives a click event and sends it's to MetaTrader 69 | /// 70 | /// Any winform element 71 | /// 72 | private void OnClick(object sender, EventArgs e) 73 | { 74 | Control control = (Control)sender; 75 | GuiEvent evnt = new GuiEvent 76 | { 77 | id = GuiEventType.ClickOnElement, 78 | el_name = control.Name, 79 | sparam = control.Text 80 | }; 81 | m_events.Add(evnt); 82 | } 83 | /// 84 | /// This method receives a click event and sends it's to MetaTrader 85 | /// 86 | /// Any winform element 87 | /// 88 | private void OnChecked(object sender, EventArgs e) 89 | { 90 | CheckBox control = (CheckBox)sender; 91 | GuiEvent evnt = new GuiEvent 92 | { 93 | id = GuiEventType.CheckBoxChange, 94 | el_name = control.Name, 95 | sparam = control.Text, 96 | lparam = (long)control.CheckState 97 | }; 98 | m_events.Add(evnt); 99 | } 100 | private void OnRadioBtnCheckedChange(object sender, EventArgs e) 101 | { 102 | RadioButton control = (RadioButton)sender; 103 | GuiEvent evnt = new GuiEvent 104 | { 105 | id = GuiEventType.RadioButtonChange, 106 | el_name = control.Name, 107 | sparam = control.Text, 108 | lparam = control.Checked ? 1 : 0 109 | }; 110 | m_events.Add(evnt); 111 | } 112 | private void OnComboBoxChange(object sender, EventArgs e) 113 | { 114 | ComboBox control = (ComboBox)sender; 115 | string item_text = control.SelectedItem as string; 116 | GuiEvent evnt = new GuiEvent 117 | { 118 | id = GuiEventType.ComboBoxChange, 119 | el_name = control.Name, 120 | sparam = item_text, 121 | lparam = control.SelectedIndex 122 | }; 123 | m_events.Add(evnt); 124 | } 125 | /// 126 | /// This method receives the availability of the objec to MetaTrader 127 | /// 128 | /// Any winform element 129 | /// 130 | private void OnEnableChange(object sender, EventArgs e) 131 | { 132 | Control control = (Control)sender; 133 | GuiEvent evnt = new GuiEvent 134 | { 135 | id = GuiEventType.ElementEnable, 136 | el_name = control.Name, 137 | sparam = control.Text, 138 | lparam = control.Enabled ? 1 : 0, 139 | }; 140 | m_events.Add(evnt); 141 | } 142 | 143 | private void OnNumericChanged(object sender, EventArgs e) 144 | { 145 | NumericUpDown numeric = (NumericUpDown)sender; 146 | GuiEvent evnt = new GuiEvent 147 | { 148 | id = GuiEventType.NumericChange, 149 | el_name = numeric.Name, 150 | dparam = (double)numeric.Value 151 | }; 152 | m_events.Add(evnt); 153 | } 154 | /// 155 | /// 156 | /// 157 | /// 158 | /// 159 | private void OnDateTimePickerChanged(object sender, EventArgs e) 160 | { 161 | DateTimePicker picker = (DateTimePicker)sender; 162 | GuiEvent evnt = new GuiEvent 163 | { 164 | id = GuiEventType.DateTimePickerChange, 165 | el_name = picker.Name, 166 | lparam = MtConverter.ToMqlDateTime(picker.Value) 167 | }; 168 | m_events.Add(evnt); 169 | } 170 | /// 171 | /// This method receives a click event and sends it's to MetaTrader 172 | /// 173 | /// Any winform element 174 | /// 175 | private void OnTabChanged(object sender, EventArgs e) 176 | { 177 | TabControl control = (TabControl)sender; 178 | GuiEvent evnt = new GuiEvent 179 | { 180 | id = GuiEventType.TabIndexChange, 181 | el_name = control.Name, 182 | lparam = control.SelectedIndex, 183 | sparam = control.SelectedTab.Name 184 | }; 185 | m_events.Add(evnt); 186 | } 187 | /// 188 | /// This method receives a change text event and sends it's to MetaTrader 189 | /// 190 | /// 191 | /// 192 | private void OnTextChange(object c, EventArgs e) 193 | { 194 | Control control = (Control)c; 195 | GuiEvent evnt = new GuiEvent 196 | { 197 | id = GuiEventType.TextChange, 198 | el_name = control.Name, 199 | sparam = control.Text 200 | }; 201 | m_events.Add(evnt); 202 | } 203 | /// 204 | /// This method receives a lost focus event and interprets it as end text changed event 205 | /// 206 | /// 207 | /// 208 | private void OnLostFocus(object sender, EventArgs e) 209 | { 210 | Control control = (Control)sender; 211 | OnTextChange(sender, e); 212 | } 213 | /// 214 | /// This method receives a key down event and if pressed key is enter interprets it as end text changed event 215 | /// 216 | /// 217 | /// 218 | private void OnKeyDown(object sender, EventArgs e) 219 | { 220 | KeyEventArgs key_args = (KeyEventArgs)e; 221 | if (key_args.KeyCode == Keys.Enter) 222 | OnTextChange(sender, e); 223 | } 224 | 225 | #endregion 226 | 227 | /// 228 | /// Create new gui controller 229 | /// 230 | private GuiController(Assembly assembly, Form form, List global_events_list) 231 | { 232 | m_assembly = assembly; 233 | m_form = form; 234 | m_events = global_events_list; 235 | SubscribeOnElements(m_form); 236 | } 237 | /// 238 | /// Subscribe on supported events 239 | /// 240 | /// Windows form 241 | private void SubscribeOnElements(Form form) 242 | { 243 | form.FormClosing += OnClosingForm; 244 | //-- define resolve events 245 | Dictionary> types_and_events = new Dictionary>(); 246 | types_and_events.Add(typeof(VScrollBar), new List() { vscrol => ((VScrollBar)vscrol).Scroll += OnScroll }); 247 | types_and_events.Add(typeof(Button), new List() { button => ((Button)button).Click += OnClick }); 248 | types_and_events.Add(typeof(Label), new List()); 249 | types_and_events.Add(typeof(TextBox), new List() { text_box => text_box.LostFocus += OnLostFocus, 250 | text_box => text_box.KeyDown += OnKeyDown }); 251 | types_and_events.Add(typeof(CheckBox), new List() { check_box => ((CheckBox)check_box).CheckStateChanged += OnChecked }); 252 | types_and_events.Add(typeof(TabControl), new List() { tab_box => ((TabControl)tab_box).SelectedIndexChanged += OnTabChanged }); 253 | types_and_events.Add(typeof(RadioButton), new List() { radio_box => ((RadioButton)radio_box).CheckedChanged += OnRadioBtnCheckedChange }); 254 | types_and_events.Add(typeof(ComboBox), new List() { combo_box => ((ComboBox)combo_box).SelectedIndexChanged += OnComboBoxChange, 255 | combo_box => ((ComboBox)combo_box).TextChanged += OnTextChange}); 256 | types_and_events.Add(typeof(NumericUpDown), new List() { numeric => ((NumericUpDown)numeric).ValueChanged += OnNumericChanged}); 257 | types_and_events.Add(typeof(DateTimePicker), new List() { numeric => ((DateTimePicker)numeric).ValueChanged += OnDateTimePickerChanged }); 258 | //-- Recursive subscribe on controls 259 | SubscribeOnControls(types_and_events, form); 260 | } 261 | /// 262 | /// Recursive subscribe on controls 263 | /// 264 | /// 265 | private void SubscribeOnControls(Dictionary> types_and_events, Control control) 266 | { 267 | if (control.GetType() != typeof(NumericUpDown)) 268 | { 269 | foreach (Control cnt in control.Controls) 270 | SubscribeOnControls(types_and_events, cnt); 271 | } 272 | try 273 | { 274 | m_controls.Add(control.Name, control); 275 | } 276 | catch(ArgumentException ex) 277 | { 278 | throw new ArgumentException("Ключ с таким именем уже существует", control.Name, ex); 279 | } 280 | if (types_and_events.ContainsKey(control.GetType())) 281 | types_and_events[control.GetType()].ForEach(el => el.Invoke(control)); 282 | } 283 | /// 284 | /// Recursive subscribe on controls 285 | /// 286 | /// 287 | private void SubscribeOnControls_old(Dictionary> types_and_events, Control control) 288 | { 289 | foreach (Control cnt in control.Controls) 290 | SubscribeOnControls(types_and_events, cnt); 291 | if (control.GetType().BaseType == typeof(Form)) 292 | m_controls.Add(control.Name, control); 293 | control.EnabledChanged += OnEnableChange; 294 | if (types_and_events.ContainsKey(control.GetType())) 295 | { 296 | types_and_events[control.GetType()].ForEach(el => el.Invoke(control)); 297 | m_controls.Add(control.Name, control); 298 | } 299 | } 300 | /// 301 | /// 302 | /// 303 | private void MessageBoxCreate(string el_name, bool is_blocked, string info) 304 | { 305 | 306 | } 307 | /// 308 | /// Run form 309 | /// 310 | public void RunForm() 311 | { 312 | Thread thread = new Thread(() => Application.Run(m_form)); 313 | thread.SetApartmentState(ApartmentState.STA); 314 | thread.Start(); 315 | Thread.Sleep(200); 316 | } 317 | #region Dispose 318 | 319 | /// 320 | /// Dispose form 321 | /// 322 | public void DisposeForm() 323 | { 324 | m_form.Dispose(); 325 | } 326 | 327 | /// 328 | /// Handler on dispose of form 329 | /// 330 | /// 331 | /// 332 | private void OnClosingForm(object sender, EventArgs e) 333 | { 334 | m_is_closing = true; 335 | m_controls.Clear(); 336 | } 337 | /// 338 | /// Dispose status 339 | /// 340 | private bool IsDiposed 341 | { 342 | get 343 | { 344 | if (m_is_closing) 345 | return true; 346 | if (m_form == null) 347 | return true; 348 | return m_form.IsDisposed; 349 | } 350 | } 351 | #endregion 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /MtGuiController/IController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | using System.Reflection; 5 | 6 | namespace MtGuiController.Published 7 | { 8 | public enum BlockingControl 9 | { 10 | NotLockControl, 11 | LockControl 12 | } 13 | // 14 | // Summary: 15 | // Specifies constants defining which buttons to display on a System.Windows.Forms.MessageBox. 16 | public enum MessageBoxButtons 17 | { 18 | // 19 | // Summary: 20 | // The message box contains an OK button. 21 | OK = 0, 22 | // 23 | // Summary: 24 | // The message box contains OK and Cancel buttons. 25 | OKCancel = 1, 26 | // 27 | // Summary: 28 | // The message box contains Abort, Retry, and Ignore buttons. 29 | AbortRetryIgnore = 2, 30 | // 31 | // Summary: 32 | // The message box contains Yes, No, and Cancel buttons. 33 | YesNoCancel = 3, 34 | // 35 | // Summary: 36 | // The message box contains Yes and No buttons. 37 | YesNo = 4, 38 | // 39 | // Summary: 40 | // The message box contains Retry and Cancel buttons. 41 | RetryCancel = 5 42 | } 43 | } 44 | 45 | 46 | namespace MtGuiController 47 | { 48 | 49 | /// 50 | /// Type of gui event 51 | /// 52 | public enum GuiEventType 53 | { 54 | Exception, 55 | MessageBox, 56 | ClickOnElement, 57 | TextChange, 58 | ScrollChange, 59 | TabIndexChange, 60 | CheckBoxChange, 61 | ElementEnable, 62 | RadioButtonChange, 63 | ComboBoxChange, 64 | NumericChange, 65 | NumericFormatChange, 66 | NumericMaxChange, 67 | NumericMinChange, 68 | DateTimePickerChange, 69 | ElementHide, 70 | AddItem, 71 | } 72 | /// 73 | /// Container for event 74 | /// 75 | public class GuiEvent 76 | { 77 | public string assembly_name; 78 | public string form_name; 79 | public string el_name; 80 | public GuiEventType id; 81 | public long lparam; 82 | public double dparam; 83 | public string sparam; 84 | } 85 | 86 | public partial class GuiController 87 | { 88 | /// 89 | /// One controller for each windows form 90 | /// 91 | private static Dictionary m_controllers = new Dictionary(); 92 | /// 93 | /// Events list 94 | /// 95 | private static List m_global_events = new List(); 96 | 97 | #region private methods 98 | /// 99 | /// Create GuiController for windows form 100 | /// 101 | /// Path to assembly 102 | /// Windows Form's name 103 | /// 104 | private static GuiController GetGuiController(string assembly_path, string form_name) 105 | { 106 | Assembly assembly = Assembly.LoadFile(assembly_path); 107 | Form form = FindForm(assembly, form_name); 108 | GuiController controller = new GuiController(assembly, form, m_global_events); 109 | return controller; 110 | } 111 | /// 112 | /// Find needed form 113 | /// 114 | /// Assembly 115 | /// 116 | private static Form FindForm(Assembly assembly, string form_name) 117 | { 118 | Type[] types = assembly.GetTypes(); 119 | foreach (Type type in types) 120 | { 121 | //assembly.CreateInstance() 122 | if (type.BaseType == typeof(Form) && type.Name == form_name) 123 | { 124 | object obj_form = type.Assembly.CreateInstance(type.FullName); 125 | return (Form)obj_form; 126 | } 127 | } 128 | throw new Exception("Form with name " + form_name + " in assembly " + assembly.FullName + " not find"); 129 | } 130 | /// 131 | /// 132 | /// 133 | /// 134 | private static void SendExceptionEvent(Exception ex) 135 | { 136 | GuiEvent ex_event = new GuiEvent() 137 | { 138 | id = (int)GuiEventType.Exception, 139 | sparam = ex.Message 140 | }; 141 | m_global_events.Add(ex_event); 142 | } 143 | 144 | #endregion 145 | #region MetaTrader Interface methods 146 | /// 147 | /// Show Windows form 148 | /// 149 | [STAThread] 150 | public static void ShowForm(string assembly_path, string form_name) 151 | { 152 | try 153 | { 154 | GuiController controller = GetGuiController(assembly_path, form_name); 155 | string full_path = assembly_path + "/" + form_name; 156 | m_controllers.Add(full_path, controller); 157 | controller.RunForm(); 158 | } 159 | catch(ArgumentException e) 160 | { 161 | Type t = e.GetType(); 162 | SendExceptionEvent(e); 163 | } 164 | } 165 | 166 | /// 167 | /// Hide Windows Form 168 | /// 169 | public static void HideForm(string assembly_path, string form_name) 170 | { 171 | try 172 | { 173 | string full_path = assembly_path + "/" + form_name; 174 | if (!m_controllers.ContainsKey(full_path)) 175 | return; 176 | GuiController controller = m_controllers[full_path]; 177 | controller.DisposeForm(); 178 | m_controllers.Remove(full_path); 179 | } 180 | catch(Exception ex) 181 | { 182 | SendExceptionEvent(ex); 183 | } 184 | } 185 | 186 | /// 187 | /// Send event 188 | /// 189 | /// name of control 190 | /// Event type 191 | /// long value 192 | /// double value 193 | /// string value 194 | public static void SendEvent(string el_name, int id, long lparam, double dparam, string sparam) 195 | { 196 | SendEventRef(el_name, ref id, ref lparam, ref dparam, sparam); 197 | } 198 | /// 199 | /// Send event 200 | /// 201 | /// name of control 202 | /// Event type 203 | /// long value 204 | /// double value 205 | /// string value 206 | public static void SendEventRef(string el_name, ref int id, ref long lparam, ref double dparam, string sparam) 207 | { 208 | try 209 | { 210 | foreach (var kvp in m_controllers) 211 | { 212 | GuiController controller = kvp.Value; 213 | if (controller.IsDiposed) 214 | { 215 | m_controllers.Remove(kvp.Key); 216 | return; 217 | } 218 | Control control = null; 219 | if (!controller.m_controls.TryGetValue(el_name, out control)) 220 | { 221 | SendExceptionEvent(new Exception("SendEvent: element with name '" + el_name + "' not find")); 222 | continue; 223 | } 224 | GuiEventType event_type = (GuiEventType)id; 225 | switch (event_type) 226 | { 227 | case GuiEventType.TextChange: 228 | control.Invoke((MethodInvoker)delegate { control.Text = sparam; }); 229 | break; 230 | case GuiEventType.CheckBoxChange: 231 | { 232 | CheckBox checkBox = (CheckBox)control; 233 | CheckState state = (CheckState)lparam; 234 | control.Invoke((MethodInvoker)delegate { checkBox.CheckState = state; }); 235 | break; 236 | } 237 | case GuiEventType.RadioButtonChange: 238 | RadioButton radio_btn = (RadioButton)control; 239 | bool check = lparam == 0 ? false : true; 240 | control.Invoke((MethodInvoker)delegate { radio_btn.Checked = check; }); 241 | break; 242 | case GuiEventType.ComboBoxChange: 243 | ComboBox combo_box = (ComboBox)control; 244 | if(combo_box.SelectedIndex != (int)lparam) 245 | combo_box.SelectedIndex = (int)lparam; 246 | break; 247 | case GuiEventType.NumericChange: 248 | NumericUpDown numeric = (NumericUpDown)control; 249 | if (numeric.Value != (decimal)dparam) 250 | numeric.Value = (decimal)dparam; 251 | break; 252 | case GuiEventType.NumericFormatChange: 253 | if (control.GetType() != typeof(NumericUpDown)) 254 | { 255 | SendExceptionEvent(new Exception("Element " + control.Name + " doesn't support 'NumericStepsChange' event")); 256 | break; 257 | } 258 | NumericUpDown num = (NumericUpDown)control; 259 | num.DecimalPlaces = (int)lparam; 260 | num.Increment = (decimal)dparam; 261 | break; 262 | case GuiEventType.NumericMaxChange: 263 | if (control.GetType() != typeof(NumericUpDown)) 264 | { 265 | SendExceptionEvent(new Exception("Element " + control.Name + " doesn't support 'NumericMaxChange' event")); 266 | break; 267 | } 268 | NumericUpDown nummax = (NumericUpDown)control; 269 | nummax.Maximum = (decimal)dparam; 270 | break; 271 | case GuiEventType.NumericMinChange: 272 | if (control.GetType() != typeof(NumericUpDown)) 273 | { 274 | SendExceptionEvent(new Exception("Element " + control.Name + " doesn't support 'NumericMinChange' event")); 275 | break; 276 | } 277 | NumericUpDown nummin = (NumericUpDown)control; 278 | nummin.Minimum = (decimal)dparam; 279 | break; 280 | case GuiEventType.ElementHide: 281 | if (lparam != 0) 282 | control.Hide(); 283 | else 284 | control.Show(); 285 | break; 286 | case GuiEventType.DateTimePickerChange: 287 | DateTimePicker picker = (DateTimePicker)control; 288 | picker.Value = MtConverter.ToSharpDateTime(lparam); 289 | break; 290 | case GuiEventType.ElementEnable: 291 | { 292 | bool enable = lparam == 0 ? false : true; 293 | if (enable != control.Enabled) 294 | { 295 | control.Invoke((MethodInvoker)delegate { control.Enabled = enable; }); 296 | controller.OnEnableChange(control, new EventArgs()); 297 | } 298 | break; 299 | } 300 | case GuiEventType.MessageBox: 301 | { 302 | if (lparam == 1) 303 | control.Enabled = false; 304 | string[] nodes = sparam.Split('|'); 305 | MessageBoxButtons buttons; 306 | if (dparam == 0.0) 307 | buttons = MessageBoxButtons.OK; 308 | else 309 | buttons = (MessageBoxButtons)(int)dparam; 310 | if (nodes.Length == 1) 311 | MessageBox.Show(sparam, sparam, buttons); 312 | else if (nodes.Length == 2) 313 | { 314 | var icon = ParseIcon(nodes[0]); 315 | if(icon == MessageBoxIcon.None) 316 | MessageBox.Show(nodes[0], nodes[1], buttons); 317 | else 318 | MessageBox.Show(nodes[1], nodes[1], buttons, icon); 319 | } 320 | else 321 | { 322 | var icon = ParseIcon(nodes[0]); 323 | MessageBox.Show(nodes[1], nodes[2], buttons, icon); 324 | } 325 | control.Enabled = true; 326 | break; 327 | } 328 | case GuiEventType.AddItem: 329 | if (control.GetType() != typeof(ComboBox)) 330 | { 331 | SendExceptionEvent(new Exception("Element " + control.Name + " doesn't support 'Add Item' event")); 332 | break; 333 | } 334 | ComboBox box = (ComboBox)control; 335 | box.Items.Add(sparam); 336 | break; 337 | 338 | } 339 | } 340 | } 341 | catch (Exception ex) 342 | { 343 | SendExceptionEvent(ex); 344 | } 345 | } 346 | /// 347 | /// Parse Icon 348 | /// 349 | /// 350 | /// 351 | private static MessageBoxIcon ParseIcon(string text) 352 | { 353 | if (text == "i" || text == "Info") 354 | return MessageBoxIcon.Information; 355 | else if (text == "?" || text == "Question") 356 | return MessageBoxIcon.Question; 357 | else if (text == "!!!" || text == "Error") 358 | return MessageBoxIcon.Error; 359 | else if (text == "!" || text == "Warning") 360 | return MessageBoxIcon.Warning; 361 | return MessageBoxIcon.None; 362 | } 363 | /// 364 | /// Get event 365 | /// 366 | /// Number of event 367 | /// element name 368 | /// Event type 369 | /// long value 370 | /// double value 371 | /// string value 372 | public static void GetEvent(int event_n, ref string el_name, ref int id, ref long lparam, ref double dparam, ref string sparam) 373 | { 374 | GuiEvent e = m_global_events[event_n]; 375 | el_name = e.el_name; 376 | id = (int)e.id; 377 | lparam = e.lparam; 378 | dparam = e.dparam; 379 | sparam = e.sparam; 380 | } 381 | /// 382 | /// 383 | /// 384 | /// 385 | public static int EventsTotal() 386 | { 387 | return m_global_events.Count; 388 | } 389 | #endregion 390 | } 391 | /// 392 | /// System Converter MetaTrader - C# 393 | /// 394 | public static class MtConverter 395 | { 396 | /// 397 | /// Convert C# DateTime format to MQL (POSIX) DateTime format. 398 | /// 399 | /// 400 | /// 401 | public static long ToMqlDateTime(DateTime date_time) 402 | { 403 | DateTime tiks_1970 = new DateTime(1970, 01, 01); 404 | if (date_time < tiks_1970) 405 | return 0; 406 | TimeSpan time_delta = date_time - tiks_1970; 407 | return (long)Math.Floor(time_delta.TotalSeconds); 408 | } 409 | /// 410 | /// Convert MQL (Posix) time format to sharp DateTime value. 411 | /// 412 | /// MQL datetime as tiks 413 | /// 414 | public static DateTime ToSharpDateTime(long mql_time) 415 | { 416 | DateTime tiks_1970 = new DateTime(1970, 01, 01); 417 | if (mql_time <= 0 || mql_time > int.MaxValue) 418 | return tiks_1970; 419 | TimeSpan time_delta = new TimeSpan(0, 0, (int)mql_time); 420 | DateTime sharp_time = tiks_1970 + time_delta; 421 | return sharp_time; 422 | } 423 | 424 | public static double DecimalMax() 425 | { 426 | return (double)decimal.MaxValue; 427 | } 428 | } 429 | } 430 | -------------------------------------------------------------------------------- /MtGuiController/MtGuiController.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C55DF26C-CE58-4E23-A6C5-8E2AD1D1F7B2} 8 | Library 9 | Properties 10 | MtGuiController 11 | MtGuiController 12 | v4.6.1 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /MtGuiController/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MtGuiController")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MtGuiController")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c55df26c-ce58-4e23-a6c5-8e2ad1d1f7b2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | --------------------------------------------------------------------------------