
Die Verwendung von AutoIt mit MQL5
Einführung
In dem Artikel Die Verwaltung des Handelsterminals MetaTrader via DLL beschreibt der Autor, wie man den Metatrader 4 (MetaTrader 4) programmgesteuert kontrolliert, indem man die grafische Benutzeroberfläche (gui) der Anwendung mit einer speziell angefertigten dynamisch verlinkten Bibliothek (dll) beeinflusst. In diesem Artikel werden wir etwas Ähnliches in vorschlagen, aber anstatt eine nutzerdefinierte DLL zu schreiben, werden wir die von AutoIt bereitgestellten Funktionen nutzen. Mit AutoIt werden wir eine Klasse erstellen, die die Automatisierung von Aufgaben ermöglicht, die mit reinem MQL5 nicht erledigt werden können.
Diese Aufgaben umfassen:
- Hinzufügen und Entfernen von Skripten oder Expert Advisors aus Charts.
- Auslesen der Experten- und Journal-Registerkarten des Terminals im Toolbox-Fenster.
- Die Fähigkeit, Alarme automatisch zu behandeln (Lesen von Alarmmeldungen und automatisches Schließen von Alarmdialogen).
- Schließlich werden wir die gleiche Funktionalität implementieren, die im MetaTrader 4 Artikel gezeigt wurde, nämlich die Möglichkeit, die MetaQuotes ID's in den Einstellungen des Terminals zu setzen.
AutoIt
AutoIt ist eine Skriptsprache zur Automatisierung der grafischen Benutzeroberfläche von Microsoft Windows, die unter anderem eine Fensterverwaltung, einen direkten Zugriff auf Komponenten der Benutzeroberfläche und die Simulation von Maus- und Tastatureingaben ermöglicht. Teil von AutoIt ist AutoItX, eine DLL, die einige der Funktionen der AutoIt-Skriptsprache implementiert. Durch die Kopplung mit dieser DLL können wir MQL5 mit ähnlichen Fähigkeiten zur Skripterstellung für die Benutzeroberfläche ausstatten.
Installation
Die AutoIt-Software ist unter diesem Link frei erhältlich. Sie funktioniert auf allen x86-Versionen von Microsoft Windows bis hin zu Windows 10. Es handelt sich um eine 32-Bit-Anwendung, die mit verschiedenen 64-Bit-Komponenten geliefert wird, einschließlich einer 64-Bit-Version von AutoItX. Wenn Sie mehr über AutoIt erfahren möchten, sollten Sie unbedingt die Hilfedatei lesen, die Teil der Anwendungsinstallation ist. Bevor wir weitergehen, müssen wir uns über die Einschränkungen von AutoIt im Klaren sein.
Einschränkungen
AutoIt ist insofern eingeschränkt, als es nur mit Standardkomponenten von Microsoft Windows, wie sie von der Win32-API bereitgestellt werden, zuverlässig arbeiten kann. Wenn ein Programm nutzerdefinierte Komponenten verwendet, wird AutoIt nicht funktionieren. Dies trifft vor allem auf Software zu, die mit plattformübergreifenden Frameworks erstellt wurde. Wir können überprüfen, ob die Benutzeroberfläche eines Programms mit AutoIt kompatibel ist, indem wir das AutoIt Window Info Tool verwenden. Eine weitere Einschränkung, der man sich bewusst sein sollte, ist die Tatsache, dass AutoItX nur einen Teil der Möglichkeiten der AutoIt-Skriptsprache implementiert. Es ist möglich, dass eine Komponente von AutoIt manipuliert werden kann, aber die gleiche Funktionalität nicht über AutoItX verfügbar ist.
Das Fenster-Info-Tool von AutoIt
AutoIt wird mit einer Anwendung namens AutoIt Window Info Tool ausgeliefert, die dazu dient, Informationen über Anwendungsfenster zu erhalten.
Indem man das Finder Tool über einen beliebigen Teil einer Zielanwendung zieht, kann man die Eigenschaften einer bestimmten Komponente abrufen. Diese Komponenten werden als Steuerelemente (controls) bezeichnet. Ein Steuerelement kann eine Schaltfläche, ein Dropdown-Menü oder eine Registerkarte sein. Dies sind nur einige Beispiele, es gibt viele Arten von Steuerelementen, die zur Erstellung von Anwendungen verwendet werden. Jedes Steuerelement ist mit einem Fenster verbunden. Eine Anwendung kann aus einer Reihe von Fenstern bestehen. Normalerweise gibt es ein Hauptfenster, an das andere untergeordnete Fenster angehängt oder angedockt sind. Wenn die untergeordneten Fenster an das Hauptfenster der Anwendung angehängt oder angedockt sind, dann werden alle Steuerelemente, die in diesen untergeordneten Fenstern enthalten sind,Teil des Hauptfensters der Anwendung. Wenn Sie AutoIt verwenden, um ein Steuerelement genau zu lokalisieren, ist das Fenster, mit dem das Steuerelement verbunden ist, wichtig, egal ob es sich um ein untergeordnetes Fenster oder das Hauptanwendungsfenster handelt.
In der nachstehenden Grafik sehen Sie, wie das Suchwerkzeug über verschiedene Bereiche einer Metatrader 5-Anwendung gezogen wird, und beachten Sie die Einstellungen des Werkzeugs Fensterinfo, wenn das Menü Optionen ausgewählt ist. Die Optionen Freeze, Always On Top und Use Spy++ Control Detection Logic sind angekreuzt.
Die Registerkarte des Fensters zeigt die Eigenschaften eines Anwendungsfensters an, das sich im Fokus befindet; hier sind der Titel und die Klasse des Fensters aufgeführt. Diese Eigenschaften können zur eindeutigen Identifizierung des Fensters verwendet werden. Auf der Registerkarte des Steuerelements "Control" werden die Eigenschaften des Steuerelements angezeigt, wobei hier die Eigenschaft ClassnameNN von Interesse ist (beachten Sie, dass sich der Klassenname im AutoIt-Kontext auf den Typ eines Steuerelements bezieht). Diese Eigenschaft kombiniert den Typ des Steuerelements mit einem Instanzbezeichner in Form einer Zahl. Die Kenntnis des Typs eines Steuerelements ist wichtig, da dadurch bestimmt wird, welche AutoIt-Funktionsaufrufe für das Steuerelement funktionieren.
Die Integration von AutoItX
Um eine erfolgreiche Integration mit MetaTrader 5 zu gewährleisten, müssen wir sicherstellen, dass das Terminal die erforderliche DLL während der Laufzeit finden kann. Um dies zu erreichen, müssen wir die benötigte DLL einfach in den Ordner Libraries unserer MetaTrader 5-Installation kopieren. Das Standard-Installationsverzeichnis von AutoIt3 befindet sich im Ordner Program files (x86). Der darin befindliche Ordner AutoItXenthält alle AutoItX-bezogenen Komponenten, einschließlich des AutoItX3_Dll-Headers, der alle Funktionsprototypen auflistet, die in der DLL enthalten sind. Es ist wichtig, dass Sie die passende dll für Ihre Version von MetaTrader 5 (64 oder 32bit) erhalten.
#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); ///////////////////////////////////////////////////////////////////////////////
Jedes MetaTrader 5-Programm, das die AutoItX-Bibliothek verwendet, muss zunächst deren Funktionen importieren. Der Einfachheit halber werden wir eine Include-Datei autoIt.mqh erstellen, deren einziger Zweck es ist, alle Funktionsprototypen zu importieren, die von der Bibliothek zur Verfügung gestellt werden.
Autoit ist streng genommen ein Werkzeug des Microsoft Windows Betriebssystems, das die Windows API nutzt. Aus diesem Grund macht die AuotItX-Bibliothek ausgiebig Gebrauch von Win32-API-spezifischen Datentypen. Um die Kompatibilität mit MQL5 zu gewährleisten, könnten wir diese Datentypen selbst in MQL5 implementieren, aber das ist nicht notwendig. Stattdessen können wir die Datei windef.mqh verwenden, die Teil der Bemühungen von MetaQuotes ist, die Win32-API in MQL5 zu integrieren. Die Datei enthält die meisten Datentypdefinitionen, die in der Windows-API verwendet werden.
Wir werden windef.mqh in unsere autoit.mqh-Datei einbinden, die alle aus der dll importierten Funktionsprototypen enthalten wird. Die Code-Datei autoit.mqh sieht nun wie folgt aus:
//+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+
Vorbemerkungen zur Verwendung
Die Verwendung der Bibliothek in MQL5 erfordert die Initialisierung der DLL durch den ersten Aufruf der Funktion AU3_Init, die vor dem Aufruf der anderen importierten Funktionen erfolgen sollte. Die Funktionssignaturen sind analog zu denen der Skriptsprache AutoIt, d.h. sie haben ähnliche Funktionsparameter und Rückgabetypen. Um die Funktionsweise der Funktionen zu verstehen, ist eine gewisse Vertrautheit mit der Skriptsprache AutoIt erforderlich; auch hier finden Sie alle Informationen in der Hilfedatei, die Teil der Anwendungsinstallation ist.
vor dem Aufruf der Funktion explizit festgelegt werden. Andernfalls wird eine Fehlermeldung ausgegeben, wenn die Pufferlänge für die Zeichenkette nicht gesetzt ist. Wenn die zugewiesene Größe des Puffers nicht ausreicht, gibt die Funktion die Zeichen aus, die in den angegebenen Bereich passen, und lässt den Rest weg, wodurch eine abgeschnittene Zeichenkette entsteht. Es gibt keine Möglichkeit, den für die Ausgabe benötigten Platz zu ermitteln, so dass man sich dieser Eigenart bewusst sein muss. Um die Pufferlänge für einen String festzulegen, können wir die eingebaute MQL5-Funktion StringInit verwenden.
Es gibt einige Funktionen, die das Suffix ...ByHandle in ihrem Namen haben, zum BeispielAU3_WinCloseByHandle(). Diese Funktion tut dasselbe wie AU3_WinClose(), mit dem Unterschied, dass die Funktion mit dem Suffix ByHandle ein Steuerelement oder Fenster anhand seines Handles identifiziert. Die Verwendung dieser Funktionen ist vorzuziehen, da sie bei der Fehlersuche hilft, da es einfacher ist, Fehler zu finden, die mit der Identifizierung des richtigen Fensters oder Steuerelements zusammenhängen.
Ein erstes Beispiel.
Das folgende Beispiel demonstriert die Verwendung von AutoitX-Funktionen in MQL5. Im folgenden Skript wird die Funktion AU3_WinGetHandle verwendet, um das Handle des Hauptfensters des Terminals zu erhalten. Das Terminal kann anhand der aktiven Kontonummer, die in der Titelleiste des Fensters angezeigt wird, eindeutig identifiziert werden.
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Nachdem das Handle des Hauptfensters ermittelt wurde, können wir weitere Informationen über die Komponenten der Benutzeroberfläche erhalten, mit denen wir interagieren können, indem wir die Funktion AU3_WinGetClassListByHandle aufrufen. Sie gibt eine Liste von Zeichenketten zurück, die die Klassennamen aller Komponenten der Benutzeroberfläche enthalten, die mit dem angegebenen Fensterhandle verbunden sind.
Das Ergebnis der Ausführung des Skripts sieht wie folgt aus:
Bevor wir zu einigen robusteren Beispielen übergehen, erstellen wir eine Klasse, die die meisten der importierten AutoIt-Funktionen umschließt.
Die Klasse CAutoit
CAutoit wird die Basisklasse sein, von der andere Klassen, die die AutoItX-Bibliothek verwenden, abgeleitet werden. Sie wird eine einzige statische Eigenschaft haben, die angibt, ob die Initialisierungsfunktion AU3_Init() der Bibliothek aufgerufen wurde oder nicht.
Die einzige andere Eigenschaft m_buffer_size bestimmt die Pufferlänge der in den Methodenaufrufen verwendeten Zeichenketten.
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Die Klasse CTerminalController
Als Nächstes erstellen wir die Klasse CTerminalController in der Datei terminalcontroller.mqh.
Zuerst binden wir die Datei autoitbase.mqh ein, die die Klasse CAutoIt enthält. Wir verwenden Präprozessordirektiven, um Stringkonstanten zu definieren, die die Komponenten der Nutzerschnittstelle identifizieren, mit denen die Klasse arbeiten wird.
Bevor wir die Klasse spezifizieren, deklarieren wir eine nutzerdefinierte Enumeration, die MetaTrader 5 Programme entweder als Skript oder als Expert Advistor klassifiziert.
//+------------------------------------------------------------------+ //| 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 };
Die privaten Eigenschaften vom Typ HWND sind die Fenster- und Steuerhandles, die in der Klasse verwendet werden.
//+------------------------------------------------------------------+ //|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 - bezieht sich auf die Kennung des Charts, wie sie durch den Aufruf der MQL5-Funktion chartID() definiert ist.
m_accountNum - ist die aktive Kontonummer, die in der Titelleiste der Terminalanwendung angezeigt wird. Dieser Wert wird verwendet, um ein aktives Terminalfenster von einem anderen zu unterscheiden.
m_buffer - Zeichenkette, in den detaillierte Fehlermeldungen geschrieben werden, falls etwas schief geht.
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 wird eine einzigen Konstruktor. Der Standard-Konstruktor initialisiert m_accountNum mit dem aktuell aktiven Terminal-Konto, das durch einen Aufruf der Funktion AccountInfoInteger zurückgegeben wird.
The methods.
//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); };
Zum Abrufen von Fehlermeldungen gibt es die Funktion GetErrorDetails(). Die Funktion gibt den Inhalt des privaten Elements m_buffer zurück. SetErrorDetails() hingegen ist eine private Methode, die intern verwendet wird, um den Inhalt des String-Members m_buffer zu setzen.
//+------------------------------------------------------------------+ //| Set error details | //+------------------------------------------------------------------+ void CTerminalController::SetErrorDetails(const string _text) { StringFill(m_buffer,0); m_buffer=_text; return; }
Die Methode Initialize() sollte mindestens einmal bei der Programminitialisierung vor allen anderen Methoden aufgerufen werden. Die Methode hat einen einzigen Standardparameter, accountNumber - wenn das Argument ungleich Null ist, wird der Wert der Klasseneigenschaft m_accountNum zurückgesetzt, was wiederum alle anderen Klasseneigenschaften zurücksetzt und die Suche nach dem durch die Eigenschaft m_accountNum identifizierten Hauptterminalfenster auslöst. Sobald das Hauptfenster gefunden ist, werden alle anderen Kontrollhandles abgerufen und zur Einstellung der übrigen Klasseneigenschaften verwendet.
//+------------------------------------------------------------------+ //| 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() wird verwendet, um Expert Advisors oder Skripte auf Charts zu starten. Die Parameter der Funktion sind:
- p_type - der Programmtyp, entweder ein Expert Advisor oder ein Skript,
- ea_name - der Name des Skripts oder des Expert Advisors, so wie er im Navigator-Fenster erscheint; Dateierweiterungen dürfen nicht enthalten sein.
- ea_relative_path - dies ist der relative Pfad zu einem Unterordner in den Ordnern Scripts oder Experts (geben Sie ein visuelles Beispiel an), der das durch den Parameter ea_name angegebene Programm enthält. Nehmen Sie zum Beispiel den in der Abbildung unten gezeigten Expert Advisor Controls, er ist in einem Ordner namens Controls im Unterordner Examples innerhalb des Ordners Experts enthalten, sein Pfad wäre also Examples\Controls, wenn sich das Programm in keinem Unterordner des Ordners Scripts oder Experts befindet, dann sollte dieses Argument auf NULL oder "" gesetzt werden.
- ea_set_file - ist der Dateiname einer .set-Datei, für dieses Argument sollte die Dateierweiterung .set angegeben werden.
- Die Argumente chart_symbol und chart tf geben die Eigenschaften des Diagramms an, zu dem das Programm hinzugefügt werden soll.
Zunächst wird die Methode SwitchToNewChart() aufgerufen. Diese Methode sucht unter den aktuell geöffneten Diagrammfenstern nach dem gewünschten Diagramm. Wenn es gefunden wird, wird der Fokus auf dieses gesetzt, andernfalls wird die Funktion ChartOpen() verwendet, um ein neues Diagramm zu öffnen. Die Methode ist auch für das Setzen der Eigenschaft m_chartid der Klasse verantwortlich.
Die Eigenschaft m_chartid wird dann verwendet, um zu prüfen, ob das Programm bereits zum Diagramm hinzugefügt worden ist. Wenn das Programm existiert, gibt die Methode true zurück.
//+------------------------------------------------------------------+ //|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); }
Wenn das Programm nicht gefunden wird, werden Vorbereitungen getroffen, um das Navigatorfenster zu durchsuchen. Wenn die Registerkarte "Common" des Navigatorfensters nicht sichtbar ist, wird sie aktiviert.
Nach der Aktivierung wird die Methode Findprogram() aufgerufen, um auf dem Steuerelement systreeview32 nach dem MetaTrader 5-Programm zu suchen. Die Methode nimmt die Hilfe der rekursiven Methode FindBranch() in Anspruch.
//+---------------------------------------------------------------------+ //|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() durchläuft das Steuerelement und erstellt auch die Zeichenkette der Referenz-ID, die den Pfad zum Speicherort des Programms auf dem systreeview32-Steuerelement angibt. Die Referenz-ID des Programms wird benötigt, damit AutoIt es auswählen und zum Diagramm hinzufügen kann.
//+-----------------------------------------------------------------------+ //|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; }
Wenn es sich bei dem Programm um einen Expert Advisor handelt und sich bereits ein anderer EA auf dem Chart befindet, erscheint an dieser Stelle ein Dialog, der den Ersatz des aktuell laufenden Expert Advisors bestätigt.
Wenn das gestartete Programm Eingaben hat, durchläuft die do...while-Schleife die Registerkarten, setzt die .set-Datei und aktiviert durch Ankreuzen von Schaltflächen den automatischen Handel und den dll-Export, falls erforderlich.
Am Ende gibt die Methode das Ergebnis der erneuten Überprüfung des Charts für das Programm zurück, um zu bestätigen, dass es dem Chart hinzugefügt wurde.
//+------------------------------------------------------------------+ //| 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() entfernt entweder ein Skript oder einen Expert Advisor von einem Chart. Dazu wird der Dialog des Expertenfensters über das Menü der Hauptanwendung aufgerufen. Die Methode iteriert dann durch die Liste der Programme und findet eine Übereinstimmung auf der Grundlage des Programmnamens und der Charteigenschaften (d.h. Chart-Symbol und Zeitrahmen).
Die Funktion ChartExpertRemoveAll() entfernt alle EAs und Skripte mit Ausnahme des Programms, das die Entfernungen tatsächlich vornimmt.
//+------------------------------------------------------------------+ //|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); }
Die Methoden GetLastExpertsLogEntry() und GetLastJournalEntry() geben den letzten Eintrag in das Expertenprotokoll bzw. das Journalprotokoll als String-Referenz zurück.
Die Methoden interagieren mit den Registerkarten "Journal" oder "Experts" und lesen nicht aus den eigentlichen Protokolldateien, sondern holen sich den Text aus dem listview32-Steuerelement. Wenn die Registerkarten manuell gelöscht wurden, können die Methoden keine Daten direkt aus den Protokolldateien abrufen.
//+------------------------------------------------------------------+ //|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; }
Die Funktionen GetLastExpertsLogEntryByText() und GetLastJournalEntryByText() geben den letzten Protokolleintrag zurück, der dem text_to_search_for Parameter entspricht. Die Funktionen beginnen die Suche mit dem jüngsten Protokolleintrag und gehen in der Zeit zurück. Der Parameter max_items_to_search_in legt die maximale Anzahl der Log-Einträge fest, die durchlaufen werden sollen. z.B. wenn er auf 10 gesetzt wird, durchläuft die Funktion die letzten 10 Log-Einträge auf der Suche nach einer Übereinstimmung. wenn dieser Parameter auf 0 oder eine negative Zahl gesetzt wird, dann durchläuft die Funktion alle Log-Einträge.
//+------------------------------------------------------------------+ //|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; }
Die Methode SetNotificationId() ist ein Rückgriff auf die ursprüngliche Demonstration dieses Konzepts. Sie nimmt einen String-Parameter mit maximal vier MetaQuotes-IDs entgegen.
//+------------------------------------------------------------------+ //|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); }
Die Funktion CloseAlertDialogue(), wenn sie aufgerufen wird, sucht nach einem Alert-Pop-up und schließt es.
//+------------------------------------------------------------------+ //| 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; }
Der Code für die gesamte Klasse ist im Folgenden dargestellt:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Verwendung der Klasse CTerminalController
Das erste Beispiel zeigt, wie man Programme auf einem Chart startet und sie auch wieder entfernt. Fügen Sie den Namen eines Programms hinzu, und geben Sie das Chart an. Der letzte Eingabeparameter gibt an, wie lange das hinzugefügte Programm in Sekunden laufen soll. Nach Ablauf der angegebenen Zeit wird das Programm entfernt, falls es noch läuft.
//+------------------------------------------------------------------+ //| 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(); } } //+------------------------------------------------------------------+
Der Expert Advisor HandleAlerts sendet bei jedem neuen Balken einen visuellen Pop-up-Alarm. Die Methode CloseAlertDialogue() wird verwendet, um alle vom Terminal generierten Popup-Dialoge zu schließen.
//+------------------------------------------------------------------+ //| 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(); } //+------------------------------------------------------------------+
Das letzte Beispiel ist das Send-Push-Skript. Das Skript funktioniert ähnlich wie das Beispiel im Artikel Verwaltung des MetaTrader-Terminals über 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; } } } //+------------------------------------------------------------------+
Schlussfolgerung
Der Artikel enthielt eine kurze Beschreibung, wie man mit AutoIt arbeitet. Wir haben erläutert, wie die AutoItX-Bibliothek durch die Integration mit MQL5 verwendet werden kann, und haben auch die Erstellung einer Klasse dokumentiert, die die dll von AutoIt verwendet. Die einzige Einschränkung bei der Verwendung der Bibliothek ist, dass es zu Zugriffsverletzungen kommt, wenn 2 oder mehr MetaTrader 5-Programme, die AutoItX verwenden, gleichzeitig ausgeführt werden. Es wird daher empfohlen, die Instanzen einzeln von MetaTrader 5-Programmen auszuführen, die auf AutoItX-Code verweisen.
Verzeichnis | Inhalt | Beschreibung |
---|---|---|
MetaTrader 5zip\MQL5\include | autoIt.mqh, autoItbase.mqh,terminalcontroller.mqh | autoIt.mqh enthält AutoItX Funktionsimport-Anweisungen, autoItbase.mqh enthält die Klasse CAutoIt und terminalcontroller.mqh die Klasse CTerminalController. |
MetaTrader 5zip\MQL5\Experts | TerminalController.mq5,HandleAlerts.mq5 | Der EA TerminalController demonstriert das automatische Entfernen und Hinzufügen von Expert Advisors oder Skripten aus einem Chart. Der EA HandleAlerts zeigt, wie man die Handhabung von Popup-Alarm-Fenstern automatisiert |
MetaTrader 5zip\MQL5\Scripts | TerminalUIComponents.mq5,Send_Push.mq5 | TerminalUICommpents demonstriert die Verwendung von AutoItX, indem es die importierten Funktionen direkt aufruft. Das Skript Send_Push fügt dem Terminal neue MetaQuotes-IDs hinzu, bevor es eine Benachrichtigung sendet. |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/10130





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.