English Русский 中文 Deutsch 日本語 Português
preview
Usando AutoIt con MQL5

Usando AutoIt con MQL5

MetaTrader 5Ejemplos | 15 diciembre 2021, 09:04
845 0
Francis Dube
Francis Dube

Introducción

En el artículo Manejar el Terminal de MetaTrader mediante DLL, la autora detalla cómo gestionar MetaTrader 4 mediante el control programático de la interfaz gráfica de usuario (gui) de la aplicación usando una biblioteca vinculada dinámicamente (dll) personalizada. En este artículo, analizaremos algo similar, pero, en lugar de escribir una dll personalizada, aprovecharemos la funcionalidad ofrecida por AutoIt. Usando AutoIt, crearemos una clase que permitará la automatización de tareas que no se pueden realizar solo con MQL5.

Estas tareas incluyen:

  • La capacidad de añadir y eliminar scripts o asesores expertos de los gráficos.
  • Leer desde los expertos del terminal y las pestañas del diario en la ventana de la caja de herramientas.
  • La capacidad de gestionar alertas automáticamente (leer mensajes de alerta y cerrar automáticamente las ventanas de diálogo de alerta).
  • Finalmente, implementaremos la misma funcionalidad que se mostró en el artículo de MetaTrader 4, la capacidad de configurar los ID de MetaQuotes en los ajustes de los terminales.


AutoIt

AutoIt es un lenguaje de scripts para automatizar la interfaz gráfica de usuario de Microsoft Windows. Ofrece, entre otras funciones, la gestión de ventanas, el acceso directo a los componentes de la interfaz de usuario y la simulación de input para los movimientos del ratón y el teclado. Parte de AutoIt es AutoItX, una dll que implementa algunas de las características del lenguaje de programación AutoIt. Al interactuar con esta dll, podemos otorgar a MQL5 capacidades similares de scripting de la interfaz gráfica.

Instalación

El software AutoIt está disponible gratuitamente en este enlace. Funciona en todas las versiones x86 de Microsoft Windows, hasta Windows 10. Se trata de una aplicación de 32 bits que se entrega con varios componentes de 64 bits, incluida una versión de AutoItX de 64 bits. Si desea obtener más información sobre AutoIt, le recomendamos encarecidamente que lea el archivo de ayuda que forma parte de la instalación de la aplicación. Antes de continuar, deberemos ser conscientes de las limitaciones de AutoIt.

Limitaciones

AutoIt tiene la limitación de que solo puede funcionar de manera fiable con los componentes estándar de Microsoft Windows que ofrece la API de Win32. Si un programa usa componentes personalizados, AutoIt no funcionará. Esto resulta esencialmente cierto para el software creado con marcos multiplataforma. Podemos comprobar si la interfaz de usuario de un programa es compatible con AutoIt usando la herramienta de información de la ventana de AutoIt. Otra limitación a considerar es que AutoItX solo implementa parte de lo que el lenguaje de scripting AutoIt es capaz de hacer. Podría ser que AutoIt sea capaz de manipular un componente, pero también es posible que la misma funcionalidad no esté disponible a través de AutoItX.

Herramienta de información de la ventana de AutoIt

AutoIt viene con una aplicación llamada AutoIt Window Info Tool, que se utiliza para obtener información sobre las ventanas de la aplicación.

Al arrastrar la herramienta Finder sobre cualquier parte de la aplicación de destino, podemos conseguir las propiedades de un componente en particular. Estos componentes se denominan controles. Un control puede ser un botón, un menú desplegable o una pestaña. Estos son solo algunos ejemplos: existen muchos tipos de controles que se usan para crear aplicaciones. Cada control está vinculado a una ventana. Una aplicación puede estar formada por varias ventanas. En general, hay una ventana principal, en la que se fijan o acoplan otras ventanas secundarias. Si las ventanas secundarias están fijadas o acopladas a la ventana principal de la aplicación, todos los controles incluidos en esas ventanas secundarias
formarán parte de la ventana principal de la aplicación. Cuando se usa AutoIt para ubicar con precisión un control, la ventana con la que está vinculado el control es importante, ya se trate de una ventana secundaria o de la ventana principal de la aplicación.

Si miramos el gráfico a continuación, podremos ver que la herramienta de búsqueda se arrastra sobre diferentes zonas de una aplicación Metatrader 5. Tome nota de los ajustes de la herramienta de información de la ventana al seleccionar el menú Opciones. Las opciones Freeze, Always On Top y Use Spy++ Control Detection Logic siempre están marcadas.


La pestaña de la ventana mostrará las propiedades de la ventana de la aplicación en el foco: aquí se enumeran el título y la clase de la ventana. Podemos usar estas propiedades para identificarla de forma única. Moviéndonos a la pestaña de control, podemos ver las propiedades del control; aquí nos interesa la propiedad ClassnameNN. (Note que nombre de clase en el contexto AutoIt se refiere al tipo de control). Esta propiedad combina el tipo de control con un identificador de instancia en forma de número. Resulta esencial conocer el tipo de control, pues esto determinará qué llamadas de función de AutoIt funcionarán en él.


Integración AutoItX

Para asegurarnos de que la integración con MetaTrader 5 tenga éxito, necesitaremos posibilitar que el terminal pueda encontrar la dll necesaria durante el tiempo de ejecución. Para conseguirlo, simplemente tendremos que copiar la dll necesaria en la carpeta de Bibliotecas de nuestra instalación de MetaTrader 5. El directorio de instalación predeterminado de AutoIt3 se encontrará en la carpeta archivos de programa (x86). La carpeta AutoItX, dentro de ella,
contiene todos los componentes relacionados con AutoItX, incluido el encabezado AutoItX3_Dll que enumera todos los prototipos de funciones expuestos en la dll. Es importante obtener la dll adecuada para nuestra versión de MetaTrader 5 (64 o 32 bits).

#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);

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


Cualquier programa MetaTrader 5 que use la biblioteca AutoItX, primero tendrá que importar sus funciones. Para mayor comodidad, vamos a crear el archivo de inclusión autoIt.mqh, cuyo único propósito será importar todos los prototipos de funciones expuestos por la biblioteca.

Autoit es estrictamente una herramienta del sistema operativo Microsoft Windows que aprovecha la API de Windows. Por este motivo, la biblioteca AuotItX hace un uso extensivo de los tipos de datos específicos de la API de Win32. Para asegurarnos de que la compatibilidad con MQL5 es completa, podríamos implementar estos tipos de datos nosotros mismos en MQL5, pero no será necesario. En su lugar, podemos usar el archivo windef.mqh, que forma parte de los esfuerzos de MetaQuotes por integrar la API Win32 en MQL5. El archivo contiene la mayoría de las definiciones de los tipos de datos que se usan en la API de Windows.
Incluiremos windef.mqh en nuestro archivo autoit.mqh, que contendrá todos los prototipos de funciones importados de la dll. El archivo de código autoit.mqh ahora tiene el aspecto que sigue:

//+------------------------------------------------------------------+
//|                                                       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


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


Preliminares de uso
El uso de la biblioteca en MQL5 requiere la inicialización de la dll llamando primero a la función AU3_Init. Debemos hacer esto antes de llamar a cualquiera de las otras funciones importadas. Las signaturas de las funciones son similares a las usadas en el lenguaje de scripting AutoIt, lo cual significa que tienen parámetros de función y tipos de retorno similares. Debemos estar familiarizados con el lenguaje de scripting AutoIt para comprender cómo funcionan las funciones; una vez más, toda esta información está disponible en el archivo de ayuda que forma parte de la instalación de la aplicación.

Las funciones que retornan un valor, devuelven valores numéricos positivos, generalmente 1 (en caso de éxito) y 0 (en caso de error). Las funciones void generan una línea o una referencia de estructura. Para este tipo de funciones, podemos llamar a la función AU3_error() para confirmar si ha sucedido un error. Una función también simplemente generará una línea con "0" o una estructura vacía cuando una función falle. Las funciones que generan referencias de líneas también especifican un parámetro correspondiente de tamaño de búfer. Esto significa que la longitud del búfer para la línea transmitida por referencia deberá

establecerse explícitamente antes de llamar a la función. De lo contrario, si no se establece la longitud del búfer de línea, se marcará un error. Si el tamaño asignado del búfer resulta insuficiente, la función mostrará los caracteres que quepan en el espacio especificado, dejando fuera el resto, y produciendo una línea truncada. No tenemos forma de conocer la cantidad de espacio necesaria para el output, por lo que deberemos tener en cuenta esta particularidad. Para establecer la longitud del búfer para una línea, podemos utilizar la función incorporada de MQL5 String init.

Hay algunas funciones que tienen el sufijo ...ByHandle en sus nombres, por ejemplo, AU3_WinCloseByHandle(). Esta función hace lo mismo que AU3_WinClose(); la diferencia es que la función con el sufijo ByHandle opera identificando un control o ventana según su identificador. Es preferible utilizar estas funciones, ya que ayudan con la depuración, y nos resultará más fácil encontrar errores relacionados con la identificación de la ventana o control correcto.


Un ejemplo inicial.
El siguiente ejemplo muestra el uso de las funciones AutoitX en MQL5. En el siguiente script, utilizaremos la función AU3_WinGetHandle para obtener el identificador de la ventana principal del terminal. Podemos identificar el terminal de forma única según el número de cuenta activa que se muestra en la barra de título de la ventana.

//+------------------------------------------------------------------+
//|                                         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);

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



Con el identificador de la ventana principal recuperado, podemos obtener más información sobre los componentes de la interfaz gráfica de usuario, con los que podemos interactuar llamando a la función AU3_WinGetClassListByHandle. Esta retornará una lista de líneas, que son los nombres de clase de todos los componentes de la interfaz de usuario vinculados con el identificador de ventana ofrececido.

A continuación, mostramos el resultado de la ejecución del script.

Resultado de TerminalUIComponents

Antes de pasar a algunos ejemplos más sólidos, creemos una clase que abarque la mayoría de las funciones de AutoIt importadas.


Clase CAutoit

CAutoit será la clase básica de la que se derivarán las otras clases que utilizan la biblioteca AutoItX. Tendrá una única propiedad estática que indicará si se ha llamado o no la función de la biblioteca de inicialización AU3_Init().

La única otra propiedad, m_buffer_size, determina la longitud del búfer de las líneas usadas en las llamadas del método.

//+------------------------------------------------------------------+
//|                                                   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);

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


Clase CTerminalController

A continuación, vamos a crear la clase CTerminalController en el archivo terminalcontroller.mqh.
En primer lugar, incluimos el archivo autoitbase.mqh, que contiene la clase CAutoIt. A continuación, usamos las directivas de preprocesador para definir las constantes de línea que identifican los componentes de la interfaz de usuario con los que trabajará la clase.
Antes de indicar la clase, declaramos una enumeración personalizada que clasifica los programas de MetaTrader 5 como un script o un asesor experto.

//+------------------------------------------------------------------+
//|                                           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
  };



Las propiedades privadas de tipo HWND son la ventana y los identificadores de control que se usan en la clase.

//+------------------------------------------------------------------+
//|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: hace referencia al identificador de gráfico definido al llamar a la función MQL5 chartID().
m_accountNum: es el número de la cuenta activa que se muestra en la barra de título de la aplicación del terminal. Este valor se utilizará para distinguir una ventana de terminal activa de otra.
m_buffer: línea donde se escribirán los mensajes de error detallados en caso de que algo salga mal.

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 tendrá un solo constructor. El constructor por defecto inicializa m_accountNum con la cuenta de terminal activa actualmente, retornada por la llamada a la función AccountInfoInteger.

Los métodos.

//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);



  };


Para recuperar los mensajes de error, existe GetErrorDetails(). La función retorna el contenido del miembro privado m_buffer. SetErrorDetails(), por otra parte, es un método privado que se utiliza de forma interna para establecer el contenido del miembro de línea m_buffer.

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

   m_buffer=_text;

   return;
  }


El método Initialize() debe llamarse al menos una vez en la inicialización del programa, antes que cualquier otro método. El método tiene un único parámetro predeterminado, accountNumber: si el argumento no es cero, restablece el valor de la propiedad de la clase m_accountNum, que a su vez restablece todas las demás propiedades de la clase, lo cual activa la búsqueda de la ventana de terminal principal identificada por la propiedad m_accountNum. Una vez que se encuentra la ventana principal, los demás identificadores de control se recuperan y usan para establecer las propiedades restantes de la clase.

//+------------------------------------------------------------------+
//| 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() se usa para adjuntar scripts o asesores expertos a los gráficos. Los parámetros de la función son:

  • p_type: tipo de programa, ya sea un asesor experto o un script,
  • ea_name: nombre del script o del asesor experto exactamente como aparece en la ventana del navegador; no se deben incluir nombres de extensión de archivo.
  • ea_relative_path: esta es la ruta relativa a una subcarpeta en las carpetas Scripts o Experts (dar un ejemplo visual) que contiene el programa dado por el parámetro ea_name; tomemos por ejemplo los controles del asesor experto que se muestran en la imagen a continuación. Se encuentran en una carpeta llamada Controls en la subcarpeta Examples dentro de la carpeta Experts, por lo que su ruta sería  Examples\Controls. Si el programa no está en ninguna subcarpeta de la carpeta Scripts o Experts, entonces este argumento deberá establecerse como NULL o "".

    Navegador


  • ea_set_file: nombre de archivo de un archivo .set; para este argumento se debe especificar la extensión de archivo .set.
  • Los argumentos chart_symbol y chart tf indican las propiedades del gráfico al que se añadirá el programa.


Primero llamamos al método SwitchToNewChart(). Este método busca el gráfico solicitado entre las ventanas de gráficos abiertas y actualizadas. Si lo encuentra, el foco se establece en él; de lo contrario, la función ChartOpen() se usará para abrir un nuevo gráfico. El método también se encarga de establecer la propiedad m_chartid de la clase.
La propiedad m_chartid se utiliza para comprobar si el programa ya se ha añadido al gráfico. Si el programa existe, el método retornará 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);
  }


Si no se encuentra el programa, se realizarán los preparativos para buscar en el panel del navegador. Si la pestaña Común del panel Navegador no está visible, está habilitada.
Una vez habilitada, se llama al método Findprogram() para buscar el programa MetaTrader 5 en el control systreeview32. El método solicita la ayuda del método recursivo 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() atraviesa el control y construye la identificación de referencia de línea que constituye la ruta a la ubicación del programa en el control systreeview32. La identificación de referencia del programa es necesaria para que AutoIt se pueda usar para seleccionarla y añadirla al gráfico.

//+-----------------------------------------------------------------------+
//|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;
  }


En este punto, si el programa es un asesor experto y ya hay otro asesor en el gráfico, aparecerá una ventana de diálogo confirmando la sustitución del asesor experto actualmente en ejecución.

Si el programa iniciado tiene inputs, el ciclo do... while recorrerá las pestañas, establecerá el archivo .set y marcará los botones de verificación que permiten el comercio automático y las exportaciones de dll, si fuera necesario.

Para terminar, al final, el método retorna el resultado de la verificación del gráfico nuevamente para el programa, para confirmar si ha sido añadido al gráfico.

//+------------------------------------------------------------------+
//| 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() separa un script o un asesor experto de un gráfico. Para ello, invoca la ventana de diálogo Experts a través del menú principal de la aplicación. A continuación, el método itera por la lista de programas y localiza una coincidencia basada en el nombre del programa y las propiedades del gráfico (es decir, el símbolo del gráfico y el marco temporal).
La función ChartExpertRemoveAll() elimina todos los asesores y los scripts, salvo el programa que realmente está haciendo las eliminaciones.

//+------------------------------------------------------------------+
//|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);
  }


El output de los métodos GetLastExpertsLogEntry() y GetLastJournalEntry() a una línea hace referencia a la última entrada realizada en el registro de expertos y el registro del diario, respectivamente.
Los métodos interactúan con las pestañas del diario o de los expertos, y no leen de los archivos de registro reales: básicamente extraen texto del control listview32. Si las pestañas se han borrado manualmente, los métodos no podrán recuperar datos directamente de los archivos de registro.

//+------------------------------------------------------------------+
//|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;
  }


Las funciones GetLastExpertsLogEntryByText() y GetLastJournalEntryByText() retornan la última entrada del registro que coincida con el parámetro text_to_search_for. Las funciones comienzan la búsqueda desde la entrada de registro más reciente retrocediendo en el tiempo. El parámetro max_items_to_search_in establece el número máximo de entradas del registro para iterar. Por ejemplo, si lo establecemos en 10, la función iterará a través de las últimas 10 entradas del registro en busca de una coincidencia. Si establecemos este parámetro en 0 o un número negativo, entonces la función iterará a través de todas las entradas del registro.

//+------------------------------------------------------------------+
//|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;

  }


El método SetNotificationId() supone un retroceso a la demostración original de este concepto. Se necesita un parámetro de línea de un máximo de cuatro IDs de MetaQuotes.

//+------------------------------------------------------------------+
//|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(), al ser llamado, busca cualquier alerta emergente y se cierra.

//+------------------------------------------------------------------+
//| 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;
  }

Abajo mostramos el código para la clase completa

//+------------------------------------------------------------------+
//|                                           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);
  }

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

Usando la clase CTerminalController

El primer ejemplo nos muestra cómo añadir programas a los gráficos, y también cómo eliminarlos. Añadimos el nombre de un programa y especificamos el gráfico. El último parámetro de entrada indica cuánto tiempo se ejecutará el programa añadido en segundos. Una vez transcurrido el tiempo indicado, el programa se eliminará si aún se está ejecutando.

//+------------------------------------------------------------------+
//|                                           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();
     }

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

El asesor experto HandleAlerts envía una alerta visual emergente para cada nueva barra. El método CloseAlertDialogue() se usa para cerrar las ventanas de diálogo emergentes generadas por el terminal.

//+------------------------------------------------------------------+
//|                                                 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();
  }
//+------------------------------------------------------------------+


El último ejemplo es el script Send Push: este script funciona de manera similar al ejemplo ofrecido en el artículo Manejar el Terminal de MetaTrader mediante 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;
        }
     }


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


Conclusión

El presente artículo ofrece una breve descripción del trabajo con AutoIt. Hemos analizado cómo usar la biblioteca AutoItX integrándola con MQL5 y también hemos documentado la creación de una clase que usa AutoIt dll. La única limitación que hemos encontrado al usar la biblioteca es que se producirán errores de infracción de acceso si se ejecutan simultáneamente 2 o más programas MetaTrader 5 que usen AutoItX. Por consiguiente, le recomendamos ejecutar instancias únicas de programas MetaTrader 5 que hagan referencia a cualquier código AutoItX.

Carpeta
Contenido
Descripción
MetaTrader 5zip\MQL5\include
autoIt.mqh, autoItbase.mqh,terminalcontroller.mqh
autoIt.mqh contiene declaraciones de importación de funciones de AutoItX; autoItbase.mqh contiene la clase CAutoIt y terminalcontroller.mqh contiene la clase CTerminalController
MetaTrader 5zip\MQL5\Experts
TerminalController.mq5,HandleAlerts.mq5
TerminalController EA demuestra la eliminación automática y la adición de asesores expertos o scripts en un gráfico.
HandleAlerts EA muestra cómo automatizar la gestión de ventanas emergentes de alerta
 MetaTrader 5zip\MQL5\Scripts  TerminalUIComponents.mq5,Send_Push.mq5  TerminalUICommpents demuestra el uso de AutoItX llamando dfirectamente a las funciones importadas; el script Send_Push añade nuevas ID de MetaQuotes al terminal antes de enviar una notificación


Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/10130

Archivos adjuntos |
Mt5.zip (15.46 KB)
Combinatoria y teoría de la probabilidad en el trading (Parte V): Análisis de curvas Combinatoria y teoría de la probabilidad en el trading (Parte V): Análisis de curvas
En este artículo, hemos decidido investigar un poco sobre la conversión de varios estados en estados dobles. El objetivo principal es el propio análisis y las conclusiones útiles que extraigamos, que nos pueden ayudar en el desarrollo posterior de algoritmos comerciales escalables basados ​​en la teoría de la probabilidad. Obviamente, no hemos podido evitar el uso de matemáticas, pero, teniendo en cuenta la experiencia de artículos anteriores, hemos observado que la información general resulta mucho más útil que los detalles en sí.
Stoploss de PriceAction Fijo o RSI fijo (Smart StopLoss) Stoploss de PriceAction Fijo o RSI fijo (Smart StopLoss)
Los Stop Loss son una herramienta importante en cuanto a la gestión de dinero en el trading. El uso efectivo de stop-loss, take profit y el tamaño de lote puede hacer que un tráder sea más consistente en el comercio y, sobre todo, que logre mayor rentabilidad. Aunque el stop-loss es una gran herramienta, existen desafíos derivados de su uso. El principal es la caza de stop-loss. Este artículo analiza cómo reducir la caza de stop-loss en el trading y la compara con el uso clásico de stop-loss para determinar su rentabilidad.
Desarrollando un EA comercial desde cero Desarrollando un EA comercial desde cero
Comprenda cómo desarrollar un EA para tráding programando lo menos posible
Combinatoria y teoría de la probabilidad en el trading (Parte IV): Lógica de Bernoulli Combinatoria y teoría de la probabilidad en el trading (Parte IV): Lógica de Bernoulli
En el presente artículo, hemos decidido hablar del conocido esquema de Bernoulli, y también mostrar cómo podemos utilizarlo al describir conjuntos de datos relacionados con el trading, para su posterior uso en la futura creación de un sistema comercial autoadaptable. Asimismo, buscaremos un algoritmo más general (la fórmula de Bernoulli constituye un caso especial dentro de este tipo), y encontraremos una aplicación para él.