English 中文 Español Deutsch 日本語 Português
preview
Использование AutoIt с MQL5

Использование AutoIt с MQL5

MetaTrader 5Примеры | 1 февраля 2022, 15:25
2 590 4
Francis Dube
Francis Dube

Введение

В статье Управление терминалом MetaTrader с помощью DLL автор описывает, как управлять платформой MetaTrader 4, программно управляя графическим пользовательским интерфейсом приложения (GUI) с помощью пользовательской динамически подключаемой библиотеки (dll). В этой статье мы будем использовать функциональность, предоставляемую AutoIt. С помощью AutoIt мы создадим класс, позволяющий автоматизировать задачи, которые невозможно выполнить с помощью чистого MQL5.

Эти задачи включают в себя:

  • Возможность добавлять и удалять скрипты или советники с графиков.
  • Чтение советников терминала и вкладок журнала в окне инструментов.
  • Возможность автоматической обработки предупреждений (чтение предупреждающих сообщений и автоматическое закрытие диалоговых окон предупреждений).
  • Наконец, мы реализуем тот же функционал, который был продемонстрирован в статье о MetaTrader 4, а именно возможность устанавливать MetaQuotes ID в настройках терминала.


AutoIt

AutoIt – скриптовый язык для автоматизации графического пользовательского интерфейса Microsoft Windows. Помимо прочего, он позволяет управлять окнами, использовать компоненты пользовательского интерфейса, а также симулировать работу мыши и нажатие клавиш. Частью AutoIt является AutoItX.  Это dll, реализующий некоторые функции скриптового языка AutoIt. Взаимодействуя с этой dll, мы можем добавить в MQL5 возможности скриптов графического интерфейса.

Установка

AutoIt доступен бесплатно здесь. Он работает на всех версиях Microsoft Windows x86, включая Windows 10. Это 32-битное приложение, которое поставляется с различными 64-битными компонентами, включая 64-битную версию AutoItX. Подробности об AutoIt можно узнать в справке, являющейся частью приложения. Прежде чем мы пойдем дальше, необходимо упомянуть об ограничениях AutoIt.

Ограничения

AutoIt может надежно работать только со стандартными компонентами Microsoft Windows на основе Win32 API. AutoIt не работает с программами, использующими пользовательские компоненты. В основном это касается программ, созданных с использованием кроссплатформенных фреймворков. Проверить совместимость пользовательского интерфейса программы с AutoIt можно с помощью AutoIt Window Info Tool. Еще одно ограничение связано с тем, что AutoItX реализует только часть того, на что способен скриптовый язык AutoIt. Может случиться так, что какой-либо компонент обрабатывается AutoIt, но не AutoItX.

AutoIt Window Info Tool

AutoIt содержит инструмент AutoIt Window Info Tool для получения информации об окнах приложения.

Перемещая перекрестие (Finder Tool) по любой части целевого приложения, мы получаем сведения о свойствах каждого отдельного компонента. Эти компоненты называются элементами управления. В их число входят кнопки, выпадающие меню, вкладки и много других типов элементов управления для создания приложений. Каждый элемент управления связан с окном. Приложение может состоять из нескольких окон. Обычно есть главное окно, к которому прикрепляются дочерние окна. Если дочерние окна прикреплены к главному, все элементы управления, заключенные в дочерних окнах, становятся частью главного окна приложения. При использовании AutoIt для поиска элемента управления важно, с каким окном он связан – дочерним или главным.

На приведенной ниже gif-анимации мы видим, что перекрестие перемещается по разным областям MetaTrader 5. Обратите внимание на настройки Window Info Tool при выборе меню Options (параметры). Опции Freeze (заморозка), Always On Top (поверх всех окон) и Use Spy++ Control Detection Logic (использовать логику обнаружения управляющего элемента Spy++) включены.


На вкладке Window отображаются свойства окна, на которое наведено перекрестие, включая заголовок и класс. Эти свойства можно использовать для его идентификации. Вкладка Control отображает свойства элемента управления. Здесь нас интересует свойство ClassnameNN. (Имя класса в AutoIt относится к типу элемента управления). Это свойство объединяет тип элемента управления с идентификатором экземпляра в виде числа. Важно знать тип элемента управления. От этого зависит, какие вызовы функций AutoIt будут с ним работать.


Интеграция AutoItX

Для успешной интеграции с MetaTrader 5 нужно убедиться, что терминал может найти нужную dll во время работы. Для этого просто скопируйте требуемую dll в папку Libraries платформы MetaTrader 5. Каталог установки AutoIt3 по умолчанию находится в папке Program Files (x86). Внутри нее находится папка AutoItX со всеми необходимыми компонентами, включая заголовок AutoItX3_Dll, в котором перечислены все имеющиеся прототипы функций. Убедитесь, что dll подходит для вашего билда MetaTrader 5 (64 или 32 бита).

#pragma once

///////////////////////////////////////////////////////////////////////////////
//
// AutoItX v3
//
// Copyright (C)1999-2013:
//    - Jonathan Bennett <jon at autoitscript dot com>
//    - See "AUTHORS.txt" for contributors.
//
// This file is part of AutoItX.  Use of this file and the AutoItX DLL is subject
// to the terms of the AutoItX license details of which can be found in the helpfile.
//
// When using the AutoItX3.dll as a standard DLL this file contains the definitions,
// and function declarations required to use the DLL and AutoItX3_DLL.lib file.
//
///////////////////////////////////////////////////////////////////////////////


#ifdef __cplusplus
#define AU3_API extern "C"
#else
#define AU3_API
#endif


// Definitions
#define AU3_INTDEFAULT        (-2147483647)  // "Default" value for _some_ int parameters (largest negative number)

//
// nBufSize
// When used for specifying the size of a resulting string buffer this is the number of CHARACTERS
// in that buffer, including the null terminator.  For example:
//
// WCHAR szBuffer[10];
// AU3_ClipGet(szBuffer, 10);
//
// The resulting string will be truncated at 9 characters with the the terminating null in the 10th.
//


///////////////////////////////////////////////////////////////////////////////
// Exported functions
///////////////////////////////////////////////////////////////////////////////

#include <windows.h>
AU3_API void WINAPI AU3_Init(void);
AU3_API int AU3_error(void);

AU3_API int WINAPI AU3_AutoItSetOption(LPCWSTR szOption, int nValue);


AU3_API void WINAPI AU3_ClipGet(LPWSTR szClip, int nBufSize);
AU3_API void WINAPI AU3_ClipPut(LPCWSTR szClip);
AU3_API int WINAPI AU3_ControlClick(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPCWSTR szButton, int nNumClicks, int nX = AU3_INTDEFAULT, int nY = AU3_INTDEFAULT);
AU3_API int WINAPI AU3_ControlClickByHandle(HWND hWnd, HWND hCtrl, LPCWSTR szButton, int nNumClicks, int nX = AU3_INTDEFAULT, int nY = AU3_INTDEFAULT);
AU3_API void WINAPI AU3_ControlCommand(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPCWSTR szCommand, LPCWSTR szExtra, LPWSTR szResult, int nBufSize);
AU3_API void WINAPI AU3_ControlCommandByHandle(HWND hWnd, HWND hCtrl, LPCWSTR szCommand, LPCWSTR szExtra, LPWSTR szResult, int nBufSize);
AU3_API void WINAPI AU3_ControlListView(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPCWSTR szCommand, LPCWSTR szExtra1, LPCWSTR szExtra2, LPWSTR szResult, int nBufSize);
AU3_API void WINAPI AU3_ControlListViewByHandle(HWND hWnd, HWND hCtrl, LPCWSTR szCommand, LPCWSTR szExtra1, LPCWSTR szExtra2, LPWSTR szResult, int nBufSize);
AU3_API int WINAPI AU3_ControlDisable(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl);
AU3_API int WINAPI AU3_ControlDisableByHandle(HWND hWnd, HWND hCtrl);
AU3_API int WINAPI AU3_ControlEnable(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl);
AU3_API int WINAPI AU3_ControlEnableByHandle(HWND hWnd, HWND hCtrl);
AU3_API int WINAPI AU3_ControlFocus(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl);
AU3_API int WINAPI AU3_ControlFocusByHandle(HWND hWnd, HWND hCtrl);
AU3_API void WINAPI AU3_ControlGetFocus(LPCWSTR szTitle, LPCWSTR szText, LPWSTR szControlWithFocus, int nBufSize);
AU3_API void WINAPI AU3_ControlGetFocusByHandle(HWND hWnd, LPWSTR szControlWithFocus, int nBufSize);
AU3_API HWND WINAPI AU3_ControlGetHandle(HWND hWnd, LPCWSTR szControl);
AU3_API void WINAPI AU3_ControlGetHandleAsText(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPCWSTR szControl, LPWSTR szRetText, int nBufSize);
AU3_API int WINAPI AU3_ControlGetPos(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPRECT lpRect);
AU3_API int WINAPI AU3_ControlGetPosByHandle(HWND hWnd, HWND hCtrl, LPRECT lpRect);
AU3_API void WINAPI AU3_ControlGetText(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPWSTR szControlText, int nBufSize);
AU3_API void WINAPI AU3_ControlGetTextByHandle(HWND hWnd, HWND hCtrl, LPWSTR szControlText, int nBufSize);
AU3_API int WINAPI AU3_ControlHide(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl);
AU3_API int WINAPI AU3_ControlHideByHandle(HWND hWnd, HWND hCtrl);
AU3_API int WINAPI AU3_ControlMove(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, int nX, int nY, int nWidth = -1, int nHeight = -1);
AU3_API int WINAPI AU3_ControlMoveByHandle(HWND hWnd, HWND hCtrl, int nX, int nY, int nWidth = -1, int nHeight = -1);
AU3_API int WINAPI AU3_ControlSend(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPCWSTR szSendText, int nMode = 0);
AU3_API int WINAPI AU3_ControlSendByHandle(HWND hWnd, HWND hCtrl, LPCWSTR szSendText, int nMode = 0);
AU3_API int WINAPI AU3_ControlSetText(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPCWSTR szControlText);
AU3_API int WINAPI AU3_ControlSetTextByHandle(HWND hWnd, HWND hCtrl, LPCWSTR szControlText);
AU3_API int WINAPI AU3_ControlShow(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl);
AU3_API int WINAPI AU3_ControlShowByHandle(HWND hWnd, HWND hCtrl);
AU3_API void WINAPI AU3_ControlTreeView(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szControl, LPCWSTR szCommand, LPCWSTR szExtra1, LPCWSTR szExtra2, LPWSTR szResult, int nBufSize);
AU3_API void WINAPI AU3_ControlTreeViewByHandle(HWND hWnd, HWND hCtrl, LPCWSTR szCommand, LPCWSTR szExtra1, LPCWSTR szExtra2, LPWSTR szResult, int nBufSize);

AU3_API void WINAPI AU3_DriveMapAdd(LPCWSTR szDevice, LPCWSTR szShare, int nFlags, /*[in,defaultvalue("")]*/LPCWSTR szUser, /*[in,defaultvalue("")]*/LPCWSTR szPwd, LPWSTR szResult, int nBufSize);
AU3_API int WINAPI AU3_DriveMapDel(LPCWSTR szDevice);
AU3_API void WINAPI AU3_DriveMapGet(LPCWSTR szDevice, LPWSTR szMapping, int nBufSize);

AU3_API int WINAPI AU3_IsAdmin(void);

AU3_API int WINAPI AU3_MouseClick(/*[in,defaultvalue("LEFT")]*/LPCWSTR szButton, int nX = AU3_INTDEFAULT, int nY = AU3_INTDEFAULT, int nClicks = 1, int nSpeed = -1);
AU3_API int WINAPI AU3_MouseClickDrag(LPCWSTR szButton, int nX1, int nY1, int nX2, int nY2, int nSpeed = -1);
AU3_API void WINAPI AU3_MouseDown(/*[in,defaultvalue("LEFT")]*/LPCWSTR szButton);
AU3_API int WINAPI AU3_MouseGetCursor(void);
AU3_API void WINAPI AU3_MouseGetPos(LPPOINT lpPoint);
AU3_API int WINAPI AU3_MouseMove(int nX, int nY, int nSpeed = -1);
AU3_API void WINAPI AU3_MouseUp(/*[in,defaultvalue("LEFT")]*/LPCWSTR szButton);
AU3_API void WINAPI AU3_MouseWheel(LPCWSTR szDirection, int nClicks);

AU3_API int WINAPI AU3_Opt(LPCWSTR szOption, int nValue);


AU3_API unsigned int WINAPI AU3_PixelChecksum(LPRECT lpRect, int nStep = 1);
AU3_API int WINAPI AU3_PixelGetColor(int nX, int nY);
AU3_API void WINAPI AU3_PixelSearch(LPRECT lpRect, int nCol, /*default 0*/int nVar, /*default 1*/int nStep, LPPOINT pPointResult);
AU3_API int WINAPI AU3_ProcessClose(LPCWSTR szProcess);
AU3_API int WINAPI AU3_ProcessExists(LPCWSTR szProcess);
AU3_API int WINAPI AU3_ProcessSetPriority(LPCWSTR szProcess, int nPriority);
AU3_API int WINAPI AU3_ProcessWait(LPCWSTR szProcess, int nTimeout = 0);
AU3_API int WINAPI AU3_ProcessWaitClose(LPCWSTR szProcess, int nTimeout = 0);

AU3_API int WINAPI AU3_Run(LPCWSTR szProgram, /*[in,defaultvalue("")]*/LPCWSTR szDir, int nShowFlag = SW_SHOWNORMAL);
AU3_API int WINAPI AU3_RunWait(LPCWSTR szProgram, /*[in,defaultvalue("")]*/LPCWSTR szDir, int nShowFlag = SW_SHOWNORMAL);
AU3_API int WINAPI AU3_RunAs(LPCWSTR szUser, LPCWSTR szDomain, LPCWSTR szPassword, int nLogonFlag, LPCWSTR szProgram, /*[in,defaultvalue("")]*/LPCWSTR szDir, int nShowFlag = SW_SHOWNORMAL);
AU3_API int WINAPI AU3_RunAsWait(LPCWSTR szUser, LPCWSTR szDomain, LPCWSTR szPassword, int nLogonFlag, LPCWSTR szProgram, /*[in,defaultvalue("")]*/LPCWSTR szDir, int nShowFlag = SW_SHOWNORMAL);


AU3_API void WINAPI AU3_Send(LPCWSTR szSendText, int nMode = 0);
AU3_API int WINAPI AU3_Shutdown(int nFlags);
AU3_API void WINAPI AU3_Sleep(int nMilliseconds);
AU3_API int WINAPI AU3_StatusbarGetText(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, /*[in,defaultvalue(1)]*/int nPart, LPWSTR szStatusText, int nBufSize);
AU3_API int WINAPI AU3_StatusbarGetTextByHandle(HWND hWnd, /*[in,defaultvalue(1)]*/int nPart, LPWSTR szStatusText, int nBufSize);

AU3_API void WINAPI AU3_ToolTip(LPCWSTR szTip, int nX = AU3_INTDEFAULT, int nY = AU3_INTDEFAULT);

AU3_API int WINAPI AU3_WinActivate(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API int WINAPI AU3_WinActivateByHandle(HWND hWnd);
AU3_API int WINAPI AU3_WinActive(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API int WINAPI AU3_WinActiveByHandle(HWND hWnd);
AU3_API int WINAPI AU3_WinClose(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API int WINAPI AU3_WinCloseByHandle(HWND hWnd);
AU3_API int WINAPI AU3_WinExists(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API int WINAPI AU3_WinExistsByHandle(HWND hWnd);
AU3_API int WINAPI AU3_WinGetCaretPos(LPPOINT lpPoint);
AU3_API void WINAPI AU3_WinGetClassList(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPWSTR szRetText, int nBufSize);
AU3_API void WINAPI AU3_WinGetClassListByHandle(HWND hWnd, LPWSTR szRetText, int nBufSize);
AU3_API int WINAPI AU3_WinGetClientSize(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPRECT lpRect);
AU3_API int WINAPI AU3_WinGetClientSizeByHandle(HWND hWnd, LPRECT lpRect);
AU3_API HWND WINAPI AU3_WinGetHandle(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API void WINAPI AU3_WinGetHandleAsText(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPWSTR szRetText, int nBufSize);
AU3_API int WINAPI AU3_WinGetPos(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPRECT lpRect);
AU3_API int WINAPI AU3_WinGetPosByHandle(HWND hWnd, LPRECT lpRect);
AU3_API DWORD WINAPI AU3_WinGetProcess(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API DWORD WINAPI AU3_WinGetProcessByHandle(HWND hWnd);
AU3_API int WINAPI AU3_WinGetState(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API int WINAPI AU3_WinGetStateByHandle(HWND hWnd);
AU3_API void WINAPI AU3_WinGetText(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPWSTR szRetText, int nBufSize);
AU3_API void WINAPI AU3_WinGetTextByHandle(HWND hWnd, LPWSTR szRetText, int nBufSize);
AU3_API void WINAPI AU3_WinGetTitle(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPWSTR szRetText, int nBufSize);
AU3_API void WINAPI AU3_WinGetTitleByHandle(HWND hWnd, LPWSTR szRetText, int nBufSize);
AU3_API int WINAPI AU3_WinKill(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText);
AU3_API int WINAPI AU3_WinKillByHandle(HWND hWnd);
AU3_API int WINAPI AU3_WinMenuSelectItem(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, LPCWSTR szItem1, LPCWSTR szItem2, LPCWSTR szItem3, LPCWSTR szItem4, LPCWSTR szItem5, LPCWSTR szItem6, LPCWSTR szItem7, LPCWSTR szItem8);
AU3_API int WINAPI AU3_WinMenuSelectItemByHandle(HWND hWnd, LPCWSTR szItem1, LPCWSTR szItem2, LPCWSTR szItem3, LPCWSTR szItem4, LPCWSTR szItem5, LPCWSTR szItem6, LPCWSTR szItem7, LPCWSTR szItem8);
AU3_API void WINAPI AU3_WinMinimizeAll();
AU3_API void WINAPI AU3_WinMinimizeAllUndo();
AU3_API int WINAPI AU3_WinMove(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nX, int nY, int nWidth = -1, int nHeight = -1);
AU3_API int WINAPI AU3_WinMoveByHandle(HWND hWnd, int nX, int nY, int nWidth = -1, int nHeight = -1);
AU3_API int WINAPI AU3_WinSetOnTop(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nFlag);
AU3_API int WINAPI AU3_WinSetOnTopByHandle(HWND hWnd, int nFlag);
AU3_API int WINAPI AU3_WinSetState(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nFlags);
AU3_API int WINAPI AU3_WinSetStateByHandle(HWND hWnd, int nFlags);
AU3_API int WINAPI AU3_WinSetTitle(LPCWSTR szTitle,/*[in,defaultvalue("")]*/ LPCWSTR szText, LPCWSTR szNewTitle);
AU3_API int WINAPI AU3_WinSetTitleByHandle(HWND hWnd, LPCWSTR szNewTitle);
AU3_API int WINAPI AU3_WinSetTrans(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nTrans);
AU3_API int WINAPI AU3_WinSetTransByHandle(HWND hWnd, int nTrans);
AU3_API int WINAPI AU3_WinWait(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nTimeout = 0);
AU3_API int WINAPI AU3_WinWaitByHandle(HWND hWnd, int nTimeout);
AU3_API int WINAPI AU3_WinWaitActive(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nTimeout = 0);
AU3_API int WINAPI AU3_WinWaitActiveByHandle(HWND hWnd, int nTimeout);
AU3_API int WINAPI AU3_WinWaitClose(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nTimeout = 0);
AU3_API int WINAPI AU3_WinWaitCloseByHandle(HWND hWnd, int nTimeout);
AU3_API int WINAPI AU3_WinWaitNotActive(LPCWSTR szTitle, /*[in,defaultvalue("")]*/LPCWSTR szText, int nTimeout);
AU3_API int WINAPI AU3_WinWaitNotActiveByHandle(HWND hWnd, int nTimeout = 0);

///////////////////////////////////////////////////////////////////////////////


Любая программа MetaTrader 5, использующая библиотеку AutoItX, должна сначала импортировать ее функции. Для удобства мы создадим включаемый файл autoIt.mqh, единственной целью которого является импорт всех прототипов функций, предоставляемых библиотекой.

AutoIt использует возможности Windows API и работает исключительно с MS Windows. По этой причине библиотека AuotItX активно использует специфичные для Win32 API типы данных. Для обеспечения совместимости с MQL5 мы могли бы сами реализовать эти типы данных в MQL5, но в этом нет необходимости. Вместо этого мы можем использовать файл windef.mqh. Этот файл является одним из инструментов MetaQuotes для интеграции Win32 API в MQL5. Файл содержит большинство определений типов данных, используемых в Windows API.
Мы включим windef.mqh в наш файл autoit.mqh, который будет содержать все прототипы функций, импортированные из dll. Теперь autoit.mqh выглядит так:

//+------------------------------------------------------------------+
//|                                                       autoIt.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <WinAPI\windef.mqh>

#define LPPOINT POINT&
#define LPRECT  RECT&
#define WORD    ushort
#define DWORD   int
#define HWND    int

#import "AutoItX3_x64.dll"
void AU3_Init(void);
int AU3_error(void);
int AU3_AutoItSetOption(string, int);
void AU3_ClipGet(string&, int);
void AU3_ClipPut(string);
int AU3_ControlClick(string, string, string, string, int, int, int);
int AU3_ControlClickByHandle(HWND, HWND, string, int, int, int);
void AU3_ControlCommand(string, string, string, string, string, string&, int);
void AU3_ControlCommandByHandle(HWND, HWND, string, string, string&, int);
void AU3_ControlListView(string, string, string, string, string, string, string&, int);
void AU3_ControlListViewByHandle(HWND, HWND, string, string, string, string&, int);
int AU3_ControlDisable(string, string, string);
int AU3_ControlDisableByHandle(HWND, HWND);
int AU3_ControlEnable(string, string, string);
int AU3_ControlEnableByHandle(HWND, HWND);
int AU3_ControlFocus(string, string, string);
int AU3_ControlFocusByHandle(HWND, HWND);
void AU3_ControlGetFocus(string, string, string&, int);
void AU3_ControlGetFocusByHandle(HWND, string&, int);
HWND AU3_ControlGetHandle(HWND, string);
void AU3_ControlGetHandleAsText(string, string, string, string&, int);
int AU3_ControlGetPos(string, string, string, LPRECT);
int AU3_ControlGetPosByHandle(HWND, HWND, LPRECT);
void AU3_ControlGetText(string, string, string, string&, int);
void AU3_ControlGetTextByHandle(HWND, HWND, string&, int);
int AU3_ControlHide(string, string, string);
int AU3_ControlHideByHandle(HWND, HWND);
int AU3_ControlMove(string, string, string, int, int, int, int);
int AU3_ControlMoveByHandle(HWND, HWND, int, int, int, int);
int AU3_ControlSend(string, string, string, string, int);
int AU3_ControlSendByHandle(HWND, HWND, string, int);
int AU3_ControlSetText(string, string, string, string);
int AU3_ControlSetTextByHandle(HWND, HWND, string);
int AU3_ControlShow(string, string, string);
int AU3_ControlShowByHandle(HWND, HWND);
void AU3_ControlTreeView(string, string, string, string, string, string, string&, int);
void AU3_ControlTreeViewByHandle(HWND, HWND, string, string, string, string&, int);
void AU3_DriveMapAdd(string,  string, int, string, string, string&, int);
int AU3_DriveMapDel(string);
void AU3_DriveMapGet(string, string&, int);
int AU3_IsAdmin(void);
int AU3_MouseClick(string, int, int, int, int);
int AU3_MouseClickDrag(string, int, int, int, int, int);
void AU3_MouseDown(string);
int AU3_MouseGetCursor(void);
void AU3_MouseGetPos(LPPOINT);
int AU3_MouseMove(int, int, int);
void AU3_MouseUp(string);
void AU3_MouseWheel(string, int);
int AU3_Opt(string, int);
unsigned int AU3_PixelChecksum(LPRECT, int);
int AU3_PixelGetColor(int, int);
void AU3_PixelSearch(LPRECT, int, int, int, LPPOINT);
int AU3_ProcessClose(string);
int AU3_ProcessExists(string);
int AU3_ProcessSetPriority(string, int);
int AU3_ProcessWait(string, int);
int AU3_ProcessWaitClose(string, int);
int AU3_Run(string, string, int);
int AU3_RunWait(string, string, int);
int AU3_RunAs(string, string, string, int, string, string, int);
int AU3_RunAsWait(string, string, string, int, string, string, int);
void AU3_Send(string, int);
int AU3_Shutdown(int);
void AU3_Sleep(int);
int AU3_StatusbarGetText(string, string, int, string&, int);
int AU3_StatusbarGetTextByHandle(HWND, int, string&, int);
void AU3_ToolTip(string, int, int);
int AU3_WinActivate(string, string);
int AU3_WinActivateByHandle(HWND);
int AU3_WinActive(string, string);
int AU3_WinActiveByHandle(HWND);
int AU3_WinClose(string, string);
int AU3_WinCloseByHandle(HWND);
int AU3_WinExists(string, string);
int AU3_WinExistsByHandle(HWND);
int AU3_WinGetCaretPos(LPPOINT);
void AU3_WinGetClassList(string, string, string&, int);
void AU3_WinGetClassListByHandle(HWND, string&, int);
int AU3_WinGetClientSize(string, string, LPRECT);
int AU3_WinGetClientSizeByHandle(HWND, LPRECT);
HWND AU3_WinGetHandle(string, string);
void AU3_WinGetHandleAsText(string, string, string&, int);
int AU3_WinGetPos(string, string, LPRECT);
int AU3_WinGetPosByHandle(HWND, LPRECT);
DWORD AU3_WinGetProcess(string, string);
DWORD AU3_WinGetProcessByHandle(HWND);
int AU3_WinGetState(string, string);
int AU3_WinGetStateByHandle(HWND);
void AU3_WinGetText(string, string, string&, int);
void AU3_WinGetTextByHandle(HWND, string&, int);
void AU3_WinGetTitle(string, string, string&, int);
void AU3_WinGetTitleByHandle(HWND, string&, int);
int AU3_WinKill(string, string);
int AU3_WinKillByHandle(HWND);
int AU3_WinMenuSelectItem(string, string, string, string, string, string, string, string, string, string);
int AU3_WinMenuSelectItemByHandle(HWND, string, string, string, string, string, string, string, string);
void AU3_WinMinimizeAll();
void AU3_WinMinimizeAllUndo();
int AU3_WinMove(string, string, int, int, int, int);
int AU3_WinMoveByHandle(HWND, int, int, int, int);
int AU3_WinSetOnTop(string, string, int);
int AU3_WinSetOnTopByHandle(HWND, int);
int AU3_WinSetState(string, string, int);
int AU3_WinSetStateByHandle(HWND, int);
int AU3_WinSetTitle(string, string, string);
int AU3_WinSetTitleByHandle(HWND, string);
int AU3_WinSetTrans(string, string, int);
int AU3_WinSetTransByHandle(HWND, int);
int AU3_WinWait(string, string, int);
int AU3_WinWaitByHandle(HWND, int);
int AU3_WinWaitActive(string, string, int);
int AU3_WinWaitActiveByHandle(HWND, int);
int AU3_WinWaitClose(string, string, int);
int AU3_WinWaitCloseByHandle(HWND, int);
int AU3_WinWaitNotActive(string, string, int);
int AU3_WinWaitNotActiveByHandle(HWND, int);
#import


//+------------------------------------------------------------------+


Предварительные сведения об использовании
Использование библиотеки в MQL5 требует инициализации dll путем предварительного вызова функции AU3_Init. Это должно быть сделано до вызова любой из других импортированных функций. Сигнатуры функций аналогичны сигнатурам, используемым в скриптовом языке AutoIt. Это означает, что они имеют аналогичные параметры функций и типы возвращаемых значений. Знакомство со скриптовым языком AutoIt позволяет понять, как работают функции. Вся информация доступна в файле справки приложения.

Функции, возвращающие значение, возвращают положительные числовые значения, обычно 1 в случае успеха и 0 в случае неудачи. Функции void выводят в ссылку на строку или структуру. Для этих типов функций можно вызывать функцию AU3_error() для подтверждения ошибки. Функция также просто выводит либо строку с "0", либо пустую структуру в случае сбоя. Функции, которые выводят ссылки на строки, также задают соответствующий параметр размера буфера. Это означает, что длина буфера для строки, передаваемой по ссылке, должна быть явно установлена перед вызовом функции. В противном случае, если длина строкового буфера не задана, будет зафиксирована ошибка. Если выделенного размера буфера недостаточно, функция выводит символы, которые помещаются в указанное пространство, пропуская остальные и создавая усеченную строку. Место, необходимое для вывода, определить невозможно, поэтому об этой особенности нужно помнить. Чтобы установить длину буфера строки, мы можем использовать встроенную функцию MQL5 StringInit. Некоторые функции имеют в именах суффикс ...ByHandle, например AU3_WinCloseByHandle(). Эта функция делает то же самое, что и AU3_WinClose(), с той лишь разницей, что функция с суффиксом ByHandle работает, идентифицируя элемент управления или окно по его дескриптору. Использование этих функций предпочтительнее, так как это помогает при отладке, упрощая поиск ошибок, связанных с идентификацией правильного окна или элемента управления.


Начальный пример
Приведенный ниже пример демонстрирует использование функций AutoItX в MQL5. В приведенном ниже скрипте мы будем использовать функцию AU3_WinGetHandle для получения дескриптора главного окна терминала. Терминал можно однозначно идентифицировать по номеру активного аккаунта, отображаемому в строке заголовка окна.

//+------------------------------------------------------------------+
//|                                         TerminalUIComponents.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com "
#property version   "1.00"
#include<autoIt.mqh>


string sbuffer;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   AU3_Init();//initialize the library

   if(!StringInit(sbuffer,1000))// set buffer length for string
      Print("Failed to set string bufferlength with error - "+string(GetLastError()));

   HWND window_handle=AU3_WinGetHandle(IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)),"");// get the terminal's handle

   if(!window_handle)
      Print("Could not find main app window. Error is "+string(AU3_error()));

   AU3_WinGetClassListByHandle(window_handle,sbuffer,1000);// get classnames of all user interface componets of the terminal

   Print(sbuffer);

  }
//+------------------------------------------------------------------+



Получив дескриптор главного окна, мы можем получить больше информации о компонентах графического интерфейса, с которыми мы можем взаимодействовать, вызвав функцию AU3_WinGetClassListByHandle. Он вернет список строк, которые являются именами классов всех компонентов пользовательского интерфейса, связанных с предоставленным дескриптором окна.

Результат работы скрипта показан ниже

Результат работы TerminalUIComponents

Прежде чем перейти к более показательным примерам, создадим класс, обертывающий большинство импортированных функций AutoIt.


Класс CAutoit

CAutoit будет базовым классом для других классов, использующих библиотеку AutoItX. Он будет иметь единственное статическое свойство, указывающее, была ли вызвана библиотечная функция инициализации AU3_Init() или нет.

Единственное другое свойство m_buffer_size определяет длину буфера строк, используемых в вызовах метода.

//+------------------------------------------------------------------+
//|                                                   autoitbase.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com "
#include<autoIt.mqh>

enum ENUM_WINDOW_STATE
  {
   SW_HIDE=0,
   SW_SHOW,
   SW_MINIMIZE,
   SW_MAXIMIZE,
   SW_RESTORE
  };

//+------------------------------------------------------------------+
//| Class CAutoIt.                                                   |
//| Purpose:  class for working with autoit.                         |
//+------------------------------------------------------------------+

class CAutoIt
  {
private:
   int               m_buffer_size;                                     //string buffer size
   // --- static property common to all object instances
   static bool       m_initialized;                              //flag for checking initialization state



   //--- private methods
   void              ResetBuffer(string &buffer)      { StringFill(buffer,0); }

public:
   //--- constructor, destructor
                     CAutoIt(void);
                    ~CAutoIt(void);

   void              Init(void);
   //--- static method
   static bool       IsInitialized(void)             { return(m_initialized);     }
   //--- general purpose methods
   int               Error(void)                           { return (AU3_error());      }
   void              Sleep(const int milliseconds)         { AU3_Sleep(milliseconds);   }
   void              SetBufferLen(const int n_bufferlen)   { m_buffer_size=(n_bufferlen>0)?n_bufferlen:1000; }
   int               GetBufferLen(void)                    { return(m_buffer_size);     }

protected:
   int               Run(const string exefile,const string path,const ENUM_WINDOW_STATE w_state) { return(AU3_Run(exefile,path,int(w_state)));  }
   //--- system clipboard manipulation
   void              ClipGet(string & out);
   void              ClipPut(string copy);
   //---
   void              ControlPosition(HWND window_handle,HWND control_handle, LPRECT rect) { AU3_ControlGetPosByHandle(window_handle,control_handle, rect);}
   //--- methods for simulating clicks
   int               ControlRightClick(HWND window_handle, HWND control_handle,int number_of_clicks=1,int x=1,int y=1);
   int               ControlLeftClick(HWND window_handle, HWND control_handle,int number_of_clicks=1,int x=1,int y=1);
   //--- general Control Command method
   bool              ControlCommand(HWND window_handle, HWND control_handle, string command, string command_option);

   //--- methods for interacting with comboboxes, buttons,radio buttons
   string            GetCurrentComboBoxSelection(HWND window_handle, HWND control_handle);
   bool              IsControlEnabled(HWND window_handle, HWND control_handle);
   bool              IsControlVisible(HWND window_handle, HWND control_handle);
   int               EnableControl(HWND window_handle, HWND control_handle) { return(AU3_ControlEnableByHandle(window_handle,control_handle));}
   int               ShowControl(HWND window_handle, HWND control_handle)  { return(AU3_ControlShowByHandle(window_handle,control_handle));  }
   int               ControlFocus(HWND window_handle,HWND control_handle)  { return(AU3_ControlFocusByHandle(window_handle,control_handle)); }
   bool              IsButtonChecked(HWND window_handle, HWND control_handle);
   bool              CheckButton(HWND window_handle, HWND control_handle);
   bool              UnCheckButton(HWND window_handle, HWND control_handle);
   //--- methods for interacting with system32tab control
   string            GetCurrentTab(HWND window_handle, HWND control_handle);
   bool              TabRight(HWND window_handle, HWND control_handle);
   bool              TabLeft(HWND window_handle, HWND control_handle);
   long              TotalTabs(HWND window, HWND systab);
   //--- methods for interacting with syslistview32 control
   bool              ControlListView(HWND window_handle, HWND control_handle, string command, string command_option1, string command_option2);

   long              GetListViewItemCount(HWND window_handle, HWND control_handle);
   long              FindListViewItem(HWND window_handle, HWND control_handle, string find_item,string sub_item);
   string            GetSelectedListViewItem(HWND window_handle, HWND control_handle);
   long              GetSelectedListViewCount(HWND window_handle, HWND control_handle);
   long              GetListViewSubItemCount(HWND window_handle, HWND control_handle);
   string            GetListViewItemText(HWND window_handle, HWND control_handle,string item_index,string sub_item_index);
   bool              IsListViewItemSelected(HWND window_handle, HWND control_handle, string item_index);
   bool              SelectListViewItem(HWND window_handle, HWND control_handle, string from_item_index,string to_item_index);
   bool              SelectAllListViewItems(HWND window_handle, HWND control_handle);
   bool              ClearAllListViewItemSelections(HWND window_handle, HWND control_handle);
   bool              ViewChangeListView(HWND window_handle, HWND control_handle);
   //--- general methods for various types of controls
   HWND              ControlGetHandle(HWND window_handle, string control_id);
   string            ControlGetText(HWND window_handle, HWND control_handle);
   int               ControlSetText(HWND window_handle,HWND control_handle,string keys)   { return(AU3_ControlSetTextByHandle(window_handle,control_handle,keys));}
   int               ControlSend(HWND window_handle, HWND control_handle, string keys, int mode);
   bool              SetFocus(HWND window_handle,HWND control_handle) { return(AU3_ControlFocusByHandle(window_handle,control_handle)>0); }
   //--- methods for interacting with systreeview32 control
   bool              ControlTreeView(HWND window_handle, HWND control_handle, string command, string command_option1, string command_option2);
   long              GetTreeViewItemCount(HWND window_handle, HWND control_handle, string item);
   string            GetSelectedTreeViewItem(HWND window_handle, HWND control_handle);
   string            GetTreeViewItemText(HWND window_handle, HWND control_handle,string item);
   bool              SelectTreeViewItem(HWND window_handle, HWND control_handle,string item);
   //--- general methods for application windows, subwindows and dialogues
   int               WinClose(string window_title, string window_text) { return(AU3_WinClose(window_title,window_text)); }
   int               WinClose(HWND window_handle)                        { return(AU3_WinCloseByHandle(window_handle));    }
   string            WinGetText(HWND window_handle);
   int               WinMenuSelectItem(HWND window_handle, string menu_name_1, string menu_name_2, string menu_name_3, string menu_name_4, string menu_name_5, string menu_name_6, string menu_name_7, string menu_name_8);
   int               WinSetState(HWND window_handle, ENUM_WINDOW_STATE new_state);
   string            WinGetTitle(HWND window_handle);
   ENUM_WINDOW_STATE WinGetState(HWND window_handle)         { return((ENUM_WINDOW_STATE)AU3_WinGetStateByHandle(window_handle)); }
   HWND              WinGetHandle(string window_title, string window_text);
   void              WinGetPosition(HWND window_handle, LPRECT winpos)   { AU3_WinGetPosByHandle(window_handle,winpos);                       }
   void              WinClientSize(HWND window_handle, LPRECT winsize)    { AU3_WinGetClientSizeByHandle(window_handle,winsize);               }
   int               WinExists(HWND window_handle)                       { return(AU3_WinExistsByHandle(window_handle));                      }
   int               WinExists(string window_title, string window_text)   { return(AU3_WinExists(window_title,window_text));                   }
  };

bool CAutoIt::m_initialized=false;
//+------------------------------------------------------------------+
//| Constructor without parameters                                   |
//+------------------------------------------------------------------+
CAutoIt::CAutoIt(void): m_buffer_size(1000)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CAutoIt::~CAutoIt(void)
  {
  }

//+------------------------------------------------------------------+
//|Initializes AutoIt library                                        |
//+------------------------------------------------------------------+

void CAutoIt::Init(void)
  {
   if(!m_initialized)
     {
      AU3_Init();
      m_initialized=true;
     }

  }

//+------------------------------------------------------------------+
//|Reads and outputs textual contents of system clipboard            |
//+------------------------------------------------------------------+
void CAutoIt::ClipGet(string &out)
  {
   if(StringBufferLen(out)<m_buffer_size)
      StringInit(out,m_buffer_size);

   ResetBuffer(out);

   AU3_ClipGet(out,m_buffer_size);

  }
//+------------------------------------------------------------------+
//|Writes text to system clipboard                                   |
//+------------------------------------------------------------------+
void CAutoIt::ClipPut(string copy)
  {
   AU3_ClipPut(copy);
  }
//+------------------------------------------------------------------+
//|Simulates a left click                                            |
//+------------------------------------------------------------------+
int CAutoIt::ControlLeftClick(int window_handle,int control_handle,int number_of_clicks=1,int x=1,int y=1)
  {
   return(AU3_ControlClickByHandle(window_handle,control_handle,"left",number_of_clicks,x,y));
  }
//+------------------------------------------------------------------+
//|Simulates a right click                                           |
//+------------------------------------------------------------------+
int CAutoIt::ControlRightClick(int window_handle,int control_handle,int number_of_clicks=1,int x=1,int y=1)
  {
   return(AU3_ControlClickByHandle(window_handle,control_handle,"right",number_of_clicks,x,y));
  }
//+------------------------------------------------------------------+
//|Sends a command to a control                                      |
//+------------------------------------------------------------------+
bool CAutoIt::ControlCommand(int window_handle,int control_handle,string command,string command_option)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlCommandByHandle(window_handle,control_handle,command,command_option,m_buffer,m_buffer_size);

   if(StringFind(m_buffer,"0")>=0)
      return(false);

   return(true);
  }
//+------------------------------------------------------------------+
//|Retrieves text of currently selected option of a Combobox Control |
//+------------------------------------------------------------------+
string CAutoIt::GetCurrentComboBoxSelection(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlCommandByHandle(window_handle,control_handle,"GetCurrentSelection","",m_buffer,m_buffer_size);

   return(m_buffer);

  }
//+------------------------------------------------------------------+
//|Checks if a button is clickable                                   |
//+------------------------------------------------------------------+
bool CAutoIt::IsControlEnabled(int window_handle,int control_handle)
  {
   return(ControlCommand(window_handle,control_handle,"IsEnabled",""));
  }
//+------------------------------------------------------------------+
//|Checks if a control is visible                                    |
//+------------------------------------------------------------------+
bool CAutoIt::IsControlVisible(int window_handle,int control_handle)
  {
   return(ControlCommand(window_handle,control_handle,"IsVisible",""));

  }
//+------------------------------------------------------------------+
//|Checks if tickbox is ticked                                       |
//+------------------------------------------------------------------+
bool CAutoIt::IsButtonChecked(int window_handle,int control_handle)
  {

   return(ControlCommand(window_handle,control_handle,"IsChecked",""));

  }
//+------------------------------------------------------------------+
//| Ticks a tick box                                                 |
//+------------------------------------------------------------------+
bool CAutoIt::CheckButton(int window_handle,int control_handle)
  {
   return(ControlCommand(window_handle,control_handle,"Check",""));
  }
//+------------------------------------------------------------------+
//|Unticks a tick box                                                |
//+------------------------------------------------------------------+
bool CAutoIt::UnCheckButton(int window_handle,int control_handle)
  {

   return(ControlCommand(window_handle,control_handle,"UnCheck",""));
  }
//+------------------------------------------------------------------+
//|Gets text of currently enabled tab of SysTabControl32 control     |
//+------------------------------------------------------------------+
string CAutoIt::GetCurrentTab(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlCommandByHandle(window_handle,control_handle,"CurrentTab","",m_buffer,m_buffer_size);

   return(m_buffer);
  }
//+------------------------------------------------------------------+
//|Enables the tab to the left in SysTabControl32 control            |
//+------------------------------------------------------------------+
bool CAutoIt::TabLeft(int window_handle,int control_handle)
  {
   return(ControlCommand(window_handle,control_handle,"TabLeft",""));
  }
//+------------------------------------------------------------------+
//|Enables the tab to the right in SysTabControl32 control           |
//+------------------------------------------------------------------+
bool CAutoIt::TabRight(int window_handle,int control_handle)
  {
   return(ControlCommand(window_handle,control_handle,"TabRight",""));
  }
//+------------------------------------------------------------------+
//|Sends a command to a ListView32 control                           |
//+------------------------------------------------------------------+
bool CAutoIt::ControlListView(int window_handle,int control_handle,string command,string command_option1,string command_option2)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,command,command_option1,command_option2,m_buffer,m_buffer_size);

   if(StringFind(m_buffer,"1")>=0)
      return(true);

   return(false);
  }
//+------------------------------------------------------------------+
//|Gets number of items in ListView32 control                        |
//+------------------------------------------------------------------+
long CAutoIt::GetListViewItemCount(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,"GetItemCount","","",m_buffer,m_buffer_size);

   return(StringToInteger(m_buffer));
  }
//+-------------------------------------------------------------------------------------------+
//|retrievs the index of a ListView32 control item that matches find_item and sub_item strings|
//+-------------------------------------------------------------------------------------------+
long CAutoIt::FindListViewItem(int window_handle,int control_handle,string find_item,string sub_item)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,"FindItem",find_item,sub_item,m_buffer,m_buffer_size);

   return(StringToInteger(m_buffer));
  }
//+------------------------------------------------------------------+
//|gets the string list of all selected ListView32 control items     |
//+------------------------------------------------------------------+
string CAutoIt::GetSelectedListViewItem(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,"GetSelected","1","",m_buffer,m_buffer_size);

   return(m_buffer);
  }
//+------------------------------------------------------------------+
//|returns number of currently selected ListView32 control items     |
//+------------------------------------------------------------------+
long CAutoIt::GetSelectedListViewCount(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,"GetSelectedCount","","",m_buffer,m_buffer_size);

   return(StringToInteger(m_buffer));
  }
//+------------------------------------------------------------------+
//|gets number of sub items in ListView32 control                    |
//+------------------------------------------------------------------+
long CAutoIt::GetListViewSubItemCount(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,"GetSubItemCount","","",m_buffer,m_buffer_size);

   return(StringToInteger(m_buffer));
  }
//+---------------------------------------------------------------------+
//|returns text of single ListView32 control item referenced by an index|
//+---------------------------------------------------------------------+
string CAutoIt::GetListViewItemText(int window_handle,int control_handle,string item_index,string sub_item_index)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,"GetText",item_index,sub_item_index,m_buffer,m_buffer_size);

   return(m_buffer);
  }
//+------------------------------------------------------------------+
//|Checks if a certain ListView32 control item is selected           |
//+------------------------------------------------------------------+
bool CAutoIt::IsListViewItemSelected(int window_handle,int control_handle,string item_index)
  {
   return(ControlListView(window_handle,control_handle,"IsSelected",item_index,""));
  }
//+------------------------------------------------------------------+
//|Selects a certain ListView32 control                              |
//+------------------------------------------------------------------+
bool CAutoIt::SelectListViewItem(int window_handle,int control_handle,string from_item_index,string to_item_index)
  {
   return(ControlListView(window_handle,control_handle,"Select",from_item_index,to_item_index));
  }
//+------------------------------------------------------------------+
//|selects all listview items                                        |
//+------------------------------------------------------------------+
bool CAutoIt::SelectAllListViewItems(int window_handle,int control_handle)
  {
   return(ControlListView(window_handle,control_handle,"SelectAll","",""));
  }

//+------------------------------------------------------------------+
//|Deselects all currently selected item in a ListView32 control     |
//+------------------------------------------------------------------+
bool CAutoIt::ClearAllListViewItemSelections(int window_handle,int control_handle)
  {
   return(ControlListView(window_handle,control_handle,"SelectClear","",""));
  }
//+------------------------------------------------------------------+
//| Change listview control view to details mode                     |
//+------------------------------------------------------------------+
bool CAutoIt::ViewChangeListView(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlListViewByHandle(window_handle,control_handle,"ViewChange","list","",m_buffer,m_buffer_size);

   if(StringFind(m_buffer,"1")>=0)
      return(true);

   return(false);
  }
//+------------------------------------------------------------------+
//|returns handle for a control                                      |
//+------------------------------------------------------------------+
HWND CAutoIt::ControlGetHandle(int window_handle,string control_id)
  {
   return(AU3_ControlGetHandle(window_handle,control_id));
  }
//+------------------------------------------------------------------+
//|returns visible text from a control                               |
//+------------------------------------------------------------------+
string CAutoIt::ControlGetText(int window_handle,int control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlGetTextByHandle(window_handle,control_handle,m_buffer,m_buffer_size);

   return(m_buffer);
  }
//+------------------------------------------------------------------+
//|directs keyboard presses to a certain control                     |
//+------------------------------------------------------------------+
int CAutoIt::ControlSend(int window_handle,int control_handle,string keys,int mode)
  {
   return(AU3_ControlSendByHandle(window_handle,control_handle,keys,mode));
  }
//+------------------------------------------------------------------+
//|Sends a command to a TreeView32 control                           |
//+------------------------------------------------------------------+
bool CAutoIt::ControlTreeView(int window_handle,int control_handle,string command,string command_option1,string command_option2)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlTreeViewByHandle(window_handle,control_handle,command,command_option1,command_option2,m_buffer,m_buffer_size);

   if(StringFind(m_buffer,"1")>=0)
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------+
//|returns number of children on a a TreeView32 control item with selected index|
//+-----------------------------------------------------------------------------+
long CAutoIt::GetTreeViewItemCount(HWND window_handle, HWND control_handle, string item_index)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlTreeViewByHandle(window_handle,control_handle,"GetItemCount",item_index,"",m_buffer,m_buffer_size);

   return(StringToInteger(m_buffer));
  }
//+------------------------------------------------------------------+
//|gets index in string format of selected TreeView32 control item   |
//+------------------------------------------------------------------+
string CAutoIt::GetSelectedTreeViewItem(HWND window_handle, HWND control_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlTreeViewByHandle(window_handle,control_handle,"GetSelected","","",m_buffer,m_buffer_size);

   return(m_buffer);
  }
//+------------------------------------------------------------------+
//|retrieves the text of a a TreeView32 control item                 |
//+------------------------------------------------------------------+
string CAutoIt::GetTreeViewItemText(HWND window_handle, HWND control_handle,string item)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_ControlTreeViewByHandle(window_handle,control_handle,"GetText",item,"",m_buffer,m_buffer_size);

   return(m_buffer);
  }
//+------------------------------------------------------------------+
//|selects a a TreeView32 control item                               |
//+------------------------------------------------------------------+
bool CAutoIt::SelectTreeViewItem(HWND window_handle, HWND control_handle,string item)
  {
   return(ControlTreeView(window_handle,control_handle,"Select",item,""));
  }

//+------------------------------------------------------------------+
//|returns handle of window by its window title                      |
//+------------------------------------------------------------------+
HWND CAutoIt::WinGetHandle(string window_title, string window_text="")
  {
   return(AU3_WinGetHandle(window_title,window_text));
  }
//+------------------------------------------------------------------+
//|return all text that is visible within a window                   |
//+------------------------------------------------------------------+
string CAutoIt::WinGetText(HWND window_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_WinGetTextByHandle(window_handle,m_buffer,m_buffer_size);

   return(m_buffer);
  }
//+------------------------------------------------------------------+
//|Invokes a menu item of a window                                   |
//+------------------------------------------------------------------+
int CAutoIt::WinMenuSelectItem(HWND window_handle, string menu_name_1, string menu_name_2, string menu_name_3, string menu_name_4, string menu_name_5, string menu_name_6, string menu_name_7, string menu_name_8)
  {
   return(AU3_WinMenuSelectItemByHandle(window_handle,menu_name_1,menu_name_2,menu_name_3,menu_name_4,menu_name_5,menu_name_6,menu_name_7,menu_name_8));
  }
//+------------------------------------------------------------------+
//|Shows, hides, minimizes, maximizes, or restores a window          |
//+------------------------------------------------------------------+
int CAutoIt::WinSetState(HWND window_handle, ENUM_WINDOW_STATE new_state)
  {
   return(AU3_WinSetStateByHandle(window_handle,(int)new_state));
  }

//+------------------------------------------------------------------+
//|retrieves window title                                            |
//+------------------------------------------------------------------+
string CAutoIt::WinGetTitle(int window_handle)
  {
   string m_buffer;
   StringInit(m_buffer,m_buffer_size);

   AU3_WinGetTitleByHandle(window_handle,m_buffer,m_buffer_size);

   return(m_buffer);
  }

//+------------------------------------------------------------------+
//|Gets total number of tabs in systab32 control                     |
//+------------------------------------------------------------------+
long CAutoIt::TotalTabs(const int window,const int systab)
  {
   if(!WinExists(window))
     {
      return(0);
     }

   string index=GetCurrentTab(window,systab);
   long shift=-1;


   while(TabRight(window,systab))
     {
      index="";
      index=GetCurrentTab(window,systab);
     }

   shift=StringToInteger(index);


   return(shift);

  }
//+------------------------------------------------------------------+


Класс CTerminalController

Теперь создадим класс CTerminalController в файле terminalcontroller.mqh.
Сначала мы подключаем файл autoitbase.mqh, содержащий класс CAutoIt. Используем директивы препроцессора для определения строковых констант, идентифицирующих компоненты пользовательского интерфейса, с которыми будет работать класс.
Прежде чем указать класс, мы объявляем пользовательское перечисление, которое классифицирует программы MetaTrader 5 либо как скрипт, либо как советник.

//+------------------------------------------------------------------+
//|                                           terminalcontroller.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com "
#include<autoItbase.mqh>

#define JOURNAL_TAB              "SysListView321"
#define EXPERTS_TAB              "SysListView327"


#define NAVIGATOR                "SysTreeView321"
#define NAVIGATOR_TAB_BAR        "AfxWnd140su3"

#define PROGRAM_WINDOW_TAB       "SysTabControl321"

#define EXPERTS_WINDOW_LISTVIEW  "SysListView321"
#define EXPERTS_REMOVE_BUTTON    "Button2"

#define DLLCHECK_BUTTON          "Button1"
#define ALGOTRADECHECK_BUTTON    "Button4"
#define OK_BUTTON_1              "Button7"
#define OK_BUTTON_2              "Button3"
#define OK_BUTTON_3              "Button5"
#define LOAD_BUTTON              "Button1"
#define YES_BUTTON               "Button1"

#define FILENAME_EDIT            "Edit1"

#define OPTWINDOW_TAB            "SysTabControl321"
#define OPTWINDOW_CHECK_1        "Button1"
#define OPTWINDOW_CHECK_2        "Button2"
#define OPTWINDOW_CHECK_3        "Button6"
#define OPTWINDOW_OK             "Button7"
#define OPTWINDOW_EDIT           "Edit1"

#define EXPERTS_WINDOW           "Experts"

#define NAVIGATORWINDOW          "Navigator"
#define TOOLBOXWINDOW            "Toolbox"

#define FILEDIALOGE_WINDOW       "Open"
#define WINDOWTEXT_DLL           "Allow DLL"
#define WINDOWTEXT_EA            "Expert Advisor settings"
#define WINDOWTEXT_INPUT         "Input"

#define OPTWINDOW                "Options"
#define NOTIFICATIONS_TEXT       "Enable Push notifications"

#define ALERTWINDOW              "Alert"


#define MENU_TOOLS             "&Tools"
#define MENU_OPTIONS           "&Options"
#define MENU_WINDOW            "&Window"
#define MENU_TILEWINDOWS       "&Tile Windows"



#define MENU_VIEW              "&View"
#define MENU_NAVIGATOR         "&Navigator"

#define MENU_CHARTS            "&Charts"
#define MENU_EXPERTS_LIST      "&Expert List"



enum ENUM_TYPE_PROGRAM
  {
   ENUM_TYPE_EXPERT=0,//EXPERT_ADVISOR
   ENUM_TYPE_SCRIPT//SCRIPT
  };



Приватные свойства типа HWND — это дескрипторы окон и элементов управления, которые используются в классе.

//+------------------------------------------------------------------+
//|Class CTerminalController                                         |
//| Purpose: class for scripting the terminal                        |
//+------------------------------------------------------------------+


class CTerminalController:public CAutoIt
  {
private:

   HWND              m_terminal;                 //terminal window handle
   HWND              m_journaltab;               //journal tab handle
   HWND              m_expertstab;               //experts tab handle

   HWND              m_navigator;                //navigator systreeview
   HWND              m_navigatortabs;            //navigator tab header
   HWND              m_navigatorwindow;          //navigator window
   HWND              m_systab32;                 //handle to inputs tabbed control with in inputs dialogue
   HWND              m_program;                  //window handle for user inputs dialogue
   HWND              m_expwindow;                //handle to window showing list of experts
   HWND              m_explistview;              //list view control for experts list in m_expwindow
   long              m_chartid;                  //chart id
   long              m_accountNum;               //account number
   string            m_buffer;                   //string buffer

m_chartid относится к идентификатору графика, определенному вызовом MQL5-функции chartID().
m_accountNum – номер активного аккаунта, отображаемый в строке заголовка приложения терминала. Это значение будет использоваться, чтобы отличить одно активное окно терминала от другого.
В строку m_buffer будут записываться подробные сообщения об ошибках на случай, если что-то пойдет не так.

public:
   //default constructor
                     CTerminalController(void): m_terminal(0),
                     m_journaltab(0),
                     m_expertstab(0),
                     m_navigator(0),
                     m_navigatortabs(0),
                     m_navigatorwindow(0),
                     m_systab32(0),
                     m_program(0),
                     m_expwindow(0),
                     m_explistview(0),
                     m_chartid(-1),
                     m_buffer("")
     {
      m_accountNum=AccountInfoInteger(ACCOUNT_LOGIN);
      StringInit(m_buffer,1000);
     }
   //destructor
                    ~CTerminalController(void)
     {

     }


У CTerminalController будет один конструктор. Конструктор по умолчанию инициализирует m_accountNum с активным на данный момент аккаунтом, возвращаемым вызовом функции AccountInfoInteger.

Методы

//public methods
   string            GetErrorDetails(void)  {     return(m_buffer);      }
   bool              ChartExpertAdd(const ENUM_TYPE_PROGRAM p_type,const string ea_name,const string ea_relative_path,const string ea_set_file,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf);
   bool              ChartExpertRemove(const string ea_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf);
   bool              ChartExpertRemoveAll(void);

   void              CloseAlertDialogue(void);

   void              GetLastExpertsLogEntry(string &entry);
   void              GetLastExpertsLogEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry);
   void              GetLastJournalEntry(string &entry);
   void              GetLastJournalEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry);
   bool              Initialize(const long accountNumber=0);
   bool              SwitchToNewChart(string n_symbol, const ENUM_TIMEFRAMES n_tf);
   bool              SetNotificationId(const string MetaQuotes_id);
   bool              ToggleAutoTrading(void);


private:
   //helper methods
   void              SetErrorDetails(const string text);
   void              Findbranch(const long childrenOnBranch,const string index,const string pname,string& sbuffer);
   bool              Findprogram(const ENUM_TYPE_PROGRAM pr_type, const string program_name,const string relative_path,string& sbuffer);
   string            PeriodToString(const ENUM_TIMEFRAMES chart_tf);
   bool              RemoveExpert(const string program_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf);
   string            BrokerName(void);



  };


Для получения сообщений об ошибках используется GetErrorDetails(). Функция возвращает содержимое приватного члена m_buffer. С другой стороны SetErrorDetails() является приватным методом, который используется внутри для установки содержимого элемента строки m_buffer.

//+------------------------------------------------------------------+
//| Set error details                                                |
//+------------------------------------------------------------------+
void CTerminalController::SetErrorDetails(const string _text)
  {
   StringFill(m_buffer,0);

   m_buffer=_text;

   return;
  }


Метод Initialize() должен вызываться хотя бы один раз при инициализации программы перед любым другим методом. Метод имеет единственный параметр по умолчанию – accountNumber. Если аргумент не равен нулю, он сбрасывает значение свойства класса m_accountNum, которое, в свою очередь, сбрасывает все остальные свойства класса, запуская поиск главного окна терминала, идентифицированного свойством m_accountNum. Как только главное окно найдено, извлекаются все остальные управляющие дескрипторы, которые используются для установки оставшихся свойств класса.

//+------------------------------------------------------------------+
//| sets or resets window and control handles used in the class      |
//+------------------------------------------------------------------+
bool CTerminalController::Initialize(const long accountNumber=0)
  {
   Init();

   if(accountNumber>0 && accountNumber!=m_accountNum)
     {
      m_accountNum=accountNumber;
      m_program=m_expwindow=m_systab32=m_explistview=m_navigatorwindow=0;
      m_terminal=m_journaltab=m_expertstab=m_navigator=m_navigatortabs=0;
      m_chartid=0;
     }

   if(m_terminal)
      return(true);

   m_terminal=WinGetHandle(IntegerToString(m_accountNum));
   if(!m_terminal)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Terminal window "+IntegerToString(m_accountNum)+" not found");
      return(false);
     }

   m_journaltab=ControlGetHandle(m_terminal,JOURNAL_TAB);
   if(!m_journaltab)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+JOURNAL_TAB+" not found");
      return(false);
     }

   m_expertstab=ControlGetHandle(m_terminal,EXPERTS_TAB);
   if(!m_expertstab)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_TAB+" not found");
      return(false);
     }

   m_navigatorwindow=ControlGetHandle(m_terminal,NAVIGATORWINDOW);
   if(!m_navigatorwindow)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+NAVIGATORWINDOW+" not found");
      return(false);
     }


   m_navigator=ControlGetHandle(m_terminal,NAVIGATOR);
   if(!m_navigator)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+NAVIGATOR+" not found");
      return(false);
     }

   m_navigatortabs=ControlGetHandle(m_terminal,NAVIGATOR_TAB_BAR);
   if(!m_navigatortabs)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+NAVIGATOR_TAB_BAR+" not found");
      return(false);
     }

   StringInit(m_buffer,1000);

   return(true);
  }


ChartExpertAdd() используется для прикрепления советников или скриптов к графикам. Параметры функции:

  • p_type - тип программы: советник или скрипт,
  • ea_name - имя скрипта или советника в том виде, в каком оно отображается в окне навигатора. Расширения файлов не учитываются.
  • ea_relative_path - относительный путь к подпапке, которая содержит программу, заданную параметром ea_name, в папке Scripts или Experts. Например, советник Controls, показанный на рисунке ниже, содержится в папке с именем Controls, в подпапке Examples, которая, в свою очередь, находится в папке Experts, то есть его путь выглядит так: Examples\Controls. Если программа не находится ни в одной подпапке ни в папке Scripts, ни в папке Experts, то этот аргумент должен быть равен NULL или "".

    Навигатор


  • ea_set_file – имя файла .set. Для этого аргумента должно быть указано расширение файла .set.
  • Аргументы chart_symbol и chart tf определяют свойства графика, к которому будет добавлена программа.


Сначала вызывается метод SwitchToNewChart(). Этот метод ищет запрошенный график среди открытых в данный момент окон графиков. Если он найден, фокус устанавливается на него, в противном случае используется функция ChartOpen() для открытия нового графика. Метод также отвечает за установку свойства m_chartid класса.
Затем свойство m_chartid используется для проверки того, была ли программа уже добавлена на график. Если программа существует, то метод возвращает true.

//+------------------------------------------------------------------+
//|sets focus to existing or new chart window                        |
//+------------------------------------------------------------------+
bool CTerminalController::SwitchToNewChart(string n_symbol,const ENUM_TIMEFRAMES n_tf)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }

   string sarray[];

   StringToUpper(n_symbol);
   string newchartname=n_symbol+","+PeriodToString(n_tf);

   if(!WinMenuSelectItem(m_terminal,MENU_WINDOW,MENU_TILEWINDOWS,"","","","","",""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to select menu item: Tile Windows");
      return(false);
     }

   Sleep(200);

   string windowtext=WinGetText(m_terminal);

   int find=StringFind(windowtext,ChartSymbol(ChartFirst())+","+PeriodToString(ChartPeriod(ChartFirst())));

   string chartstring=StringSubstr(windowtext,find);

   StringReplace(chartstring,"\n\n","\n");

   int sarraysize=StringSplit(chartstring,StringGetCharacter("\n",0),sarray);

   bool found=false;
   int i;

   long prevChart=0;
   m_chartid=ChartFirst();


   for(i=0; i<sarraysize; i++,)
     {
      if(sarray[i]=="")
         continue;

      if(i>0)
         m_chartid=ChartNext(prevChart);

      if(StringFind(sarray[i],newchartname)>=0)
        {
         found=true;
         break;
        }

      prevChart=m_chartid;
     }

   ArrayFree(sarray);

   HWND frameview=0;

   if(found)
      frameview=ControlGetHandle(m_terminal,newchartname);
   else
      if(ChartOpen(n_symbol,n_tf))
         frameview=ControlGetHandle(m_terminal,newchartname);

   if(frameview)
     {
      if(!WinSetState(frameview,SW_MAXIMIZE))
        {

         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Could not maximize "+newchartname+" chart window");
         return(false);
        }
     }
   else
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Chart window "+newchartname+" not found");
      return(false);
     }


   return(true);
  }


Если программа не найдена, выполняется подготовка к поиску в области Навигатора. Если вкладка "Общие" панели "Навигатор" не отображается, она включена.
После включения вызывается метод Findprogram() для поиска программы MetaTrader 5 в элементе управления systreeview32. Метод получает поддержку рекурсивного метода FindBranch().

//+---------------------------------------------------------------------+
//|searches navigator for a program and outputs its location on the tree|
//+---------------------------------------------------------------------+
bool CTerminalController::Findprogram(const ENUM_TYPE_PROGRAM pr_type,const string program_name,const string relative_path,string &sbuffer)
  {

   long listsize=GetTreeViewItemCount(m_terminal,m_navigator,"#0");

   if(!listsize)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Root treeview control is empty");
      return(false);
     }
   else
     {
      string rpath="";

      if(relative_path=="")
         rpath=relative_path;
      else
        {
         if(StringFind(relative_path,"\\")==0)
            rpath=StringSubstr(relative_path,1);
         else
            rpath=relative_path;
         if(StringFind(rpath,"\\",StringLen(rpath)-1)<0)
            rpath+="\\";
        }

      switch(pr_type)
        {
         case ENUM_TYPE_EXPERT:
           {
            string fullpath="Expert Advisors\\"+rpath+program_name;
            Findbranch(listsize,"#0",fullpath,sbuffer);
            break;
           }
         case ENUM_TYPE_SCRIPT:
           {
            string fullpath="Scripts\\"+rpath+program_name;
            Findbranch(listsize,"#0",fullpath,sbuffer);
            break;
           }
         default:
            Findbranch(listsize,"#0","",sbuffer);
            break;
        }

     }

   if(sbuffer=="")
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Operation failed could not find "+program_name);
      return(false);
     }
   else
      return(true);

  }


FindBranch() просматривает элемент управления, а также создает идентификатор ссылки строки, который представляет собой путь к местоположению программ в элементе управления systreeview32. Идентификатор ссылки программы необходим, чтобы AutoIt можно было использовать для ее выбора и добавления на график.

//+-----------------------------------------------------------------------+
//|recursively searches systreeview for program and builds location string|
//+-----------------------------------------------------------------------+
void CTerminalController::Findbranch(const long childrenOnBranch,const string index,const string pname,string &sbuffer)
  {
   if(pname=="" ||  index=="")
     {
      sbuffer=index;
      return;
     }
   else
     {
      if(childrenOnBranch<=0)
         return;
      else
        {
         int find=StringFind(pname,"\\");

         long ss=0;
         long i;

         for(i=0; i<childrenOnBranch; i++)
           {

            ss=GetTreeViewItemCount(m_terminal,m_navigator,index+"|#"+IntegerToString(i));

            string search=(find>=0)?StringSubstr(pname,0,find):pname;

            string treebranchtext=GetTreeViewItemText(m_terminal,m_navigator,index+"|#"+IntegerToString(i));

            if(StringFind(treebranchtext,search)>=0 && StringLen(treebranchtext)==StringLen(search))
               break;

           }

         string npath=(find>=0)?StringSubstr(pname,find+1):"";

         Findbranch(ss,(i<childrenOnBranch)?index+"|#"+IntegerToString(i):"",npath,sbuffer);
        }
     }

   return;
  }


На этом этапе, если программа является советником и на графике уже есть другой советник, появится диалоговое окно с подтверждением замены работающего в данный момент советника.

Если запущенная программа имеет входные данные, цикл do... while перебирает вкладки, устанавливает файл .set, а также включает автоматическую торговлю и экспорт dll, если это необходимо.

Наконец, метод возвращает результат повторной проверки графика, чтобы программа подтвердила, была ли она добавлена на график.

//+------------------------------------------------------------------+
//| Adds EA,Script,Service to a chart                                |
//+------------------------------------------------------------------+
bool CTerminalController::ChartExpertAdd(const ENUM_TYPE_PROGRAM p_type,const string ea_name,const string ea_relative_path,const string ea_set_file,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf)
  {

   if(!SwitchToNewChart(chart_symbol,chart_tf))
     {
      return(false);
     }

   if(StringFind((p_type==ENUM_TYPE_EXPERT)?ChartGetString(m_chartid,CHART_EXPERT_NAME):ChartGetString(m_chartid,CHART_SCRIPT_NAME),ea_name)>=0)
     {
      return(true);
     }

   if(p_type==ENUM_TYPE_EXPERT && StringFind(ChartGetString(m_chartid,CHART_EXPERT_NAME),ChartGetString(ChartID(),CHART_EXPERT_NAME))>=0)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Cannot replace currenlty running Expert");
      return(false);
     }

   if(StringLen(ea_set_file)>0)
     {
      if(StringFind(ea_relative_path,".set")<0)
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Incorrect parameter setting, set file name should contain .set file extension");
         return(false);
        }
     }




   if(!IsControlVisible(m_terminal,m_navigator))
     {
      if(!IsControlVisible(m_terminal,m_navigatorwindow))
        {
         if(!WinMenuSelectItem(m_terminal,MENU_VIEW,MENU_NAVIGATOR,"","","","","",""))
           {
            SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to select menu item : Navigator");
            return(false);
           }
        }

      if(!ControlLeftClick(m_terminal,m_navigatortabs,1,5,5))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to click on Navigator, Common tab");
         return(false);
        }
     }

   string treepath="";

   if(!Findprogram(p_type,ea_name,ea_relative_path,treepath))
      return(false);


   if(!SelectTreeViewItem(m_terminal,m_navigator,treepath))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to select treeview item: "+treepath);
      return(false);
     }

   if(!ControlSend(m_terminal,m_navigator,"{SHIFTDOWN}{F10}{SHIFTUP}c",0))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Control Send failure");
      return(false);
     }

   Sleep(500);

   m_program=WinGetHandle(ea_name);

   HWND dialogue=WinGetHandle(BrokerName()+" - MetaTrader 5",ea_name);

   if(!m_program && !dialogue)
     {
      if(p_type==ENUM_TYPE_EXPERT && StringFind(ChartGetString(m_chartid,CHART_EXPERT_NAME),ea_name)<0)
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Could not add program to chart");
         return(false);
        }
      else
        {
         return(true);
        }
     }

   if(!m_program && dialogue)// replace current ea
     {
      HWND button = ControlGetHandle(dialogue,YES_BUTTON);

      if(button)
        {
         if(ControlLeftClick(dialogue,button))
           {
            Sleep(200);
            m_program=WinGetHandle(ea_name);
           }
         else
           {

            SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed left click on yes button");
            WinClose(dialogue);
            return(false);
           }
        }
      else
        {

         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Yes button for dialogue not found");
         WinClose(dialogue);
         return(false);
        }

     }

   m_systab32=ControlGetHandle(m_program,PROGRAM_WINDOW_TAB);
   if(!m_systab32)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+PROGRAM_WINDOW_TAB+ "not found");
      return(false);
     }


   long totaltabs=TotalTabs(m_program,m_systab32);
   bool algoenabled=false;
   bool inputmod=false;
   bool dllenabled=(totaltabs<3)?true:false;

   do
     {
      string windowtext=WinGetText(m_program);

      if(StringFind(windowtext,WINDOWTEXT_DLL)>=0)
        {
         StringFill(windowtext,0);
         HWND button=ControlGetHandle(m_program,DLLCHECK_BUTTON);

         if(!button)
           {
            WinClose(m_program);
              {
               SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"DLL check button not found");
               return(false);
              }
           }

         if(!IsButtonChecked(m_program,button))
           {
            if(CheckButton(m_program,button))
               dllenabled=true;
           }
         else
            dllenabled=true;

         if(dllenabled)
           {
            if(TabLeft(m_program,m_systab32))
               if(!TabLeft(m_program,m_systab32))
                 {
                  inputmod=true;
                 }
           }
         else
           {
            WinClose(m_program);
            SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Could not enable DLL loading");
            return(false);
           }
        }
      else
         if(StringFind(windowtext,WINDOWTEXT_EA)==0)
           {
            StringFill(windowtext,0);
            HWND button=ControlGetHandle(m_program,ALGOTRADECHECK_BUTTON);


            if(!button)
              {
               WinClose(m_program);
               SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Algo check button not found");
               return(false);
              }

            if(!IsButtonChecked(m_program,button))
              {
               if(CheckButton(m_program,button))
                  algoenabled=true;
              }
            else
               algoenabled=true;

            if(algoenabled)
              {
               if(!inputmod)
                 {
                  if(!TabRight(m_program,m_systab32))
                    {
                     HWND okbutton=ControlGetHandle(m_program,OK_BUTTON_3);
                     if(!okbutton)
                       {
                        WinClose(m_program);
                        SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed find Ok button");
                        return(false);
                       }

                     if(!ControlLeftClick(m_program,okbutton))
                       {
                        WinClose(m_program);
                        SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Left Click failure");
                        return(false);
                       }
                     else
                       {
                        break;
                       }
                    }
                 }
               else
                 {
                  HWND okbutton=ControlGetHandle(m_program,OK_BUTTON_3);
                  if(!okbutton)
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed find Ok button");
                     return(false);
                    }

                  if(!ControlLeftClick(m_program,okbutton))
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Left Click failure");
                     return(false);
                    }
                 }
              }
            else
              {
               WinClose(m_program);
               SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Unable to enable autotrading");
               return(false);
              }
           }
         else
            if(StringFind(windowtext,WINDOWTEXT_INPUT)==0)
              {
               StringFill(windowtext,0);

               HWND button=ControlGetHandle(m_program,LOAD_BUTTON);

               HWND okbutton=ControlGetHandle(m_program,(totaltabs>2)?OK_BUTTON_1:OK_BUTTON_2);

               if(!okbutton)
                 {
                  WinClose(m_program);
                  SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to find OK button");
                  return(false);
                 }



               if(StringLen(ea_set_file)>0)
                 {
                  if(!button)
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to find .set file load button");
                     return(false);
                    }

                  if(!ControlLeftClick(m_program,button))
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Left click failure");
                     return(false);
                    }

                  HWND filewin=0;
                  int try
                        =50;
                  while(!filewin && try
                           >0)
                       {
                        filewin=WinGetHandle(FILEDIALOGE_WINDOW);
                        try
                           --;
                        Sleep(200);
                       }

                  HWND filedit=ControlGetHandle(filewin,FILENAME_EDIT);

                  if(!filedit || !filewin)
                    {
                     if(!filedit)
                       {
                        if(filewin)
                           WinClose(filewin);
                       }
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" File dialogue failure");
                     return(false);
                    }

                  if(ControlSetText(filewin,filedit,""))
                    {
                     if(ControlSend(filewin,filedit,ea_set_file,1))
                       {
                        Sleep(200);
                        if(ControlSend(filewin,filedit,"{ENTER}",0))
                           Sleep(300);
                       }
                    }

                  if(WinExists(filewin))
                    {
                     WinClose(filewin);
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to set .set file through file dialogue");
                     return(false);
                    }
                 }

               inputmod=true;

               if(algoenabled)
                 {
                  if(ControlLeftClick(m_program,okbutton))
                     break;
                  else
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to click OK button");
                     return(false);
                    }
                 }
               else
                 {
                  if(!TabLeft(m_program,m_systab32))
                    {
                     if(ControlLeftClick(m_program,okbutton))
                        break;
                     else
                       {
                        WinClose(m_program);
                        SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to click OK button");
                        return(false);
                       }
                    }
                 }
              }
     }
   while(!inputmod||!dllenabled||!algoenabled);

   int try
         =50;

   while(WinExists(m_program) && try
            >0)
        {
         Sleep(500);
         try
            --;
        }

   if(WinExists(m_program) && !try)
     {
      WinClose(m_program);
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to add program to chart");
      return(false);
     }


   if(p_type==ENUM_TYPE_EXPERT && StringFind(ChartGetString(m_chartid,CHART_EXPERT_NAME),ea_name)<0)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Operation failed could not add program to chart");
      return(false);
     }

   return(true);

  }


ChartExpertRemove() удаляет с графика скрипт или советник. Это делается путем вызова диалогового окна "Эксперты" через главное меню приложения. Затем метод проходит по списку программ и находит соответствие по имени программы и свойствам графика (символу и таймфрейму).
Функция ChartExpertRemoveAll() удаляет все советники и скрипты, кроме программы, которая выполняет удаление.

//+------------------------------------------------------------------+
//|Removes EA,Script from a chart                                    |
//+------------------------------------------------------------------+
bool CTerminalController::ChartExpertRemove(const string ea_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf)
  {
   return(RemoveExpert(ea_name,chart_symbol,chart_tf));
  }


//+------------------------------------------------------------------+
//|Helper function detaches program from a chart                     |
//+------------------------------------------------------------------+
bool CTerminalController::RemoveExpert(const string program_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }


   if(!WinMenuSelectItem(m_terminal,MENU_CHARTS,MENU_EXPERTS_LIST,"","","","","",""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Menu selection failure.");
      return(false);
     }

   Sleep(200);

   m_expwindow=WinGetHandle(EXPERTS_WINDOW);
   if(!m_expwindow)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_WINDOW+" window not found");
      return(false);
     }

   m_explistview=ControlGetHandle(m_expwindow,EXPERTS_WINDOW_LISTVIEW);
   if(!m_explistview)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_WINDOW_LISTVIEW+" control not found");
      return(false);
     }

   HWND remove_button=ControlGetHandle(m_expwindow,EXPERTS_REMOVE_BUTTON);
   if(!remove_button)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Remove button not found");
      return(false);
     }

   long listsize=GetListViewItemCount(m_expwindow,m_explistview);

   if(listsize<=0)
     {
      return(true);
     }

   string newchartname=chart_symbol;
   StringToUpper(newchartname);
   newchartname+=","+PeriodToString(chart_tf);



   bool found=false;

   ClearAllListViewItemSelections(m_expwindow,m_explistview);

   for(int i=0; i<int(listsize); i++)
     {
      if(!SelectListViewItem(m_expwindow,m_explistview,IntegerToString(i),""))
         continue;

      string pname=GetListViewItemText(m_expwindow,m_explistview,IntegerToString(i),"0");

      string chartname=GetListViewItemText(m_expwindow,m_explistview,IntegerToString(i),"1");

      if(StringFind(pname,program_name)>=0 && StringFind(chartname,newchartname)>=0)
        {
         if(IsControlEnabled(m_expwindow,remove_button))
            if(ControlLeftClick(m_expwindow,remove_button))
               found=true;
        }

      if(found)
         break;

      ClearAllListViewItemSelections(m_expwindow,m_explistview);

     }

   WinClose(m_expwindow);

   return(found);
  }


Методы GetLastExpertsLogEntry() и GetLastJournalEntry() выводят в виде строки ссылку на последнюю запись, внесенную в логи советников и журнал соответственно.
Методы взаимодействуют либо с вкладками журнала, либо с вкладками экспертов и не читают из реальных файлов журнала. В основном они очищают текст из элемента управления listview32. Если вкладки были очищены вручную, методы не могут получить данные непосредственно из файлов журнала.

//+------------------------------------------------------------------+
//|Gets the last journal entry                                       |
//+------------------------------------------------------------------+
void CTerminalController::GetLastJournalEntry(string &entry)
  {
   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   long listsize=GetListViewItemCount(m_terminal,m_journaltab);

   if(listsize<=0)
      return;


   ClipPut("");


   if(!ClearAllListViewItemSelections(m_terminal,m_journaltab))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(!SelectListViewItem(m_terminal,m_journaltab,IntegerToString(listsize-1),""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select last listview item");
      return;
     }


   if(!ControlSend(m_terminal,m_journaltab,"{LCTRL down}c{LCTRL up}",0))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(entry);

   StringTrimRight(entry);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_journaltab);

   return;
  }
//+------------------------------------------------------------------+
//|Gets last entry made to experts log file                          |
//+------------------------------------------------------------------+
void CTerminalController::GetLastExpertsLogEntry(string &entry)
  {
   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   long listsize=GetListViewItemCount(m_terminal,m_expertstab);

   if(listsize<=0)
      return;

   ClipPut("");

   if(!ClearAllListViewItemSelections(m_terminal,m_expertstab))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(!SelectListViewItem(m_terminal,m_expertstab,IntegerToString(listsize-1),""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select last listview item");
      return;
     }


   if(!ControlSend(m_terminal,m_expertstab,"{LCTRL down}c{LCTRL up}",0))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(entry);

   StringTrimRight(entry);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_expertstab);

   return;
  }


Функции GetLastExpertsLogEntryByText() и GetLastJournalEntryByText() возвращают последнюю запись, совпадающую с параметром text_to_search_for. Функции начинают поиск с самой последней записи журнала в обратном направлении. Параметр max_items_to_search_in устанавливает максимальное количество записей журнала для работы. Например, если установлено значение 10, функция будет перебирать последние 10 записей журнала в поисках совпадений. Если для этого параметра установлено значение 0 или отрицательное число, функция перебирает все записи журнала.

//+------------------------------------------------------------------+
//|Gets last entry made to experts log file containg certain string  |
//+------------------------------------------------------------------+
void CTerminalController::GetLastExpertsLogEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry)
  {
   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   string items;
   string itemsarray[];

   long listsize=GetListViewItemCount(m_terminal,m_expertstab);

   if(listsize<=0)
      return;

   long stop=(max_items_to_search_in>0)? listsize-max_items_to_search_in:0;

   if(!ClearAllListViewItemSelections(m_terminal,m_expertstab))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(stop<=0)
     {
      if(!SelectAllListViewItems(m_terminal,m_expertstab))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select all listview items");
         return;
        }

      StringInit(items,int(listsize)*1000);
     }
   else
     {
      if(!SelectListViewItem(m_terminal,m_expertstab,IntegerToString(stop),IntegerToString(listsize-1)))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select "+IntegerToString(stop)+" listview items");
         return;
        }

      StringInit(items,int(stop)*1000);
     }


   ClipPut("");

   if(!ControlSend(m_terminal,m_expertstab,"{LCTRL down}c",0))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(items);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_expertstab);

   int a_size=StringSplit(items,StringGetCharacter("\n",0),itemsarray);

   for(int i=(a_size-1); i>=0; i--)
     {
      if(itemsarray[i]=="")
         continue;

      if(StringFind(itemsarray[i],text_to_search_for,24)>=24)
        {
         entry=itemsarray[i];
         StringTrimRight(entry);
         break;;
        }
     }

   ArrayFree(itemsarray);


   return;

  }


//+------------------------------------------------------------------+
//|Gets last entry made to journal containing certain string         |
//+------------------------------------------------------------------+
void CTerminalController::GetLastJournalEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry)
  {

   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   string items;
   string itemsarray[];

   long listsize=GetListViewItemCount(m_terminal,m_journaltab);

   if(listsize<=0)
      return;

   long stop=(max_items_to_search_in>0)? listsize-max_items_to_search_in:0;

   if(!ClearAllListViewItemSelections(m_terminal,m_journaltab))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(stop<=0)
     {
      if(!SelectAllListViewItems(m_terminal,m_journaltab))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select all listview items");
         return;
        }

      StringInit(items,int(listsize)*1000);
     }
   else
     {
      if(!SelectListViewItem(m_terminal,m_journaltab,IntegerToString(stop),IntegerToString(listsize-1)))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select "+IntegerToString(stop)+" listview items");
         return;
        }

      StringInit(items,int(stop)*1000);
     }


   ClipPut("");

   if(!ControlSend(m_terminal,m_journaltab,"{LCTRL down}c",0))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(items);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_journaltab);

   int a_size=StringSplit(items,StringGetCharacter("\n",0),itemsarray);

   for(int i=(a_size-1); i>=0; i--)
     {
      if(itemsarray[i]=="")
         continue;

      if(StringFind(itemsarray[i],text_to_search_for,24)>=24)
        {
         entry=itemsarray[i];
         StringTrimRight(entry);
         break;;
        }
     }

   ArrayFree(itemsarray);


   return;

  }


Метод SetNotificationId() является возвратом к первоначальной демонстрации этой концепции. Он принимает в качестве строкового параметра максимум четыре MetaQuotes ID.

//+------------------------------------------------------------------+
//|set the MetaQuotes id                                             |
//+------------------------------------------------------------------+
bool CTerminalController::SetNotificationId(const string MetaQuotes_id)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }

   string itemsarray[];

   int totalids=StringSplit(MetaQuotes_id,StringGetCharacter(",",0),itemsarray);

   if(totalids>4)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Invalid parameter settings, Only maximum of 4 MetaQuotes ID's allowed");
      return(false);
     }

   HWND opt_window,opt_tab,edit,ok,checkbutton1,checkbutton2,checkbutton3;

   if(!WinMenuSelectItem(m_terminal,MENU_TOOLS,MENU_OPTIONS,"","","","","",""))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Menu selection failure.");
      return(false);
     }

   Sleep(200);

   opt_window=WinGetHandle(OPTWINDOW);
   if(!opt_window)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Options Window not found.");
      return(false);
     }

   opt_tab=ControlGetHandle(opt_window,OPTWINDOW_TAB);
   if(!opt_tab)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Options Window tab control not found");
      WinClose(opt_window);
      return(false);
     }

   RECT wnsize;

   WinClientSize(opt_window,wnsize);

   int y=5;
   int x=5;

   string wintext=WinGetText(opt_window);
   while(StringFind(wintext,NOTIFICATIONS_TEXT)<0)
     {
      if(x<wnsize.right && ControlLeftClick(opt_window,opt_tab,1,x,5))
        {
         wintext=WinGetText(opt_window);
         x+=y;
        }
      else
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Notification settings tab not found");
         WinClose(opt_window);
         return(false);
        }
     }

   checkbutton1=ControlGetHandle(opt_window,OPTWINDOW_CHECK_1);
   if(!checkbutton1)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Enable Notifications check button not found");
      WinClose(opt_window);
      return(false);
     }

   checkbutton2=ControlGetHandle(opt_window,OPTWINDOW_CHECK_2);
   if(!checkbutton2)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Enable Notifications from terminal check button not found");
      WinClose(opt_window);
      return(false);
     }

   checkbutton3=ControlGetHandle(opt_window,OPTWINDOW_CHECK_3);
   if(!checkbutton3)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Enable Notifications from trade server check button not found");
      WinClose(opt_window);
      return(false);
     }

   ok=ControlGetHandle(opt_window,OPTWINDOW_OK);
   if(!ok)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"OK button not found");
      WinClose(opt_window);
      return(false);
     }

   edit=ControlGetHandle(opt_window,OPTWINDOW_EDIT);
   if(!checkbutton1)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Notification Ids edit control not found");
      WinClose(opt_window);
      return(false);
     }

   string current_id=ControlGetText(opt_window,edit);

   if(!StringCompare(current_id,MetaQuotes_id))
     {
      WinClose(opt_window);
      return(true);
     }

   if(!IsButtonChecked(opt_window,checkbutton1))
      CheckButton(opt_window,checkbutton1);

   if(IsControlEnabled(opt_window,checkbutton2) && !IsButtonChecked(opt_window,checkbutton2))
      CheckButton(opt_window,checkbutton2);

   if(IsControlEnabled(opt_window,checkbutton3) && !IsButtonChecked(opt_window,checkbutton3))
      CheckButton(opt_window,checkbutton3);

   if(ControlSetText(opt_window,edit,""))
      ControlSend(opt_window,edit,MetaQuotes_id,1);

   if(ControlLeftClick(opt_window,ok))
      Sleep(200);

   if(WinExists(opt_window))
      WinClose(opt_window);

   return(true);

  }

При вызове CloseAlertDialogue() ищет любое всплывающее окно с предупреждением и закрывается.

//+------------------------------------------------------------------+
//| closes any pop up alert window                                   |
//+------------------------------------------------------------------+
void CTerminalController::CloseAlertDialogue(void)
  {
   static datetime lastcheck;

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   if(WinExists(ALERTWINDOW,""))
     {
      string alertmessage;
      StringInit(alertmessage,200);

      GetLastExpertsLogEntryByText(ALERTWINDOW,0,alertmessage);

      if(StringLen(alertmessage)>0)
        {
         datetime check=StringToTime(StringSubstr(alertmessage,0,24));
         if(check>lastcheck && check>iTime(NULL,PERIOD_D1,0))
           {
            WinClose(ALERTWINDOW,"");
            lastcheck=check;
           }
        }

     }

   return;
  }

Ниже показан код всего класса

//+------------------------------------------------------------------+
//|                                           terminalcontroller.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com "
#include<autoItbase.mqh>

#define JOURNAL_TAB              "SysListView321"
#define EXPERTS_TAB              "SysListView327"


#define NAVIGATOR                "SysTreeView321"
#define NAVIGATOR_TAB_BAR        "AfxWnd140su3"

#define PROGRAM_WINDOW_TAB       "SysTabControl321"

#define EXPERTS_WINDOW_LISTVIEW  "SysListView321"
#define EXPERTS_REMOVE_BUTTON    "Button2"

#define DLLCHECK_BUTTON          "Button1"
#define ALGOTRADECHECK_BUTTON    "Button4"
#define OK_BUTTON_1              "Button7"
#define OK_BUTTON_2              "Button3"
#define OK_BUTTON_3              "Button5"
#define LOAD_BUTTON              "Button1"
#define YES_BUTTON               "Button1"

#define FILENAME_EDIT            "Edit1"

#define OPTWINDOW_TAB            "SysTabControl321"
#define OPTWINDOW_CHECK_1        "Button1"
#define OPTWINDOW_CHECK_2        "Button2"
#define OPTWINDOW_CHECK_3        "Button6"
#define OPTWINDOW_OK             "Button7"
#define OPTWINDOW_EDIT           "Edit1"

#define EXPERTS_WINDOW           "Experts"

#define NAVIGATORWINDOW          "Navigator"
#define TOOLBOXWINDOW            "Toolbox"

#define FILEDIALOGE_WINDOW       "Open"
#define WINDOWTEXT_DLL           "Allow DLL"
#define WINDOWTEXT_EA            "Expert Advisor settings"
#define WINDOWTEXT_INPUT         "Input"

#define OPTWINDOW                "Options"
#define NOTIFICATIONS_TEXT       "Enable Push notifications"

#define ALERTWINDOW              "Alert"


#define MENU_TOOLS             "&Tools"
#define MENU_OPTIONS           "&Options"
#define MENU_WINDOW            "&Window"
#define MENU_TILEWINDOWS       "&Tile Windows"



#define MENU_VIEW              "&View"
#define MENU_NAVIGATOR         "&Navigator"

#define MENU_CHARTS            "&Charts"
#define MENU_EXPERTS_LIST      "&Expert List"



enum ENUM_TYPE_PROGRAM
  {
   ENUM_TYPE_EXPERT=0,//EXPERT_ADVISOR
   ENUM_TYPE_SCRIPT//SCRIPT
  };


//+------------------------------------------------------------------+
//|Class CTerminalController                                         |
//| Purpose: class for scripting the terminal                        |
//+------------------------------------------------------------------+

class CTerminalController:public CAutoIt
  {
private:

   HWND              m_terminal;                 //terminal window handle
   HWND              m_journaltab;               //journal tab handle
   HWND              m_expertstab;               //experts tab handle

   HWND              m_navigator;                //navigator systreeview
   HWND              m_navigatortabs;            //navigator tab header
   HWND              m_navigatorwindow;          //navigator window
   HWND              m_systab32;                 //handle to inputs tabbed control with in inputs dialogue
   HWND              m_program;                  //window handle for user inputs dialogue
   HWND              m_expwindow;                //handle to window showing list of experts
   HWND              m_explistview;              //list view control for experts list in m_expwindow
   long              m_chartid;                  //chart id
   long              m_accountNum;               //account number
   string            m_buffer;                   //string buffer

public:
   //default constructor
                     CTerminalController(void): m_terminal(0),
                     m_journaltab(0),
                     m_expertstab(0),
                     m_navigator(0),
                     m_navigatortabs(0),
                     m_navigatorwindow(0),
                     m_systab32(0),
                     m_program(0),
                     m_expwindow(0),
                     m_explistview(0),
                     m_chartid(-1),
                     m_buffer("")
     {
      m_accountNum=AccountInfoInteger(ACCOUNT_LOGIN);
      StringInit(m_buffer,1000);
     }
   //destructor
                    ~CTerminalController(void)
     {

     }

   //public methods
   string            GetErrorDetails(void)  {     return(m_buffer);      }
   bool              ChartExpertAdd(const ENUM_TYPE_PROGRAM p_type,const string ea_name,const string ea_relative_path,const string ea_set_file,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf);
   bool              ChartExpertRemove(const string ea_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf);
   bool              ChartExpertRemoveAll(void);

   void              CloseAlertDialogue(void);

   void              GetLastExpertsLogEntry(string &entry);
   void              GetLastExpertsLogEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry);
   void              GetLastJournalEntry(string &entry);
   void              GetLastJournalEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry);
   bool              Initialize(const long accountNumber=0);
   bool              SwitchToNewChart(string n_symbol, const ENUM_TIMEFRAMES n_tf);
   bool              SetNotificationId(const string MetaQuotes_id);
   bool              ToggleAutoTrading(void);


private:
   //helper methods
   void              SetErrorDetails(const string text);
   void              Findbranch(const long childrenOnBranch,const string index,const string pname,string& sbuffer);
   bool              Findprogram(const ENUM_TYPE_PROGRAM pr_type, const string program_name,const string relative_path,string& sbuffer);
   string            PeriodToString(const ENUM_TIMEFRAMES chart_tf);
   bool              RemoveExpert(const string program_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf);
   string            BrokerName(void);



  };

//+------------------------------------------------------------------+
//| sets or resets window and control handles used in the class      |
//+------------------------------------------------------------------+
bool CTerminalController::Initialize(const long accountNumber=0)
  {
   Init();

   if(accountNumber>0 && accountNumber!=m_accountNum)
     {
      m_accountNum=accountNumber;
      m_program=m_expwindow=m_systab32=m_explistview=m_navigatorwindow=0;
      m_terminal=m_journaltab=m_expertstab=m_navigator=m_navigatortabs=0;
      m_chartid=0;
     }

   if(m_terminal)
      return(true);

   m_terminal=WinGetHandle(IntegerToString(m_accountNum));
   if(!m_terminal)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Terminal window "+IntegerToString(m_accountNum)+" not found");
      return(false);
     }

   m_journaltab=ControlGetHandle(m_terminal,JOURNAL_TAB);
   if(!m_journaltab)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+JOURNAL_TAB+" not found");
      return(false);
     }

   m_expertstab=ControlGetHandle(m_terminal,EXPERTS_TAB);
   if(!m_expertstab)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_TAB+" not found");
      return(false);
     }

   m_navigatorwindow=ControlGetHandle(m_terminal,NAVIGATORWINDOW);
   if(!m_navigatorwindow)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+NAVIGATORWINDOW+" not found");
      return(false);
     }


   m_navigator=ControlGetHandle(m_terminal,NAVIGATOR);
   if(!m_navigator)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+NAVIGATOR+" not found");
      return(false);
     }

   m_navigatortabs=ControlGetHandle(m_terminal,NAVIGATOR_TAB_BAR);
   if(!m_navigatortabs)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+NAVIGATOR_TAB_BAR+" not found");
      return(false);
     }

   StringInit(m_buffer,1000);

   return(true);
  }

//+------------------------------------------------------------------+
//|sets focus to existing or new chart window                        |
//+------------------------------------------------------------------+
bool CTerminalController::SwitchToNewChart(string n_symbol,const ENUM_TIMEFRAMES n_tf)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }

   string sarray[];

   StringToUpper(n_symbol);
   string newchartname=n_symbol+","+PeriodToString(n_tf);

   if(!WinMenuSelectItem(m_terminal,MENU_WINDOW,MENU_TILEWINDOWS,"","","","","",""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to select menu item: Tile Windows");
      return(false);
     }

   Sleep(200);

   string windowtext=WinGetText(m_terminal);

   int find=StringFind(windowtext,ChartSymbol(ChartFirst())+","+PeriodToString(ChartPeriod(ChartFirst())));

   string chartstring=StringSubstr(windowtext,find);

   StringReplace(chartstring,"\n\n","\n");

   int sarraysize=StringSplit(chartstring,StringGetCharacter("\n",0),sarray);

   bool found=false;
   int i;

   long prevChart=0;
   m_chartid=ChartFirst();


   for(i=0; i<sarraysize; i++,)
     {
      if(sarray[i]=="")
         continue;

      if(i>0)
         m_chartid=ChartNext(prevChart);

      if(StringFind(sarray[i],newchartname)>=0)
        {
         found=true;
         break;
        }

      prevChart=m_chartid;
     }

   ArrayFree(sarray);

   HWND frameview=0;

   if(found)
      frameview=ControlGetHandle(m_terminal,newchartname);
   else
      if(ChartOpen(n_symbol,n_tf))
         frameview=ControlGetHandle(m_terminal,newchartname);

   if(frameview)
     {
      if(!WinSetState(frameview,SW_MAXIMIZE))
        {

         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Could not maximize "+newchartname+" chart window");
         return(false);
        }
     }
   else
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Chart window "+newchartname+" not found");
      return(false);
     }


   return(true);
  }
//+------------------------------------------------------------------+
//| Adds EA,Script,Service to a chart                                |
//+------------------------------------------------------------------+
bool CTerminalController::ChartExpertAdd(const ENUM_TYPE_PROGRAM p_type,const string ea_name,const string ea_relative_path,const string ea_set_file,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf)
  {

   if(!SwitchToNewChart(chart_symbol,chart_tf))
     {
      return(false);
     }

   if(StringFind((p_type==ENUM_TYPE_EXPERT)?ChartGetString(m_chartid,CHART_EXPERT_NAME):ChartGetString(m_chartid,CHART_SCRIPT_NAME),ea_name)>=0)
     {
      return(true);
     }

   if(p_type==ENUM_TYPE_EXPERT && StringFind(ChartGetString(m_chartid,CHART_EXPERT_NAME),ChartGetString(ChartID(),CHART_EXPERT_NAME))>=0)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Cannot replace currenlty running Expert");
      return(false);
     }

   if(StringLen(ea_set_file)>0)
     {
      if(StringFind(ea_relative_path,".set")<0)
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Incorrect parameter setting, set file name should contain .set file extension");
         return(false);
        }
     }




   if(!IsControlVisible(m_terminal,m_navigator))
     {
      if(!IsControlVisible(m_terminal,m_navigatorwindow))
        {
         if(!WinMenuSelectItem(m_terminal,MENU_VIEW,MENU_NAVIGATOR,"","","","","",""))
           {
            SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to select menu item : Navigator");
            return(false);
           }
        }

      if(!ControlLeftClick(m_terminal,m_navigatortabs,1,5,5))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to click on Navigator, Common tab");
         return(false);
        }
     }

   string treepath="";

   if(!Findprogram(p_type,ea_name,ea_relative_path,treepath))
      return(false);


   if(!SelectTreeViewItem(m_terminal,m_navigator,treepath))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to select treeview item: "+treepath);
      return(false);
     }

   if(!ControlSend(m_terminal,m_navigator,"{SHIFTDOWN}{F10}{SHIFTUP}c",0))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Control Send failure");
      return(false);
     }

   Sleep(500);

   m_program=WinGetHandle(ea_name);

   HWND dialogue=WinGetHandle(BrokerName()+" - MetaTrader 5",ea_name);

   if(!m_program && !dialogue)
     {
      if(p_type==ENUM_TYPE_EXPERT && StringFind(ChartGetString(m_chartid,CHART_EXPERT_NAME),ea_name)<0)
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Could not add program to chart");
         return(false);
        }
      else
        {
         return(true);
        }
     }

   if(!m_program && dialogue)// replace current ea
     {
      HWND button = ControlGetHandle(dialogue,YES_BUTTON);

      if(button)
        {
         if(ControlLeftClick(dialogue,button))
           {
            Sleep(200);
            m_program=WinGetHandle(ea_name);
           }
         else
           {

            SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed left click on yes button");
            WinClose(dialogue);
            return(false);
           }
        }
      else
        {

         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Yes button for dialogue not found");
         WinClose(dialogue);
         return(false);
        }

     }

   m_systab32=ControlGetHandle(m_program,PROGRAM_WINDOW_TAB);
   if(!m_systab32)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+PROGRAM_WINDOW_TAB+ "not found");
      return(false);
     }


   long totaltabs=TotalTabs(m_program,m_systab32);
   bool algoenabled=false;
   bool inputmod=false;
   bool dllenabled=(totaltabs<3)?true:false;

   do
     {
      string windowtext=WinGetText(m_program);

      if(StringFind(windowtext,WINDOWTEXT_DLL)>=0)
        {
         StringFill(windowtext,0);
         HWND button=ControlGetHandle(m_program,DLLCHECK_BUTTON);

         if(!button)
           {
            WinClose(m_program);
              {
               SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"DLL check button not found");
               return(false);
              }
           }

         if(!IsButtonChecked(m_program,button))
           {
            if(CheckButton(m_program,button))
               dllenabled=true;
           }
         else
            dllenabled=true;

         if(dllenabled)
           {
            if(TabLeft(m_program,m_systab32))
               if(!TabLeft(m_program,m_systab32))
                 {
                  inputmod=true;
                 }
           }
         else
           {
            WinClose(m_program);
            SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Could not enable DLL loading");
            return(false);
           }
        }
      else
         if(StringFind(windowtext,WINDOWTEXT_EA)==0)
           {
            StringFill(windowtext,0);
            HWND button=ControlGetHandle(m_program,ALGOTRADECHECK_BUTTON);


            if(!button)
              {
               WinClose(m_program);
               SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Algo check button not found");
               return(false);
              }

            if(!IsButtonChecked(m_program,button))
              {
               if(CheckButton(m_program,button))
                  algoenabled=true;
              }
            else
               algoenabled=true;

            if(algoenabled)
              {
               if(!inputmod)
                 {
                  if(!TabRight(m_program,m_systab32))
                    {
                     HWND okbutton=ControlGetHandle(m_program,OK_BUTTON_3);
                     if(!okbutton)
                       {
                        WinClose(m_program);
                        SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed find Ok button");
                        return(false);
                       }

                     if(!ControlLeftClick(m_program,okbutton))
                       {
                        WinClose(m_program);
                        SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Left Click failure");
                        return(false);
                       }
                     else
                       {
                        break;
                       }
                    }
                 }
               else
                 {
                  HWND okbutton=ControlGetHandle(m_program,OK_BUTTON_3);
                  if(!okbutton)
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed find Ok button");
                     return(false);
                    }

                  if(!ControlLeftClick(m_program,okbutton))
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Left Click failure");
                     return(false);
                    }
                 }
              }
            else
              {
               WinClose(m_program);
               SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Unable to enable autotrading");
               return(false);
              }
           }
         else
            if(StringFind(windowtext,WINDOWTEXT_INPUT)==0)
              {
               StringFill(windowtext,0);

               HWND button=ControlGetHandle(m_program,LOAD_BUTTON);

               HWND okbutton=ControlGetHandle(m_program,(totaltabs>2)?OK_BUTTON_1:OK_BUTTON_2);

               if(!okbutton)
                 {
                  WinClose(m_program);
                  SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to find OK button");
                  return(false);
                 }



               if(StringLen(ea_set_file)>0)
                 {
                  if(!button)
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to find .set file load button");
                     return(false);
                    }

                  if(!ControlLeftClick(m_program,button))
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Left click failure");
                     return(false);
                    }

                  HWND filewin=0;
                  int try
                        =50;
                  while(!filewin && try
                           >0)
                       {
                        filewin=WinGetHandle(FILEDIALOGE_WINDOW);
                        try
                           --;
                        Sleep(200);
                       }

                  HWND filedit=ControlGetHandle(filewin,FILENAME_EDIT);

                  if(!filedit || !filewin)
                    {
                     if(!filedit)
                       {
                        if(filewin)
                           WinClose(filewin);
                       }
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" File dialogue failure");
                     return(false);
                    }

                  if(ControlSetText(filewin,filedit,""))
                    {
                     if(ControlSend(filewin,filedit,ea_set_file,1))
                       {
                        Sleep(200);
                        if(ControlSend(filewin,filedit,"{ENTER}",0))
                           Sleep(300);
                       }
                    }

                  if(WinExists(filewin))
                    {
                     WinClose(filewin);
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to set .set file through file dialogue");
                     return(false);
                    }
                 }

               inputmod=true;

               if(algoenabled)
                 {
                  if(ControlLeftClick(m_program,okbutton))
                     break;
                  else
                    {
                     WinClose(m_program);
                     SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to click OK button");
                     return(false);
                    }
                 }
               else
                 {
                  if(!TabLeft(m_program,m_systab32))
                    {
                     if(ControlLeftClick(m_program,okbutton))
                        break;
                     else
                       {
                        WinClose(m_program);
                        SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to click OK button");
                        return(false);
                       }
                    }
                 }
              }
     }
   while(!inputmod||!dllenabled||!algoenabled);

   int try
         =50;

   while(WinExists(m_program) && try
            >0)
        {
         Sleep(500);
         try
            --;
        }

   if(WinExists(m_program) && !try)
     {
      WinClose(m_program);
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Failed to add program to chart");
      return(false);
     }


   if(p_type==ENUM_TYPE_EXPERT && StringFind(ChartGetString(m_chartid,CHART_EXPERT_NAME),ea_name)<0)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+" Operation failed could not add program to chart");
      return(false);
     }

   return(true);

  }
//+------------------------------------------------------------------+
//|Removes EA,Script from a chart                                    |
//+------------------------------------------------------------------+
bool CTerminalController::ChartExpertRemove(const string ea_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf)
  {
   return(RemoveExpert(ea_name,chart_symbol,chart_tf));
  }
//+------------------------------------------------------------------+
//| Removes all scripts and experts from all charts                  |
//+------------------------------------------------------------------+
bool CTerminalController::ChartExpertRemoveAll(void)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }

   if(!WinMenuSelectItem(m_terminal,MENU_CHARTS,MENU_EXPERTS_LIST,"","","","","",""))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Menu selection failure.");
      return(false);
     }

   Sleep(200);

   m_expwindow=WinGetHandle(EXPERTS_WINDOW);
   if(!m_expwindow)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_WINDOW+" window not found");
      return(false);
     }

   m_explistview=ControlGetHandle(m_expwindow,EXPERTS_WINDOW_LISTVIEW);
   if(!m_explistview)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_WINDOW_LISTVIEW+" control not found");
      WinClose(m_expwindow);
      return(false);
     }

   HWND remove_button=ControlGetHandle(m_expwindow,EXPERTS_REMOVE_BUTTON);
   if(!remove_button)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Remove button not found");
      WinClose(m_expwindow);
      return(false);
     }

   long listsize=GetListViewItemCount(m_expwindow,m_explistview);

   if(listsize<=1)
     {
      WinClose(m_expwindow);
      return(true);
     }

   string prgname;

   ENUM_PROGRAM_TYPE mql_program=(ENUM_PROGRAM_TYPE)MQLInfoInteger(MQL_PROGRAM_TYPE);
   switch(mql_program)
     {
      case PROGRAM_SCRIPT:
        {
         prgname=ChartGetString(ChartID(),CHART_SCRIPT_NAME);
         break;
        }
      case PROGRAM_EXPERT:
        {
         prgname=ChartGetString(ChartID(),CHART_EXPERT_NAME);
         break;
        }
      default:
         prgname="";
     }


   if(prgname=="")
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Unable to determine name of current program");
      WinClose(m_expwindow);
      return(false);
     }


   do
     {
      ClearAllListViewItemSelections(m_expwindow,m_explistview);


      for(int i=0; i<int(listsize); i++)
        {
         if(!SelectListViewItem(m_expwindow,m_explistview,IntegerToString(i),""))
            continue;

         string pname=GetListViewItemText(m_expwindow,m_explistview,IntegerToString(i),"0");

         if(StringFind(pname,prgname)<0)
           {
            if(IsControlEnabled(m_expwindow,remove_button))
              {
               if(ControlLeftClick(m_expwindow,remove_button))
                 {
                  listsize--;
                  Sleep(500);
                  break;
                 }
               else
                 {
                  SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Failed to click remove button");
                  break;
                 }
              }
            else
              {
               SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Remove button is disabled");
               break;
              }
           }
         else
           {
            ClearAllListViewItemSelections(m_expwindow,m_explistview);
            continue;
           }
        }
     }
   while(listsize>1);


   while(WinExists(m_expwindow))
      WinClose(m_expwindow);


   return(true);

  }
//+------------------------------------------------------------------+
//|Gets the last journal entry                                       |
//+------------------------------------------------------------------+
void CTerminalController::GetLastJournalEntry(string &entry)
  {
   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   long listsize=GetListViewItemCount(m_terminal,m_journaltab);

   if(listsize<=0)
      return;


   ClipPut("");


   if(!ClearAllListViewItemSelections(m_terminal,m_journaltab))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(!SelectListViewItem(m_terminal,m_journaltab,IntegerToString(listsize-1),""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select last listview item");
      return;
     }


   if(!ControlSend(m_terminal,m_journaltab,"{LCTRL down}c{LCTRL up}",0))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(entry);

   StringTrimRight(entry);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_journaltab);

   return;
  }
//+------------------------------------------------------------------+
//|Gets last entry made to experts log file                          |
//+------------------------------------------------------------------+
void CTerminalController::GetLastExpertsLogEntry(string &entry)
  {
   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   long listsize=GetListViewItemCount(m_terminal,m_expertstab);

   if(listsize<=0)
      return;

   ClipPut("");

   if(!ClearAllListViewItemSelections(m_terminal,m_expertstab))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(!SelectListViewItem(m_terminal,m_expertstab,IntegerToString(listsize-1),""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select last listview item");
      return;
     }


   if(!ControlSend(m_terminal,m_expertstab,"{LCTRL down}c{LCTRL up}",0))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(entry);

   StringTrimRight(entry);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_expertstab);

   return;
  }
//+------------------------------------------------------------------+
//|Gets last entry made to experts log file containg certain string  |
//+------------------------------------------------------------------+
void CTerminalController::GetLastExpertsLogEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry)
  {
   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   string items;
   string itemsarray[];

   long listsize=GetListViewItemCount(m_terminal,m_expertstab);

   if(listsize<=0)
      return;

   long stop=(max_items_to_search_in>0)? listsize-max_items_to_search_in:0;

   if(!ClearAllListViewItemSelections(m_terminal,m_expertstab))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(stop<=0)
     {
      if(!SelectAllListViewItems(m_terminal,m_expertstab))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select all listview items");
         return;
        }

      StringInit(items,int(listsize)*1000);
     }
   else
     {
      if(!SelectListViewItem(m_terminal,m_expertstab,IntegerToString(stop),IntegerToString(listsize-1)))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select "+IntegerToString(stop)+" listview items");
         return;
        }

      StringInit(items,int(stop)*1000);
     }


   ClipPut("");

   if(!ControlSend(m_terminal,m_expertstab,"{LCTRL down}c",0))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(items);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_expertstab);

   int a_size=StringSplit(items,StringGetCharacter("\n",0),itemsarray);

   for(int i=(a_size-1); i>=0; i--)
     {
      if(itemsarray[i]=="")
         continue;

      if(StringFind(itemsarray[i],text_to_search_for,24)>=24)
        {
         entry=itemsarray[i];
         StringTrimRight(entry);
         break;;
        }
     }

   ArrayFree(itemsarray);


   return;

  }


//+------------------------------------------------------------------+
//|Gets last entry made to journal containing certain string         |
//+------------------------------------------------------------------+
void CTerminalController::GetLastJournalEntryByText(const string text_to_search_for,const int max_items_to_search_in,string &entry)
  {

   entry="";

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   string items;
   string itemsarray[];

   long listsize=GetListViewItemCount(m_terminal,m_journaltab);

   if(listsize<=0)
      return;

   long stop=(max_items_to_search_in>0)? listsize-max_items_to_search_in:0;

   if(!ClearAllListViewItemSelections(m_terminal,m_journaltab))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to deselect all listview items");
      return;
     }

   if(stop<=0)
     {
      if(!SelectAllListViewItems(m_terminal,m_journaltab))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select all listview items");
         return;
        }

      StringInit(items,int(listsize)*1000);
     }
   else
     {
      if(!SelectListViewItem(m_terminal,m_journaltab,IntegerToString(stop),IntegerToString(listsize-1)))
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to select "+IntegerToString(stop)+" listview items");
         return;
        }

      StringInit(items,int(stop)*1000);
     }


   ClipPut("");

   if(!ControlSend(m_terminal,m_journaltab,"{LCTRL down}c",0))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"failed to send keys to control");
      return;
     }

   ClipGet(items);

   ClipPut("");

   ClearAllListViewItemSelections(m_terminal,m_journaltab);

   int a_size=StringSplit(items,StringGetCharacter("\n",0),itemsarray);

   for(int i=(a_size-1); i>=0; i--)
     {
      if(itemsarray[i]=="")
         continue;

      if(StringFind(itemsarray[i],text_to_search_for,24)>=24)
        {
         entry=itemsarray[i];
         StringTrimRight(entry);
         break;;
        }
     }

   ArrayFree(itemsarray);


   return;

  }

//+------------------------------------------------------------------+
//|Helper function detaches program from a chart                     |
//+------------------------------------------------------------------+
bool CTerminalController::RemoveExpert(const string program_name,const string chart_symbol,const ENUM_TIMEFRAMES chart_tf)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }


   if(!WinMenuSelectItem(m_terminal,MENU_CHARTS,MENU_EXPERTS_LIST,"","","","","",""))
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Menu selection failure.");
      return(false);
     }

   Sleep(200);

   m_expwindow=WinGetHandle(EXPERTS_WINDOW);
   if(!m_expwindow)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_WINDOW+" window not found");
      return(false);
     }

   m_explistview=ControlGetHandle(m_expwindow,EXPERTS_WINDOW_LISTVIEW);
   if(!m_explistview)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+EXPERTS_WINDOW_LISTVIEW+" control not found");
      return(false);
     }

   HWND remove_button=ControlGetHandle(m_expwindow,EXPERTS_REMOVE_BUTTON);
   if(!remove_button)
     {

      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Remove button not found");
      return(false);
     }

   long listsize=GetListViewItemCount(m_expwindow,m_explistview);

   if(listsize<=0)
     {
      return(true);
     }

   string newchartname=chart_symbol;
   StringToUpper(newchartname);
   newchartname+=","+PeriodToString(chart_tf);



   bool found=false;

   ClearAllListViewItemSelections(m_expwindow,m_explistview);

   for(int i=0; i<int(listsize); i++)
     {
      if(!SelectListViewItem(m_expwindow,m_explistview,IntegerToString(i),""))
         continue;

      string pname=GetListViewItemText(m_expwindow,m_explistview,IntegerToString(i),"0");

      string chartname=GetListViewItemText(m_expwindow,m_explistview,IntegerToString(i),"1");

      if(StringFind(pname,program_name)>=0 && StringFind(chartname,newchartname)>=0)
        {
         if(IsControlEnabled(m_expwindow,remove_button))
            if(ControlLeftClick(m_expwindow,remove_button))
               found=true;
        }

      if(found)
         break;

      ClearAllListViewItemSelections(m_expwindow,m_explistview);

     }

   WinClose(m_expwindow);

   return(found);
  }
//+------------------------------------------------------------------+
//|helper method converts period names to string format              |
//+------------------------------------------------------------------+
string CTerminalController::PeriodToString(const ENUM_TIMEFRAMES chart_tf)
  {
   string strper="";

   switch(chart_tf)
     {
      case PERIOD_MN1:
         strper="Monthly";
         break;
      case PERIOD_W1:
         strper="Weekly";
         break;
      case PERIOD_D1:
         strper="Daily";
         break;
      default:
         strper=StringSubstr(EnumToString(chart_tf),StringFind(EnumToString(chart_tf),"_")+1);
         break;
     }

   return strper;
  }
//+---------------------------------------------------------------------+
//|searches navigator for a program and outputs its location on the tree|
//+---------------------------------------------------------------------+
bool CTerminalController::Findprogram(const ENUM_TYPE_PROGRAM pr_type,const string program_name,const string relative_path,string &sbuffer)
  {

   long listsize=GetTreeViewItemCount(m_terminal,m_navigator,"#0");

   if(!listsize)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Root treeview control is empty");
      return(false);
     }
   else
     {
      string rpath="";

      if(relative_path=="")
         rpath=relative_path;
      else
        {
         if(StringFind(relative_path,"\\")==0)
            rpath=StringSubstr(relative_path,1);
         else
            rpath=relative_path;
         if(StringFind(rpath,"\\",StringLen(rpath)-1)<0)
            rpath+="\\";
        }

      switch(pr_type)
        {
         case ENUM_TYPE_EXPERT:
           {
            string fullpath="Expert Advisors\\"+rpath+program_name;
            Findbranch(listsize,"#0",fullpath,sbuffer);
            break;
           }
         case ENUM_TYPE_SCRIPT:
           {
            string fullpath="Scripts\\"+rpath+program_name;
            Findbranch(listsize,"#0",fullpath,sbuffer);
            break;
           }
         default:
            Findbranch(listsize,"#0","",sbuffer);
            break;
        }

     }

   if(sbuffer=="")
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Operation failed could not find "+program_name);
      return(false);
     }
   else
      return(true);

  }
//+-----------------------------------------------------------------------+
//|recursively searches systreeview for program and builds location string|
//+-----------------------------------------------------------------------+
void CTerminalController::Findbranch(const long childrenOnBranch,const string index,const string pname,string &sbuffer)
  {
   if(pname=="" ||  index=="")
     {
      sbuffer=index;
      return;
     }
   else
     {
      if(childrenOnBranch<=0)
         return;
      else
        {
         int find=StringFind(pname,"\\");

         long ss=0;
         long i;

         for(i=0; i<childrenOnBranch; i++)
           {

            ss=GetTreeViewItemCount(m_terminal,m_navigator,index+"|#"+IntegerToString(i));

            string search=(find>=0)?StringSubstr(pname,0,find):pname;

            string treebranchtext=GetTreeViewItemText(m_terminal,m_navigator,index+"|#"+IntegerToString(i));

            if(StringFind(treebranchtext,search)>=0 && StringLen(treebranchtext)==StringLen(search))
               break;

           }

         string npath=(find>=0)?StringSubstr(pname,find+1):"";

         Findbranch(ss,(i<childrenOnBranch)?index+"|#"+IntegerToString(i):"",npath,sbuffer);
        }
     }

   return;
  }
//+------------------------------------------------------------------+
//| Get the broker name from the terminal window title               |
//+------------------------------------------------------------------+
string CTerminalController::BrokerName(void)
  {
   string full_title=WinGetTitle(m_terminal);
   int find=StringFind(full_title,"-");
   string m_brokername=StringSubstr(full_title,find+1,StringFind(full_title,"-",find+1)-find-1);

   StringTrimLeft(m_brokername);
   StringTrimRight(m_brokername);

   return(m_brokername);
  }


//+------------------------------------------------------------------+
//| Set error details                                                |
//+------------------------------------------------------------------+
void CTerminalController::SetErrorDetails(const string _text)
  {
   StringFill(m_buffer,0);

   m_buffer=_text;

   return;
  }
//+------------------------------------------------------------------+
//|set the MetaQuotes id                                             |
//+------------------------------------------------------------------+
bool CTerminalController::SetNotificationId(const string MetaQuotes_id)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }

   string itemsarray[];

   int totalids=StringSplit(MetaQuotes_id,StringGetCharacter(",",0),itemsarray);

   if(totalids>4)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Invalid parameter settings, Only maximum of 4 MetaQuotes ID's allowed");
      return(false);
     }

   HWND opt_window,opt_tab,edit,ok,checkbutton1,checkbutton2,checkbutton3;

   if(!WinMenuSelectItem(m_terminal,MENU_TOOLS,MENU_OPTIONS,"","","","","",""))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Menu selection failure.");
      return(false);
     }

   Sleep(200);

   opt_window=WinGetHandle(OPTWINDOW);
   if(!opt_window)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Options Window not found.");
      return(false);
     }

   opt_tab=ControlGetHandle(opt_window,OPTWINDOW_TAB);
   if(!opt_tab)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Options Window tab control not found");
      WinClose(opt_window);
      return(false);
     }

   RECT wnsize;

   WinClientSize(opt_window,wnsize);

   int y=5;
   int x=5;

   string wintext=WinGetText(opt_window);
   while(StringFind(wintext,NOTIFICATIONS_TEXT)<0)
     {
      if(x<wnsize.right && ControlLeftClick(opt_window,opt_tab,1,x,5))
        {
         wintext=WinGetText(opt_window);
         x+=y;
        }
      else
        {
         SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Notification settings tab not found");
         WinClose(opt_window);
         return(false);
        }
     }

   checkbutton1=ControlGetHandle(opt_window,OPTWINDOW_CHECK_1);
   if(!checkbutton1)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Enable Notifications check button not found");
      WinClose(opt_window);
      return(false);
     }

   checkbutton2=ControlGetHandle(opt_window,OPTWINDOW_CHECK_2);
   if(!checkbutton2)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Enable Notifications from terminal check button not found");
      WinClose(opt_window);
      return(false);
     }

   checkbutton3=ControlGetHandle(opt_window,OPTWINDOW_CHECK_3);
   if(!checkbutton3)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Enable Notifications from trade server check button not found");
      WinClose(opt_window);
      return(false);
     }

   ok=ControlGetHandle(opt_window,OPTWINDOW_OK);
   if(!ok)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"OK button not found");
      WinClose(opt_window);
      return(false);
     }

   edit=ControlGetHandle(opt_window,OPTWINDOW_EDIT);
   if(!checkbutton1)
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"Notification Ids edit control not found");
      WinClose(opt_window);
      return(false);
     }

   string current_id=ControlGetText(opt_window,edit);

   if(!StringCompare(current_id,MetaQuotes_id))
     {
      WinClose(opt_window);
      return(true);
     }

   if(!IsButtonChecked(opt_window,checkbutton1))
      CheckButton(opt_window,checkbutton1);

   if(IsControlEnabled(opt_window,checkbutton2) && !IsButtonChecked(opt_window,checkbutton2))
      CheckButton(opt_window,checkbutton2);

   if(IsControlEnabled(opt_window,checkbutton3) && !IsButtonChecked(opt_window,checkbutton3))
      CheckButton(opt_window,checkbutton3);

   if(ControlSetText(opt_window,edit,""))
      ControlSend(opt_window,edit,MetaQuotes_id,1);

   if(ControlLeftClick(opt_window,ok))
      Sleep(200);

   if(WinExists(opt_window))
      WinClose(opt_window);

   return(true);

  }
//+------------------------------------------------------------------+
//| closes any pop up alert window                                   |
//+------------------------------------------------------------------+
void CTerminalController::CloseAlertDialogue(void)
  {
   static datetime lastcheck;

   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return;
     }

   if(WinExists(ALERTWINDOW,""))
     {
      string alertmessage;
      StringInit(alertmessage,200);

      GetLastExpertsLogEntryByText(ALERTWINDOW,0,alertmessage);

      if(StringLen(alertmessage)>0)
        {
         datetime check=StringToTime(StringSubstr(alertmessage,0,24));
         if(check>lastcheck && check>iTime(NULL,PERIOD_D1,0))
           {
            WinClose(ALERTWINDOW,"");
            lastcheck=check;
           }
        }

     }

   return;
  }
//+------------------------------------------------------------------+
//|Enable and disable autotrading                                    |
//+------------------------------------------------------------------+
bool CTerminalController::ToggleAutoTrading(void)
  {
   if(!IsInitialized())
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }

   if(!ControlSend(m_terminal,m_navigatortabs,"{LCTRL down}e{LCTRL up}",1))
     {
      SetErrorDetails(__FUNCTION__+" "+string(__LINE__)+". "+"AutoIt library not Initialized");
      return(false);
     }

   return(true);
  }

//+------------------------------------------------------------------+

Использование класса CTerminalController

Первый пример демонстрирует добавление программ на графики, а также их удаление. Добавьте название программы и укажите график. Последний входной параметр определяет, как долго будет работать добавленная программа в секундах. По истечении указанного времени программа будет удалена, если она еще запущена.

//+------------------------------------------------------------------+
//|                                           TerminalController.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com "
#property version   "1.00"
#include<terminalcontroller.mqh>

//--- input parameters
input string   ProgramName="Controls";
input string   Path="Examples\\Controls";
input string   Symbolname="BTCUSD";
input ENUM_TIMEFRAMES    Timeframe=PERIOD_D1;
input ENUM_TYPE_PROGRAM  Type=0;
input string   SetFileName="";
input int      RemoveProgramTimer=10;//Max seconds added program will run

CTerminalController terminal;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   if(!terminal.Initialize())
     {
      Print("Service failed to initialize CTerminalController instance");
      return(INIT_FAILED);
     }

   if(!terminal.ChartExpertAdd(Type,ProgramName,Path,SetFileName,Symbolname,Timeframe))
      Print("Failed to add "+ProgramName+" to chart. Error > "+terminal.GetErrorDetails());


   if(RemoveProgramTimer>0)
      EventSetTimer(RemoveProgramTimer);
   else
      EventSetTimer(10);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert timer function                                            |
//+------------------------------------------------------------------+
void OnTimer(void)
  {
   if(!terminal.ChartExpertRemove(ProgramName,Symbolname,Timeframe))
     {
      Print("Failed to remove "+ProgramName+". Error > "+terminal.GetErrorDetails());
     }
   else
     {
      string comment;
      terminal.GetLastJournalEntry(comment);
      Print(comment);
      ExpertRemove();
     }

  }
//+------------------------------------------------------------------+

Советник HandleAlerts отправляет визуальное всплывающее оповещение о каждом новом баре. Затем метод CloseAlertDialogue() закрывает любые всплывающие диалоги, сгенерированные терминалом.

//+------------------------------------------------------------------+
//|                                                 HandleAlerts.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com "
#property version   "1.00"
#include<terminalcontroller.mqh>
//--- input parameters
input int      Seconds=5;

CTerminalController terminal;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   if(!terminal.Initialize())
     {
      Print("Service failed to initialize CTerminalController instance");
      return(INIT_FAILED);
     }
   if(Seconds>0)
      EventSetTimer(Seconds);
   else
      EventSetTimer(10);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   static datetime lastsend;

   if(iTime(NULL,0,0)!=lastsend)
     {
      Alert("New Alert message sent at "+TimeToString(TimeCurrent()));
     }
  }
//+------------------------------------------------------------------+
//| Expert Timer functions                                           |
//+------------------------------------------------------------------+
void OnTimer()
  {
   terminal.CloseAlertDialogue();
  }
//+------------------------------------------------------------------+


Последний пример – это скрипт Send Push. Скрипт работает аналогично примеру, приведенному в статье об управлении терминалом MetaTrader через DLL.

//+------------------------------------------------------------------+
//|                                                    Send_Push.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com "
#property version   "1.00"
#property script_show_inputs
#include<terminalcontroller.mqh>
//--- input parameters
input string     message_text="test";
input string     Mq_ID="1C2F1442,2C2F1442,3C2F1442,4C2F1442";

CTerminalController terminal;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   if(!terminal.Initialize())
     {
      Print("Service failed to initialize CTerminalController instance");
      return;
     }

   if(!terminal.SetNotificationId(Mq_ID))
     {
      Print("Failed to set MetaQuotes id's. Error > "+terminal.GetErrorDetails());
      return;
     }

   if(!SendNotification(message_text))
     {
      int Err=GetLastError();
      switch(Err)
        {
         case 4515:
            Alert("Waiting: Failed to send ", Mq_ID);
            break;
         case 4516:
            Alert("Err: Invalid message text ", message_text);
            return;
            break;
         case 4517:
            Alert("Waiting: Invalid ID list ", Mq_ID);
            break;
         case 4518:
            Alert("Err: Too frequent requests! ");
            return;
            break;
        }
     }


  }
//+------------------------------------------------------------------+


Заключение

В статье было кратко описано, как работать с AutoIt. Я показал, как можно использовать библиотеку AutoItX после ее интеграции с MQL5, а также задокументировал создание класса, использующего AutoIt dll. Единственное ограничение, обнаруженное при использовании библиотеки, заключается в том, что при одновременном запуске двух или более программ MetaTrader 5, использующих AutoItX, возникают ошибки нарушения прав доступа. Поэтому рекомендуется запускать отдельные экземпляры программ MetaTrader 5, которые ссылаются на любой код AutoItX.

Папка
Содержание
Описание
MetaTrader 5zip\MQL5\include
autoIt.mqh, autoItbase.mqh,terminalcontroller.mqh
autoIt.mqh содержит операторы импорта функций AutoItX, autoItbase.mqh содержит класс CAutoIt, а terminalcontroller.mqh содержит класс CTerminalController
MetaTrader 5zip\MQL5\Experts
TerminalController.mq5,HandleAlerts.mq5
Советник TerminalController демонстрирует, как автоматически удалять и добавлять советники и скрипты на график.
Советник HandleAlerts показывает, как автоматизировать обработку всплывающих окон предупреждений
 MetaTrader 5zip\MQL5\Scripts TerminalUIComponents.mq5,Send_Push.mq5 TerminalUICommpents демонстрирует использование AutoItX путем прямого вызова импортированных функций, скрипт Send_Push добавляет в терминал новые MetaQuotes ID перед отправкой уведомления


Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/10130

Прикрепленные файлы |
Mt5.zip (15.46 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (4)
Vladimir Pastushak
Vladimir Pastushak | 1 февр. 2022 в 17:21

Код без комментариев... Не есть хорошо...

А так спасибо!

Denis Nikolaev
Denis Nikolaev | 7 апр. 2022 в 15:57
Очень интересная и полезная статья. Спасибо автору!
grimdragon
grimdragon | 7 июн. 2022 в 12:23
А подскажите, пожалуйста, как задать третий параметр в этой функции int AU3_WinGetPos(string, string, LPRECT); и получить эти координаты?
Maxim Kuznetsov
Maxim Kuznetsov | 7 июн. 2022 в 16:53

в комплекте VS есть более полезный и овеянный разработчиками Microsoft spy

а AutoIt не является свободно-доступным ПО (он shareware), за него надо платить и непонятно как вообще пропустили его рекламную статью

Графика в библиотеке DoEasy (Часть 95): Элементы управления составными графическими объектами Графика в библиотеке DoEasy (Часть 95): Элементы управления составными графическими объектами
В статье рассмотрим инструментарий для управления составными графическими объектами - элементы управления расширенным стандартным графическим объектом. Сегодня мы немного отступим от темы перемещения составного графического объекта и сделаем обработчик события изменения графика, на котором находится составной графический объект, и займёмся объектами управления составным графическим объектом.
Графика в библиотеке DoEasy (Часть 94): Составные графические объекты, перемещение и удаление Графика в библиотеке DoEasy (Часть 94): Составные графические объекты, перемещение и удаление
В статье начнём разработку различных событий составного графического объекта. Рассмотрим частично перемещение и удаление составного графического объекта. Сегодня по большей части мы будем дорабатывать то, что было создано в прошлой статье.
Веб-проекты (Часть I): Создание веб-приложения в схеме Laravel/Nuxt/MetaTrader 5 Веб-проекты (Часть I): Создание веб-приложения в схеме Laravel/Nuxt/MetaTrader 5
Разработчики MetaTrader 5 предоставили MQL-сообществу множество технологических решений, что даёт возможность реализовывать сложные программные комплексы, схемы которых могут выходить даже за рамки «песочницы» локального компьютера.
Фиксированный стоп-лосс на основе ценового действия и RSI ("умный" стоп-лосс) Фиксированный стоп-лосс на основе ценового действия и RSI ("умный" стоп-лосс)
Стоп-лосс – основной инструмент управления капиталом в трейдинге. Эффективное использование стоп-лосса, тейк-профита и размера лота может сделать торговлю более последовательной и в целом более прибыльной. Тем не менее, в использовании стоп-лосса есть и свои трудности. Основная из них – охота на стоп-лоссы. В этой статье рассматривается, как свести к минимуму эффект от охоты на стоп-лоссы, а также проводится сравнение с классическим применением стоп-лосса для определения его прибыльности.