Andere Klassen in der Bibliothek DoEasy (Teil 68): Die Chartfenster-Objektklasse und die Indikator-Objektklassen im Chartfenster
Inhalt
Konzept
Im vorigen Artikel habe ich mit der Entwicklung der Chart-Objektklasse begonnen und ihre erste Version vorbereitet. Das Objekt beschreibt ein Terminal Chart mit all seinen Parametern. Es ermöglicht die Verwaltung seiner Eigenschaften — das Abrufen und Installieren der Fenstergröße und der Anzeigeparameter der Chart-Elemente.
In unserem Fall kann ein Chart mehrere Fenster aufweisen, die wiederum Indikatoren enthalten können. Die Fenster haben ihre eigene Größe, während unser Chart-Objekt vorerst einfach die Parameter des angegebenen Unterfensters, das sich auf ihm befindet, zurückgeben und seine Höhe verwalten kann. Ein Unterfenster kann (genau wie das Hauptfenster des Charts) eine unterschiedliche Anzahl von Indikatoren enthalten. Wir sollten dies berücksichtigen, um Zugriff auf das Chart-Objekt eines benötigtes Fenster, das sich auf dem Chart befindet, erhalten zu können. Mit Hilfe des erhaltenen Fenster-Objekts können wir dann die Liste seiner Indikatoren abfragen und das Handle des notwendigen Fensters für die weitere Verarbeitung erhalten.
Heute werde ich zwei Objekte erstellen — das Indikator-Objekt im Chartfenster, das einige Indikator-Parameter für seine Identifizierung beschreiben wird, und das Chartfenster-Objekt, das seine Größe und die Liste der Indikatoren (Indikator-Objekte im Chartfenster), die mit ihm verbunden sind, speichern soll. Das Chart-Objekt, mit dessen Entwicklung ich im vorigen Artikel begonnen habe, soll die Liste der daran angehängten Fenster-Objekte (einschließlich des Fensters mit dem Hauptchart) enthalten.
In der Zukunft wird eine solche Hierarchie unsere Arbeit mit vielen Charts und deren Unterfenstern, die die Listen der Indikatoren enthalten, erheblich erleichtern. Leider ist es noch zu früh, um die im vorherigen Artikel angekündigte Kollektionsklasse von Chart-Objekten zu erstellen. Zuerst müssen wir alle Hauptverbesserungen am Chart-Objekt fertigstellen. Genau das werde ich hier tun.
Die Klasse des Chartfensters mit Indikatorobjekten
Fügen wir zunächst alle notwendigen Nachrichten in die Bibliothek ein.
In \MQL5\Include\DoEasy\Data.mqh fügen wir die Indizes der neuen Nachrichten ein:
MSG_CHART_OBJ_CHART_WINDOW, // Main chart window MSG_CHART_OBJ_CHART_SUBWINDOW, // Chart subwindow MSG_CHART_OBJ_CHART_SUBWINDOWS_NUM, // Subwindows MSG_CHART_OBJ_INDICATORS_MW_NAME_LIST, // Indicators in the main chart window MSG_CHART_OBJ_INDICATORS_SW_NAME_LIST, // Indicators in the chart window MSG_CHART_OBJ_INDICATOR, // Indicator MSG_CHART_OBJ_INDICATORS_TOTAL, // Indicators MSG_CHART_OBJ_WINDOW_N, // Window MSG_CHART_OBJ_INDICATORS_NONE, // No indicators }; //+------------------------------------------------------------------+
und die Nachrichtentexte entsprechend den neu hinzugefügten Indizes:
{"Главное окно графика","Main chart window"}, {"Подокно графика","Chart subwindow"}, {"Подокон","Subwindows"}, {"Индикаторы в главном окне графика","Indicators in the main chart window"}, {"Индикаторы в окне графика","Indicators in the chart window"}, {"Индикатор","Indicator"}, {"Индикаторов","Indicators total"}, {"Окно","Window"}, {"Отсутствуют","No indicators"}, }; //+---------------------------------------------------------------------+
Bei der Erstellung der Enumeration der Eigenschaften des Integer-Chartobjekts habe ich absichtlich drei Eigenschaften übersprungen, die nicht nur zum Hauptfensterobjekt, sondern auch zu allen Chart-Unterfenstern gehören:
- Sichtbarkeit des Unterfensters,
- Abstand in Pixeln auf der Y-Achse zwischen dem oberen Rahmen des Indikator-Unterfensters und dem oberen Rahmen des Chart-Hauptfensters,
- Chart-Höhe in Pixeln.
Dies sind die Haupteigenschaften des Fensterobjekts der Charts (abgesehen von der Sichtbarkeit der Unterfenster, die wir vom Chart-Objekt aus definieren werden). Die Liste der Chartfenster soll in jedem Chart-Objekt vorhanden sein, und jedes Objekt soll seine eigenen Werte für diese Eigenschaften haben. Jedes Fensterobjekt soll die Liste der Indikatoren enthalten, die dem Fenster zugeordnet sind. Wir müssen also zusätzliche Konstanten in den Aufzählungen der Integer- und String-Chart-Objekteigenschaften setzen.
In \MQL5\Include\DoEasy\Defines.mqh, entfernen wir die zuvor definierten und auskommentierten Eigenschaften — das sind die Eigenschaften des Chartfensterobjekts und fügen Sie die neuen hinzu — für das Indikatorobjekt im Chartfenster:
//+------------------------------------------------------------------+ //| Chart integer property | //+------------------------------------------------------------------+ enum ENUM_CHART_PROP_INTEGER { CHART_PROP_ID = 0, // Chart ID CHART_PROP_TIMEFRAME, // Chart timeframe CHART_PROP_SHOW, // Price chart drawing CHART_PROP_IS_OBJECT, // Chart object (OBJ_CHART) identification attribute CHART_PROP_BRING_TO_TOP, // Show chart above all others CHART_PROP_CONTEXT_MENU, // Enable/disable access to the context menu using the right click CHART_PROP_CROSSHAIR_TOOL, // Enable/disable access to the Crosshair tool using the middle click CHART_PROP_MOUSE_SCROLL, // Scroll the chart horizontally using the left mouse button CHART_PROP_EVENT_MOUSE_WHEEL, // Send messages about mouse wheel events (CHARTEVENT_MOUSE_WHEEL) to all MQL5 programs on a chart CHART_PROP_EVENT_MOUSE_MOVE, // Send messages about mouse button click and movement events (CHARTEVENT_MOUSE_MOVE) to all MQL5 programs on a chart CHART_PROP_EVENT_OBJECT_CREATE, // Send messages about the graphical object creation event (CHARTEVENT_OBJECT_CREATE) to all MQL5 programs on a chart CHART_PROP_EVENT_OBJECT_DELETE, // Send messages about the graphical object destruction event (CHARTEVENT_OBJECT_DELETE) to all MQL5 programs on a chart CHART_PROP_MODE, // Type of the chart (candlesticks, bars or line (ENUM_CHART_MODE)) CHART_PROP_FOREGROUND, // Price chart in the foreground CHART_PROP_SHIFT, // Mode of shift of the price chart from the right border CHART_PROP_AUTOSCROLL, // The mode of automatic shift to the right border of the chart CHART_PROP_KEYBOARD_CONTROL, // Allow managing the chart using a keyboard CHART_PROP_QUICK_NAVIGATION, // Allow the chart to intercept Space and Enter key strokes to activate the quick navigation bar CHART_PROP_SCALE, // Scale CHART_PROP_SCALEFIX, // Fixed scale mode CHART_PROP_SCALEFIX_11, // 1:1 scale mode CHART_PROP_SCALE_PT_PER_BAR, // The mode of specifying the scale in points per bar CHART_PROP_SHOW_TICKER, // Display a symbol ticker in the upper left corner CHART_PROP_SHOW_OHLC, // Display OHLC values in the upper left corner CHART_PROP_SHOW_BID_LINE, // Display Bid value as a horizontal line on the chart CHART_PROP_SHOW_ASK_LINE, // Display Ask value as a horizontal line on a chart CHART_PROP_SHOW_LAST_LINE, // Display Last value as a horizontal line on a chart CHART_PROP_SHOW_PERIOD_SEP, // Display vertical separators between adjacent periods CHART_PROP_SHOW_GRID, // Display a grid on the chart CHART_PROP_SHOW_VOLUMES, // Display volumes on a chart CHART_PROP_SHOW_OBJECT_DESCR, // Display text descriptions of objects CHART_PROP_VISIBLE_BARS, // Number of bars on a chart that are available for display CHART_PROP_WINDOWS_TOTAL, // The total number of chart windows including indicator subwindows CHART_PROP_WINDOW_IS_VISIBLE, // Subwindow visibility CHART_PROP_WINDOW_HANDLE, // Chart window handle CHART_PROP_WINDOW_YDISTANCE, // Distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window CHART_PROP_FIRST_VISIBLE_BAR, // Number of the first visible bar on the chart CHART_PROP_WIDTH_IN_BARS, // Width of the chart in bars CHART_PROP_WIDTH_IN_PIXELS, // Width of the chart in pixels CHART_PROP_HEIGHT_IN_PIXELS, // Height of the chart in pixels CHART_PROP_COLOR_BACKGROUND, // Color of background of the chart CHART_PROP_COLOR_FOREGROUND, // Color of axes, scale and OHLC line CHART_PROP_COLOR_GRID, // Grid color CHART_PROP_COLOR_VOLUME, // Color of volumes and position opening levels CHART_PROP_COLOR_CHART_UP, // Color for the up bar, shadows and body borders of bull candlesticks CHART_PROP_COLOR_CHART_DOWN, // Color of down bar, its shadow and border of body of the bullish candlestick CHART_PROP_COLOR_CHART_LINE, // Color of the chart line and the Doji candlesticks CHART_PROP_COLOR_CANDLE_BULL, // Color of body of a bullish candlestick CHART_PROP_COLOR_CANDLE_BEAR, // Color of body of a bearish candlestick CHART_PROP_COLOR_BID, // Color of the Bid price line CHART_PROP_COLOR_ASK, // Color of the Ask price line CHART_PROP_COLOR_LAST, // Color of the last performed deal's price line (Last) CHART_PROP_COLOR_STOP_LEVEL, // Color of stop order levels (Stop Loss and Take Profit) CHART_PROP_SHOW_TRADE_LEVELS, // Display trade levels on the chart (levels of open positions, Stop Loss, Take Profit and pending orders) CHART_PROP_DRAG_TRADE_LEVELS, // Enable the ability to drag trading levels on a chart using mouse CHART_PROP_SHOW_DATE_SCALE, // Display the time scale on a chart CHART_PROP_SHOW_PRICE_SCALE, // Display a price scale on a chart CHART_PROP_SHOW_ONE_CLICK, // Display the quick trading panel on the chart CHART_PROP_IS_MAXIMIZED, // Chart window maximized CHART_PROP_IS_MINIMIZED, // Chart window minimized CHART_PROP_IS_DOCKED, // Chart window docked CHART_PROP_FLOAT_LEFT, // Left coordinate of the undocked chart window relative to the virtual screen CHART_PROP_FLOAT_TOP, // Upper coordinate of the undocked chart window relative to the virtual screen CHART_PROP_FLOAT_RIGHT, // Right coordinate of the undocked chart window relative to the virtual screen CHART_PROP_FLOAT_BOTTOM, // Bottom coordinate of the undocked chart window relative to the virtual screen //--- CWndInd CHART_PROP_WINDOW_IND_HANDLE, // Indicator handle in the chart window CHART_PROP_WINDOW_IND_INDEX, // Indicator index in the chart window }; #define CHART_PROP_INTEGER_TOTAL (67) // Total number of integer properties #define CHART_PROP_INTEGER_SKIP (0) // Number of integer DOM properties not used in sorting //+------------------------------------------------------------------+ //| Chart real properties | //+------------------------------------------------------------------+ enum ENUM_CHART_PROP_DOUBLE { CHART_PROP_SHIFT_SIZE = CHART_PROP_INTEGER_TOTAL, // Shift size of the zero bar from the right border in % CHART_PROP_FIXED_POSITION, // Chart fixed position from the left border in % CHART_PROP_FIXED_MAX, // Chart fixed maximum CHART_PROP_FIXED_MIN, // Chart fixed minimum CHART_PROP_POINTS_PER_BAR, // Scale in points per bar CHART_PROP_PRICE_MIN, // Chart minimum CHART_PROP_PRICE_MAX, // Chart maximum }; #define CHART_PROP_DOUBLE_TOTAL (7) // Total number of real properties #define CHART_PROP_DOUBLE_SKIP (0) // Number of real properties not used in sorting //+------------------------------------------------------------------+ //| Chart string properties | //+------------------------------------------------------------------+ enum ENUM_CHART_PROP_STRING { CHART_PROP_COMMENT = (CHART_PROP_INTEGER_TOTAL+CHART_PROP_DOUBLE_TOTAL), // Chart comment text CHART_PROP_EXPERT_NAME, // Name of an EA launched on the chart CHART_PROP_SCRIPT_NAME, // Name of a script launched on the chart CHART_PROP_INDICATOR_NAME, // Name of an indicator launched on the chart CHART_PROP_SYMBOL, // Chart symbol }; #define CHART_PROP_STRING_TOTAL (5) // Total number of string properties //+------------------------------------------------------------------+
Wir ändern die Anzahl der Eigenschaften mit Aufzählungen mit neuen Konstanten — die Anzahl der Integer-Eigenschaften erhöht sich von 62 auf 67, während die Anzahl der String-Eigenschaften von 4 auf 5 erhöht wird.
Fügen wir also in der Enumeration der möglichen Chart-Objekt-Sortierkriterien die neuen Kriterien hinzu, die den neu hinzugefügten Eigenschaften entsprechen:
//+------------------------------------------------------------------+ //| Possible chart sorting criteria | //+------------------------------------------------------------------+ #define FIRST_CHART_DBL_PROP (CHART_PROP_INTEGER_TOTAL-CHART_PROP_INTEGER_SKIP) #define FIRST_CHART_STR_PROP (CHART_PROP_INTEGER_TOTAL-CHART_PROP_INTEGER_SKIP+CHART_PROP_DOUBLE_TOTAL-CHART_PROP_DOUBLE_SKIP) enum ENUM_SORT_CHART_MODE { //--- Sort by integer properties SORT_BY_CHART_SHOW = 0, // Sort by the price chart drawing attribute SORT_BY_CHART_IS_OBJECT, // Sort by chart object (OBJ_CHART) identification attribute SORT_BY_CHART_BRING_TO_TOP, // Sort by the flag of displaying a chart above all others SORT_BY_CHART_CONTEXT_MENU, // Sort by the flag of enabling/disabling access to the context menu using the right click SORT_BY_CHART_CROSSHAIR_TOO, // Sort by the flag of enabling/disabling access to the Crosshair tool using the middle click SORT_BY_CHART_MOUSE_SCROLL, // Sort by the flag of scrolling the chart horizontally using the left mouse button SORT_BY_CHART_EVENT_MOUSE_WHEEL, // Sort by the flag of sending messages about mouse wheel events to all MQL5 programs on a chart SORT_BY_CHART_EVENT_MOUSE_MOVE, // Sort by the flag of sending messages about mouse button click and movement events to all MQL5 programs on a chart SORT_BY_CHART_EVENT_OBJECT_CREATE, // Sort by the flag of sending messages about the graphical object creation event to all MQL5 programs on a chart SORT_BY_CHART_EVENT_OBJECT_DELETE, // Sort by the flag of sending messages about the graphical object destruction event to all MQL5 programs on a chart SORT_BY_CHART_MODE, // Sort by chart type SORT_BY_CHART_FOREGROUND, // Sort by the "Price chart in the foreground" flag SORT_BY_CHART_SHIFT, // Sort by the "Mode of shift of the price chart from the right border" flag SORT_BY_CHART_AUTOSCROLL, // Sort by the "The mode of automatic shift to the right border of the chart" flag SORT_BY_CHART_KEYBOARD_CONTROL, // Sort by the flag allowing the chart management using a keyboard SORT_BY_CHART_QUICK_NAVIGATION, // Sort by the flag allowing the chart to intercept Space and Enter key strokes to activate the quick navigation bar SORT_BY_CHART_SCALE, // Sort by scale SORT_BY_CHART_SCALEFIX, // Sort by the fixed scale flag SORT_BY_CHART_SCALEFIX_11, // Sort by the 1:1 scale flag SORT_BY_CHART_SCALE_PT_PER_BAR, // Sort by the flag of specifying the scale in points per bar SORT_BY_CHART_SHOW_TICKER, // Sort by the flag displaying a symbol ticker in the upper left corner SORT_BY_CHART_SHOW_OHLC, // Sort by the flag displaying OHLC values in the upper left corner SORT_BY_CHART_SHOW_BID_LINE, // Sort by the flag displaying Bid value as a horizontal line on the chart SORT_BY_CHART_SHOW_ASK_LINE, // Sort by the flag displaying Ask value as a horizontal line on the chart SORT_BY_CHART_SHOW_LAST_LINE, // Sort by the flag displaying Last value as a horizontal line on the chart SORT_BY_CHART_SHOW_PERIOD_SEP, // Sort by the flag displaying vertical separators between adjacent periods SORT_BY_CHART_SHOW_GRID, // Sort by the flag of displaying a grid on the chart SORT_BY_CHART_SHOW_VOLUMES, // Sort by the mode of displaying volumes on a chart SORT_BY_CHART_SHOW_OBJECT_DESCR, // Sort by the flag of displaying object text descriptions SORT_BY_CHART_VISIBLE_BARS, // Sort by the number of bars on a chart that are available for display SORT_BY_CHART_WINDOWS_TOTAL, // Sort by the total number of chart windows including indicator subwindows SORT_BY_CHART_WINDOW_IS_VISIBLE, // Sort by the subwindow visibility flag SORT_BY_CHART_WINDOW_HANDLE, // Sort by the chart handle SORT_BY_CHART_WINDOW_YDISTANCE, // Sort by the distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window SORT_BY_CHART_FIRST_VISIBLE_BAR, // Sort by the number of the first visible bar on the chart SORT_BY_CHART_WIDTH_IN_BARS, // Sort by the width of the chart in bars SORT_BY_CHART_WIDTH_IN_PIXELS, // Sort by the width of the chart in pixels SORT_BY_CHART_HEIGHT_IN_PIXELS, // Sort by the height of the chart in pixels SORT_BY_CHART_COLOR_BACKGROUND, // Sort by the color of the chart background SORT_BY_CHART_COLOR_FOREGROUND, // Sort by color of axes, scale and OHLC line SORT_BY_CHART_COLOR_GRID, // Sort by grid color SORT_BY_CHART_COLOR_VOLUME, // Sort by the color of volumes and position opening levels SORT_BY_CHART_COLOR_CHART_UP, // Sort by the color for the up bar, shadows and body borders of bull candlesticks SORT_BY_CHART_COLOR_CHART_DOWN, // Sort by the color of down bar, its shadow and border of body of the bullish candlestick SORT_BY_CHART_COLOR_CHART_LINE, // Sort by the color of the chart line and the Doji candlesticks SORT_BY_CHART_COLOR_CANDLE_BULL, // Sort by the color of a bullish candlestick body SORT_BY_CHART_COLOR_CANDLE_BEAR, // Sort by the color of a bearish candlestick body SORT_BY_CHART_COLOR_BID, // Sort by the color of the Bid price line SORT_BY_CHART_COLOR_ASK, // Sort by the color of the Ask price line SORT_BY_CHART_COLOR_LAST, // Sort by the color of the last performed deal's price line (Last) SORT_BY_CHART_COLOR_STOP_LEVEL, // Sort by the color of stop order levels (Stop Loss and Take Profit) SORT_BY_CHART_SHOW_TRADE_LEVELS, // Sort by the flag of displaying trading levels on the chart SORT_BY_CHART_DRAG_TRADE_LEVELS, // Sort by the flag enabling the ability to drag trading levels on a chart using mouse SORT_BY_CHART_SHOW_DATE_SCALE, // Sort by the flag of displaying the time scale on the chart SORT_BY_CHART_SHOW_PRICE_SCALE, // Sort by the flag of displaying the price scale on the chart SORT_BY_CHART_SHOW_ONE_CLICK, // Sort by the flag of displaying the quick trading panel on the chart SORT_BY_CHART_IS_MAXIMIZED, // Sort by the "Chart window maximized" flag SORT_BY_CHART_IS_MINIMIZED, // Sort by the "Chart window minimized" flag SORT_BY_CHART_IS_DOCKED, // Sort by the "Chart window docked" flag SORT_BY_CHART_FLOAT_LEFT, // Sort by the left coordinate of the undocked chart window relative to the virtual screen SORT_BY_CHART_FLOAT_TOP, // Sort by the upper coordinate of the undocked chart window relative to the virtual screen SORT_BY_CHART_FLOAT_RIGHT, // Sort by the right coordinate of the undocked chart window relative to the virtual screen SORT_BY_CHART_FLOAT_BOTTOM, // Sort by the bottom coordinate of the undocked chart window relative to the virtual screen SORT_BY_CHART_WINDOW_IND_HANDLE, // Sort by the indicator handle in the chart window SORT_BY_CHART_WINDOW_IND_INDEX, // Sort by the indicator index in the chart window //--- Sort by real properties SORT_BY_CHART_SHIFT_SIZE = FIRST_CHART_DBL_PROP, // Sort by the shift size of the zero bar from the right border in % SORT_BY_CHART_FIXED_POSITION, // Sort by the chart fixed position from the left border in % SORT_BY_CHART_FIXED_MAX, // Sort by the fixed chart maximum SORT_BY_CHART_FIXED_MIN, // Sort by the fixed chart minimum SORT_BY_CHART_POINTS_PER_BAR, // Sort by the scale value in points per bar SORT_BY_CHART_PRICE_MIN, // Sort by the chart minimum SORT_BY_CHART_PRICE_MAX, // Sort by the chart maximum //--- Sort by string properties SORT_BY_CHART_COMMENT = FIRST_CHART_STR_PROP, // Sort by a comment text on the chart SORT_BY_CHART_EXPERT_NAME, // Sort by a name of an EA launched on the chart SORT_BY_CHART_SCRIPT_NAME, // Sort by a name of a script launched on the chart SORT_BY_CHART_INDICATOR_NAME, // Sort by a name of an indicator launched on the chart SORT_BY_CHART_SYMBOL, // Sort by chart symbol }; //+------------------------------------------------------------------+
In der ersten Version des Chart-Objekts war die Liste der Kriterien nicht korrekt, weil auskommentierte Integer-Chart-Eigenschaften zu den Sortierkriterien hinzugefügt wurden und es keine Sortierung nach Symbolnamen gab. Dies habe ich im aktuellen Artikel behoben.
Jetzt muss ich zwei Klassen erstellen — die Klasse des Indikatorobjekts im Chartfenster und die Klasse des Chartfensterobjekts. Fügen wir sie auf einmal in eine Datei ein.
Erstellen wir in \MQL5\Include\DoEasy\Objects\Chart\ eine neue Datei ChartWnd.mqh mit den Klassen CWndInd (Indikator im Chartfenster) und CChartWnd (Chartfenster).
Die Klasse CWndInd sollte von der Basisklasse der Standardbibliothek CObject abgeleitet werden, während die Klasse CChartWnd — vom Basisobjekt aller Bibliotheksobjekte CBaseObj.
Viele verschiedene Indikatoren können an das Chartfenster angehängt werden. Das Chartfenster-Objekt sollte sie kennen, so dass wir immer in der Lage sind, das Handle des benötigten Indikators aus dem Chartfenster zu holen, um mit ihm zu arbeiten. Wir brauchen nicht viele verschiedene Parameter, um Indikatoren zu identifizieren. Das Indikator-Handle, sein Kurzname und ein Index des Chartfensters, an das der Indikator angehängt ist, sind ausreichend. Deshalb wird die Indikator-Objektklasse im Chartfenster die einfachste sein und vom Basis-Objekt der Standardbibliothek geerbt werden, so dass wir alle diese Objekte zur Liste der Zeiger auf CArrayObj-Objekte hinzufügen können, die sich im Chartfenster-Objekt befindet.
Lassen Sie uns den Code der neuen Klasse in die neu erstellte Datei ChartWnd.mqh schreiben:
//+------------------------------------------------------------------+ //| ChartWnd.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\..\Objects\BaseObj.mqh" //+------------------------------------------------------------------+ //| Chart window indicator object class | //+------------------------------------------------------------------+ class CWndInd : public CObject { private: long m_chart_id; // Chart ID string m_name; // Indicator short name int m_index; // Window index on the chart int m_handle; // Indicator handle public: //--- Return itself CWndInd *GetObject(void) { return &this; } //--- Return (1) indicator name, (2) window index and (3) indicator handle string Name(void) const { return this.m_name; } int Index(void) const { return this.m_index; } int Handle(void) const { return this.m_handle; } //--- Display the description of object properties in the journal (dash=true - hyphen before the description, false - description only) void Print(const bool dash=false) { ::Print((dash ? "- " : "")+this.Header()); } //--- Return the object short name string Header(void) const { return CMessage::Text(MSG_CHART_OBJ_INDICATOR)+" "+this.Name(); } //--- Compare CWndInd objects with each other by the specified property virtual int Compare(const CObject *node,const int mode=0) const; //--- Constructors CWndInd(void); CWndInd(const int handle,const string name,const int index) : m_handle(handle),m_name(name),m_index(index) {} }; //+------------------------------------------------------------------+ //| Compare CWndInd objects with each other by the specified property| //+------------------------------------------------------------------+ int CWndInd::Compare(const CObject *node,const int mode=0) const { const CWndInd *obj_compared=node; if(mode==CHART_PROP_WINDOW_IND_HANDLE) return(this.Handle()>obj_compared.Handle() ? 1 : this.Handle()<obj_compared.Handle() ? -1 : 0); else if(mode==CHART_PROP_WINDOW_IND_INDEX) return(this.Index()>obj_compared.Index() ? 1 : this.Index()<obj_compared.Index() ? -1 : 0); return(this.Name()==obj_compared.Name() ? 0 : this.Name()<obj_compared.Name() ? -1 : 1); } //+------------------------------------------------------------------+
Dies ist eine ganze Indikator-Objektklasse im Chartfenster.
Der private Abschnitt enthält die zu speichernden Variablen der Klassenvariablen:
- die ID des Charts, in dem sich das Fenster mit dem Indikator befindet,
- den Kurzname des Indikators (in den Chartfenstern werden die Indikatoren vom Terminal durch ihre Kurznamen identifiziert),
- den Index des Chartfensters, in dem sich der Indikator befindet (0 — Hauptfenster des Charts, 1, usw. — Unterfenster des Charts),
- Indikator-Handle.
Diese Daten reichen aus, um die Liste aller Indikatoren zu speichern, die dem Fenster im Chartfenster-Objekt zugeordnet sind. Die Liste selbst soll die Objekte enthalten, die uns erlauben, den notwendigen Indikator zu finden und sein Handle für die weitere Arbeit zurückzugeben.
Die öffentlichen Methoden, die die Werte der oben genannten Variablen zurückgeben, sind selbsterklärend. Betrachten wir nun einige andere Methoden der Klasse.
Die Methode, die den Kurznamen des Indikatorobjekts zurückgibt:
//--- Return the object short name string Header(void) const { return CMessage::Text(MSG_CHART_OBJ_INDICATOR)+" "+this.Name(); }
Es wird einfach der Indikatorkopf + Indikatorkurznamen zurückgegeben.
Die Methode, die die Beschreibung der Eigenschaften des Indikatorobjekts im Journal anzeigt:
//--- Display the description of object properties in the journal (dash=true - hyphen before the description, false - description only) void Print(const bool dash=false) { ::Print((dash ? "- " : "")+this.Header()); }
Da es im Chartfenster mehrere Indikatoren geben kann, sollen diese als Liste mit einer Überschrift angezeigt werden. Um die Liste im Journal optisch ansprechender zu gestalten, werde ich den Bindestrich vor einem Indikatornamen verwenden. Die Methodeneingabe wird die Notwendigkeit der Anzeige des Bindestrichs anzeigen.
Wir haben zwei Konstruktoren: den Standardkonstruktor und den parametrischen. Der Standard-Konstruktor kann für die Erstellung eines "leeren" Indikatorobjekts im Fenster hilfreich sein, während der parametrische als Hauptklassenkonstruktor bei der Erstellung der Liste der Indikatoren in der Objektklasse des Chartfensters verwendet werden soll.
Der parametrische Konstruktor erhält das Indikator-Handle, seinen Kurznamen und den Index des Teilfensters, in dem sich der Indikator befindet.
//--- Constructors CWndInd(void); CWndInd(const int handle,const string name,const int index) : m_handle(handle),m_name(name),m_index(index) {}
Alle Parameterwerte, die der Methode übergeben werden, werden sofort den Klassenvariablen in ihrer Initialisierungsliste zugewiesen.
Die Methode zum Vergleich der Indikatorobjekte des Chartfensters anhand der angegebenen Eigenschaft:
//+------------------------------------------------------------------+ //| Compare CWndInd objects with each other by the specified property| //+------------------------------------------------------------------+ int CWndInd::Compare(const CObject *node,const int mode=0) const { const CWndInd *obj_compared=node; if(mode==CHART_PROP_WINDOW_IND_HANDLE) return(this.Handle()>obj_compared.Handle() ? 1 : this.Handle()<obj_compared.Handle() ? -1 : 0); else if(mode==CHART_PROP_WINDOW_IND_INDEX) return(this.Index()>obj_compared.Index() ? 1 : this.Index()<obj_compared.Index() ? -1 : 0); return(this.Name()==obj_compared.Name() ? 0 : this.Name()<obj_compared.Name() ? -1 : 1); } //+------------------------------------------------------------------+
Wir haben keine nutzerdefinierten Enumerationen von Eigenschaften für dieses Objekt. Alle seine Eigenschaften sind in den Enumerationen der Chart-Objekteigenschaften enthalten. Daher kann die Methode beliebige Chart-Objekteigenschaften erhalten. Der Vergleich durch die übergebenen Eigenschaften wird jedoch nur durchgeführt, wenn der Modus die Eigenschaft "Indikator-Handle" oder "Chartfensterindex" erhält. In allen anderen Fällen wird der Vergleich über den Indikator-Kurznamen durchgeführt.
Die Vergleichsmethode ist standardmäßig für alle Bibliotheksobjekte: ist der Parameterwert des aktuellen Objekts größer als der des verglichenen, wird 1 zurückgegeben. Ist er kleiner, dann wird -1 zurückgegeben, ansonsten 0.
Beginnen wir mit der Entwicklung der Objektklasse des Chartfensters.
Ich werde die Entwicklung des Codes fortsetzen und die Objektklasse Chartfenster in die Datei schreiben, die die Klasse des Indikatorobjekts im Chartfenster enthält (ChartWnd.mqh). Die Klasse soll vom Basisobjekt aller CBaseObj-Bibliotheksobjekte abgeleitet werden:
//+------------------------------------------------------------------+ //| Chart window object class | //+------------------------------------------------------------------+ class CChartWnd : public CBaseObj { }
Der private Teil der Klasse soll die Liste der Zeiger auf Indikatorobjekte in diesem Fenster, einen Index des durch das Objekt beschriebenen Unterfensters und zusätzliche Methoden zur Gestaltung des Klassenbetriebs enthalten:
//+------------------------------------------------------------------+ //| Chart window object class | //+------------------------------------------------------------------+ class CChartWnd : public CBaseObj { private: CArrayObj m_list_ind; // Indicator list int m_window_num; // Subwindow index //--- Return the flag indicating the presence of an indicator from the list in the window bool IsPresentInWindow(const CWndInd *ind); //--- Remove indicators not present in the window from the list void IndicatorsDelete(void); //--- Add new indicators to the list void IndicatorsAdd(void); //--- Set a subwindow index void SetWindowNum(const int num) { this.m_window_num=num; } public:
Der öffentliche Teil der Klasse enthält Standardmethoden (mit Ausnahme der Methoden, die die Eigenschaftswerte setzen — da das Objekt keine benutzerdefinierten Eigenschaftsaufzählungslisten hat, werden wir nur die erforderlichen Werte zurückgeben, die durch einige Eigenschaften des Chart-Objekts beschrieben werden, die zum Chartfenster gehören). Diese Methoden wurden in den vorangegangenen Artikeln bereits mehrfach berücksichtigt.
Außerdem verfügt die Klasse über Methoden zum Setzen und Zurückgeben von Fenstereigenschaftswerten, sowie zum Arbeiten mit der Klasse. Diese werde ich im Folgenden näher betrachten.
//+------------------------------------------------------------------+ //| Chart window object class | //+------------------------------------------------------------------+ class CChartWnd : public CBaseObj { private: CArrayObj m_list_ind; // Indicator list int m_window_num; // Subwindow index //--- Return the flag indicating the presence of an indicator from the list in the window bool IsPresentInWindow(const CWndInd *ind); //--- Remove indicators not present in the window from the list void IndicatorsDelete(void); //--- Add new indicators to the list void IndicatorsAdd(void); //--- Set a subwindow index void SetWindowNum(const int num) { this.m_window_num=num; } public: //--- Return itself CChartWnd *GetObject(void) { return &this; } //--- Return the flag of the object supporting this property virtual bool SupportProperty(ENUM_CHART_PROP_INTEGER property) { return(property==CHART_PROP_WINDOW_YDISTANCE || property==CHART_PROP_HEIGHT_IN_PIXELS ? true : false); } virtual bool SupportProperty(ENUM_CHART_PROP_DOUBLE property) { return false; } virtual bool SupportProperty(ENUM_CHART_PROP_STRING property) { return (property==CHART_PROP_INDICATOR_NAME ? true : false); } //--- Get description of (1) integer, (2) real and (3) string properties string GetPropertyDescription(ENUM_CHART_PROP_INTEGER property); string GetPropertyDescription(ENUM_CHART_PROP_DOUBLE property) { return CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED); } string GetPropertyDescription(ENUM_CHART_PROP_STRING property) { return CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED); } //--- Display the description of object properties in the journal (full_prop=true - all properties, false - supported ones only) void Print(const bool full_prop=false); //--- Display a short description of the object in the journal virtual void PrintShort(const bool dash=false); //--- Return the object short name virtual string Header(void); //--- Compare CChartWnd objects by a specified property (to sort the list by an MQL5 signal object) virtual int Compare(const CObject *node,const int mode=0) const; //--- Compare CChartWnd objects by all properties (to search for equal MQL5 signal objects) bool IsEqual(CChartWnd* compared_obj) const; //--- Constructors CChartWnd(void); CChartWnd(const long chart_id,const int wnd_num); //--- Return the distance in pixels between the window borders int YDistance(void) const { return (int)::ChartGetInteger(this.m_chart_id,CHART_WINDOW_YDISTANCE,this.m_window_num);} //--- (1) Return and (2) set the window height in pixels int HeightInPixels(void) const { return (int)::ChartGetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS,this.m_window_num);} bool SetHeightInPixels(const int value,const bool redraw=false); //--- Return (1) the subwindow index and (2) the number of indicators attached to the window int WindowNum(void) const { return this.m_window_num;} int IndicatorsTotal(void) const { return this.m_list_ind.Total(); } //--- Return (1) the indicator list and (2) the window indicator object from the list by index CArrayObj *GetIndicatorsList(void) { return &this.m_list_ind; } CWndInd *GetIndicator(const int index) { return this.m_list_ind.At(index); } //--- Display the description of indicators attached to the chart window in the journal void PrintIndicators(const bool dash=false); //--- Display the description of the window parameters in the journal void PrintParameters(const bool dash=false); //--- Create the list of indicators attached to the window void IndicatorsListCreate(void); //--- Update data on attached indicators void Refresh(void); }; //+------------------------------------------------------------------+
Die Methode gibt den Abstand in Pixeln zwischen den Fenstergrenzen zurück:
//--- Return the distance in pixels between the window borders int YDistance(void) const { return (int)::ChartGetInteger(this.m_chart_id,CHART_WINDOW_YDISTANCE,this.m_window_num);}
Da die Chart-Eigenschaft CHART_WINDOW_YDISTANCE schreibgeschützt ist, gibt es hier keine Methode, die den Wert setzt. Die Methode gibt einfach den Wert der Eigenschaft für dieses bestimmte Unterfenster des Chart zurück.
Die Methode gibt die Fensterhöhe in Pixel zurück:
int HeightInPixels(void) const { return (int)::ChartGetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS,this.m_window_num);}
Die Methode arbeitet ähnlich wie die obige und liefert den Eigenschaftswert für den Index des in der Variablen m_window_num angegebenen Fensters.
Die Methode zum Setzen der Fensterhöhe in Pixel (deklariert im Klassenkörper, während sie außerhalb des Klassenkörpers implementiert ist):
//+------------------------------------------------------------------+ //| Set the window height in pixels | //+------------------------------------------------------------------+ bool CChartWnd::SetHeightInPixels(const int value,const bool redraw=false) { ::ResetLastError(); if(!::ChartSetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS,this.m_window_num,value)) { CMessage::ToLog(DFUN,::GetLastError(),true); return false; } if(redraw) ::ChartRedraw(this.m_chart_id); return true; } //+------------------------------------------------------------------+
Die Methode ähnelt denjenigen, die die Werte von Chart-Objekteigenschaften setzen, die im vorherigen Artikel betrachtet wurden. Die Methode erhält den zum Setzen benötigten Wert, dann wird versucht, ihn mit der Funktion ChartSetInteger() dem Fenster zuzuweisen. Wenn das Chart-Änderungsereignis nicht in die Warteschlange gestellt wird, wird dies mitgeteilt und false zurückgegeben. Wenn das Ereignis erfolgreich in der Warteschlange steht, wird true zurückgegeben, indem Sie den Chart mit aktiviertem Flag redraw (Neuzeichnen) zwangsweise neu zeichnen. Das erzwungene Neuzeichnen des Charts ist notwendig, um nicht auf irgendein Chart-Ereignis (Kurseintreffen, Größenänderung, Mausklick usw.) zu warten, um Änderungen anzuzeigen, sondern um den Chart neu zu zeichnen und das Ergebnis zu sehen.
Die Methode vergleicht Chartfensterobjekte anhand einer angegebenen Eigenschaft:
//+------------------------------------------------------------------+ //| Compare CChartWnd objects with each other by a specified property| //+------------------------------------------------------------------+ int CChartWnd::Compare(const CObject *node,const int mode=0) const { const CChartWnd *obj_compared=node; if(mode==CHART_PROP_WINDOW_YDISTANCE) return(this.YDistance()>obj_compared.YDistance() ? 1 : this.YDistance()<obj_compared.YDistance() ? -1 : 0); else if(mode==CHART_PROP_HEIGHT_IN_PIXELS) return(this.HeightInPixels()>obj_compared.HeightInPixels() ? 1 : this.HeightInPixels()<obj_compared.HeightInPixels() ? -1 : 0); return -1; } //+------------------------------------------------------------------+
Genau wie in der oben betrachteten Methode zum Vergleichen in der Indikatorklasse des Chartfensters vergleichen wir nur einige Eigenschaften, die in den Enumerationen der Chart-Objekteigenschaften angegeben sind:
- Abstand in Pixeln der Y-Achse zwischen dem oberen Rahmen des Indikator-Unterfensters und dem oberen Rahmen des Hauptfensters des Charts,
- Höhe des Charts in Pixeln,
- In allen anderen Fällen wird -1 zurückgegeben.
Die Methode vergleicht Chartfensterobjekte anhand aller Eigenschaften:
//+------------------------------------------------------------------+ //| Compare the CChartWnd objects by all properties | //+------------------------------------------------------------------+ bool CChartWnd::IsEqual(CChartWnd *compared_obj) const { return(this.YDistance()!=compared_obj.YDistance() || this.HeightInPixels()!=compared_obj.HeightInPixels() ? false : true); } //+------------------------------------------------------------------+
Hier wird, wenn mindestens eine der beiden Eigenschaften der verglichenen Objekte Ungleichheit liefert, false zurückgegeben — die Objekte sind nicht gleich. Andernfalls wird true zurückgegeben — die Objekte sind identisch.
Die Methode gibt die Beschreibung der Integer-Eigenschaft zurück:
//+------------------------------------------------------------------+ //| Return description of object's integer property | //+------------------------------------------------------------------+ string CChartWnd::GetPropertyDescription(ENUM_CHART_PROP_INTEGER property) { return ( property==CHART_PROP_WINDOW_YDISTANCE ? CMessage::Text(MSG_CHART_OBJ_WINDOW_YDISTANCE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.YDistance() ) : property==CHART_PROP_HEIGHT_IN_PIXELS ? CMessage::Text(MSG_CHART_OBJ_HEIGHT_IN_PIXELS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.HeightInPixels() ) : "" ); } //+------------------------------------------------------------------+
Je nachdem, welche Integer-Eigenschaft des Chartfensterobjekts an die Methode übergeben wird, wird die Zeichenkette mit seiner Beschreibung erstellt und zurückgegeben.
Die Methode, die Objekteigenschaften im Journal anzeigt:
//+------------------------------------------------------------------+ //| Display object properties in the journal | //+------------------------------------------------------------------+ void CChartWnd::Print(const bool full_prop=false) { ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") ============="); int beg=0, end=CHART_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_INTEGER prop=(ENUM_CHART_PROP_INTEGER)i; if(prop!=CHART_PROP_WINDOW_YDISTANCE && prop!=CHART_PROP_HEIGHT_IN_PIXELS) continue; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("------"); beg=end; end+=CHART_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { //ENUM_CHART_PROP_DOUBLE prop=(ENUM_CHART_PROP_DOUBLE)i; //if(!full_prop && !this.SupportProperty(prop)) continue; //::Print(this.GetPropertyDescription(prop)); } beg=end; end+=CHART_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_STRING prop=(ENUM_CHART_PROP_STRING)i; if(prop==CHART_PROP_INDICATOR_NAME) { this.PrintIndicators(); continue; } if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.Header(),") =============\n"); } //+------------------------------------------------------------------+
In drei Schleifen durch alle Chart-Objekteigenschaften, die nächste Eigenschaft erhalten und deren Beschreibung im Journal anzeigen. Da das Chartfenster-Objekt keine nutzerdefinierten Enumeration-Listen seiner Eigenschaften hat, müssen wir nur die Eigenschaften des Chart-Objekts anzeigen, die dem Chartfenster-Objekt eigen sind — Integer- und String-Eigenschaften. Das Objekt hat keine echten Eigenschaften, was bedeutet, dass sie nicht angezeigt werden können. Ich hätte einen starren Rahmen für den Anfang und das Ende jeder Schleife setzen können... Aber eine solche Lösung ist nicht die beste im Hinblick auf nachträgliche Änderungen der Eigenschaften des Chart-Objekts, da ich zum Objekt zurückkehren und die Werte für jeden Schleifenanfang und jedes Schleifenende bearbeiten hätte müssen. Deshalb werde ich die eigentliche Eigenschaftsschleife einfach leer machen (vielleicht ist das nur vorübergehend, bis in der Zukunft echte Eigenschaften für das Chartfensterobjekt benötigt werden). So werden bei jeder Änderung der Anzahl der Eigenschaften der Start und das Ende jeder Schleife immer korrekt sein.
Die Methode gibt eine Kurzbeschreibung des Chartfenster-Objekts zurück:
//+------------------------------------------------------------------+ //| Return the object short name | //+------------------------------------------------------------------+ string CChartWnd::Header(void) { return(this.m_window_num==0 ? CMessage::Text(MSG_CHART_OBJ_CHART_WINDOW) : (string)this.WindowNum()+" "+CMessage::Text(MSG_CHART_OBJ_CHART_SUBWINDOW)); } //+------------------------------------------------------------------+
Die Methode prüft den Index des Unterfensters. Ist dies das Hauptfenster des Charts (Index 0), wird der Text "Hauptfenster des Charts" zurückgegeben. Wenn es sich um das Hauptfenster des Charts handelt, werden der Index des Unterfensters und die Zeichenfolge "Chart-Unterfenster" zurückgegeben.
Die Methode zeigt die kurze Chartfenster-Objektbeschreibung im Journal an:https://schinagl.priv.at/nt/hardlinkshellext/linkshellextension.html
//+------------------------------------------------------------------+ //| Display a short description of the object in the journal | //+------------------------------------------------------------------+ void CChartWnd::PrintShort(const bool dash=false) { ::Print((dash ? "- " : ""),this.Header()," ID: ",(string)this.GetChartID(),", ",CMessage::Text(MSG_CHART_OBJ_INDICATORS_TOTAL),": ",this.IndicatorsTotal()); } //+------------------------------------------------------------------+
Hier wird eine Textzeile erstellt, der aus einem kurzen Objektnamen, der Chart-ID und der Anzahl der an das Fenster angehängten Indikatoren besteht. Wenn die Methode das Flag erhält, das die Notwendigkeit der Anzeige des Bindestrichs vor einer Objektbeschreibung anzeigt (dash), wird der Bindestrich vor dem erstellten String angezeigt.
Die Methode, die die Beschreibungen aller an das Fenster angehängten Indikatoren im Journal anzeigt:
//+------------------------------------------------------------------+ //| Display the description of indicators attached to the window | //+------------------------------------------------------------------+ void CChartWnd::PrintIndicators(const bool dash=false) { string header= ( this.WindowNum()==0 ? CMessage::Text(MSG_CHART_OBJ_INDICATORS_MW_NAME_LIST) : CMessage::Text(MSG_CHART_OBJ_INDICATORS_SW_NAME_LIST)+" "+(string)this.WindowNum() ); ::Print(header,":"); int total=this.IndicatorsTotal(); if(total==0) ::Print("- ",CMessage::Text(MSG_CHART_OBJ_INDICATORS_NONE)); else for(int i=0;i<total;i++) { CWndInd *ind=this.m_list_ind.At(i); if(ind==NULL) continue; ind.Print(dash); } } //+------------------------------------------------------------------+
Erstellen wir zunächst eine zum Fenster passende Kopfzeile und zeigen diese im Journal an.
Wenn es sich um das Hauptfenster des Charts handelt, sollte der Text der Kopfzeile "Indicators in the main chart window" (Indikatoren im Hauptfenster des Charts) lauten, andernfalls lautet der Text der Kopfzeile "Indicators in the chart window" (Indikatoren im Fenster des Charts) + Fensterindex.
Als Nächstes definieren wir die Anzahl der Indikatoren, die an das Fenster angehängt sind. Wenn keine solchen Indikatoren vorhanden sind, wird "No indicators" (Keine Indikatoren) angezeigt.
Andernfalls in der Schleife durch die Liste aller Indikatoren holen wir uns das nächste Indikatorobjekt im Chartfenster und geben dessen Daten aus.
Die Methode, die die Beschreibung der Fensterparameter im Journal anzeigt:
//+------------------------------------------------------------------+ //| Display the description of the window parameters in the journal | //+------------------------------------------------------------------+ void CChartWnd::PrintParameters(const bool dash=false) { string header= ( this.WindowNum()==0 ? CMessage::Text(MSG_CHART_OBJ_CHART_WINDOW) : CMessage::Text(MSG_CHART_OBJ_CHART_SUBWINDOW)+" "+(string)this.WindowNum() ); ::Print((dash ? " " : ""),header,":"); if(this.WindowNum()>0) ::Print((dash ? " - " : ""),GetPropertyDescription(CHART_PROP_WINDOW_YDISTANCE)); ::Print((dash ? " - " : ""),GetPropertyDescription(CHART_PROP_HEIGHT_IN_PIXELS)); } //+------------------------------------------------------------------+
Erstellen wir zunächst eine zum Fenster passende Kopfzeile und zeigen diese im Journal an.
Wenn dies das Hauptfenster des Charts ist, sollte der Kopftext "Main chart window" (Hauptfenster des Charts) lauten, andernfalls lautet der Kopftext "Chart subwindow" (Unterfenster des Charts) + Fensterindex.
Wenn dies ein Chart-Unterfenster ist (sein Index ist größer als Null), zeigen wir den vertikalen (Y-Achse) Abstand in Pixeln zwischen dem oberen Rand des Indikator-Unterfensters und dem oberen Rand des Haupt-Chartfensters an (für das Hauptfenster ist er immer 0, und er wird nicht angezeigt). Anschließend wird die zweite Objekteigenschaft (Chart-Höhe in Pixel) im Journal angezeigt.
Die Methode, die die Liste der an das Fenster angehängten Indikatoren erstellt:
//+------------------------------------------------------------------+ //| Create the list of indicators attached to the window | //+------------------------------------------------------------------+ void CChartWnd::IndicatorsListCreate(void) { //--- Clear the list of indicators this.m_list_ind.Clear(); //--- Get the total number of indicators in the window int total=::ChartIndicatorsTotal(this.m_chart_id,this.m_window_num); //--- In the loop by the number of indicators, for(int i=0;i<total;i++) { //--- obtain and save the short indicator name, string name=::ChartIndicatorName(this.m_chart_id,this.m_window_num,i); //--- get and save the indicator handle by its short name int handle=::ChartIndicatorGet(this.m_chart_id,this.m_window_num,name); //--- Free the indicator handle ::IndicatorRelease(handle); //--- Create the new indicator object in the chart window CWndInd *ind=new CWndInd(handle,name,i); if(ind==NULL) continue; //--- set the sorted list flag to the list this.m_list_ind.Sort(); //--- If failed to add the object to the list, remove it if(!this.m_list_ind.Add(ind)) delete ind; } } //+------------------------------------------------------------------+
Die Methode ist im Code ausführlich kommentiert. Wenn wir die Liste der Indikatoren im Fenster abrufen, erhalten wir den Indikator-Handle über seinen Kurznamen mit ChartIndicatorGet(), was uns einige "Verantwortlichkeiten" auferlegt. Das Terminal verfolgt die Verwendung der einzelnen Indikatoren. Mit jedem Handle-Empfang wird der interne Zähler der Verwendung des Indikators erhöht. Wenn wir uns in unserem Programm nicht darum kümmern, den für uns bereits unnötigen Indikator-Handle wieder freizugeben, dann wird es unmöglich sein, den "verlorenen" Handle später wieder einzufangen. Deshalb gebe ich das Handle sofort frei, nachdem ich alle notwendigen Indikatordaten erhalten habe, wodurch der interne Zähler der Indikatorverwendung verringert wird.
Die Methode, die neue Indikatoren zur Liste hinzufügt:
//+------------------------------------------------------------------+ //| Add new indicators to the list | //+------------------------------------------------------------------+ void CChartWnd::IndicatorsAdd(void) { //--- Get the total number of indicators in the window int total=::ChartIndicatorsTotal(this.m_chart_id,this.m_window_num); //--- In the loop by the number of indicators, for(int i=0;i<total;i++) { //--- obtain and save the short indicator name, string name=::ChartIndicatorName(this.m_chart_id,this.m_window_num,i); //--- get and save the indicator handle by its short name int handle=::ChartIndicatorGet(this.m_chart_id,this.m_window_num,name); //--- Release the indicator handle ::IndicatorRelease(handle); //--- Create the new indicator object in the chart window CWndInd *ind=new CWndInd(handle,name,i); if(ind==NULL) continue; //--- set the sorted list flag to the list this.m_list_ind.Sort(); //--- If the object is already in the list or an attempt to add it to the list failed, remove it if(this.m_list_ind.Search(ind)>WRONG_VALUE || !this.m_list_ind.Add(ind)) delete ind; } } //+------------------------------------------------------------------+
Die Logik der Methode ist identisch mit der oben betrachteten. Sie ist auch im Code kommentiert. Der einzige Unterschied ist, dass die Liste in der Methode zunächst nicht geleert wird. Wenn ein Indikator zur Liste hinzugefügt wird, wird zunächst das Vorhandensein eines solchen Indikators in der Liste geprüft. Wenn er bereits vorhanden ist, wird das Indikatorobjekt entfernt.
Um unsere Liste der Indikatoren im Fenster mit ihrer tatsächlichen Anzahl abgleichen zu können (schließlich können Indikatoren zum Fenster hinzugefügt und aus dem Chartfenster entfernt werden), müssen wir ihre Anzahl im Fenster mit der Anzahl in der Liste vergleichen. Dies werden wir in späteren Artikeln tun.
Jedoch werde ich hier die Methode implementieren, die das Vorhandensein eines Indikators aus der Liste im Terminalfenster zurückgibt:
//+--------------------------------------------------------------------------------------+ //| Return the flag indicating the presence of an indicator from the list in the window | //+--------------------------------------------------------------------------------------+ bool CChartWnd::IsPresentInWindow(const CWndInd *ind) { int total=::ChartIndicatorsTotal(this.m_chart_id,this.m_window_num); for(int i=0;i<total;i++) { string name=::ChartIndicatorName(this.m_chart_id,this.m_window_num,i); int handle=::ChartIndicatorGet(this.m_chart_id,this.m_window_num,name); ::IndicatorRelease(handle); if(ind.Name()==name && ind.Handle()==handle) return true; } return false; } //+------------------------------------------------------------------+
Die Methode erhält den Zeiger auf das Indikatorobjekt im Chartfenster, dessen tatsächliches Vorhandensein geprüft werden soll. Anschließend holen wir uns in der Schleife durch die Gesamtzahl der Indikatoren im Chartfenster den Namen des nächsten Indikators, seinen Handle und geben es sofort wieder frei. Wenn der Kurzname und das Handle des aktuellen Indikators mit denen des geprüften Objekts übereinstimmen, wird true zurückgegeben. Der Indikator ist noch im Chartfenster vorhanden. Nach Abschluss der Schleife wird false zurückgegeben — es wurden keine Übereinstimmungen gefunden, d. h. es gibt keinen solchen Indikator im Chartfenster.
Wenn die Liste Indikatoren enthält, die nicht im Chart vorhanden sind, sollten sie aus der Liste entfernt werden.
Die Methode zum Entfernen von Indikatoren, die nicht im Fenster vorhanden sind, aus der Liste:
//+------------------------------------------------------------------+ //| Remove indicators not present in the window from the list | //+------------------------------------------------------------------+ void CChartWnd::IndicatorsDelete(void) { int total=this.m_list_ind.Total(); for(int i=total-1;i>WRONG_VALUE;i--) { CWndInd *ind=this.m_list_ind.At(i); if(!this.IsPresentInWindow(ind)) this.m_list_ind.Delete(i); } } //+------------------------------------------------------------------+
Hier in der Schleife durch die Liste der Indikatorobjekte, erhalten wir das nächste Indikatorobjekt durch den Schleifenindex und überprüfen sein Vorhandensein im realen Chartfenster. Wenn es nicht vorhanden ist, entfernen wir den Zeiger mit der Methode Delete() aus der Liste.
Später, bei der Implementierung der Kollektionsklasse des Charts, werden wir den Indikatorstatus in den Unterfenstern aller Chart-Objekte verfolgen müssen. Wenn es eine Diskrepanz zwischen einer realen Anzahl von Indikatoren in den Chart-Unterfenstern und ihren Beschreibungen in den Listen der Chartfenster-Objekte gibt, müssen wir überflüssige Indikatoren aus der Liste entfernen und neue hinzufügen, falls vorhanden.
Um dies zu erreichen, erstellen wir die Methode zum Aktualisieren der Daten von Indikatoren, die an Chartfenster angehängt sind:
//+------------------------------------------------------------------+ //| Update data on attached indicators | //+------------------------------------------------------------------+ void CChartWnd::Refresh(void) { this.IndicatorsDelete(); this.IndicatorsAdd(); } //+------------------------------------------------------------------+
Hier suchen wir zunächst die Indikatoren, die nicht in einem realen Chartfenster vorhanden sind und entfernen sie aus der Liste. Als Nächstes suchen wir und fügen wir neue Indikatoren hinzu, die im Fenster, aber nicht in der Liste vorhanden sind, indem wir die oben genannten Methoden verwenden.
Betrachten wir schließlich den Konstruktor der parametrischen Klasse:
//+------------------------------------------------------------------+ //| Parametric constructor | //+------------------------------------------------------------------+ CChartWnd::CChartWnd(const long chart_id,const int wnd_num) : m_window_num(wnd_num) { CBaseObj::SetChartID(chart_id); this.IndicatorsListCreate(); } //+------------------------------------------------------------------+
Hier setzen wir zunächst die Chart-ID im übergeordneten Objekt CBaseObj. Dann erstellen wir die Liste der Indikatoren, die an das Chartfenster angehängt sind. Der Index des Chart-Unterfensters wird in der Initialisierungsliste des Konstruktors gesetzt.
Damit ist die Erstellung der Indikator-Objektklassen im Chartfenster und des Chartfenster-Objekts abgeschlossen.
Die vollständige Auflistung beider Klassen, die sich in einer Datei befinden, können Sie in den unten angehängten Dateien einsehen.
Da wir nun das Objekt haben, das das Chartfenster und seine Unterfenster beschreibt, ist es an der Zeit, die Chart-Objektklasse CChartObj in \MQL5\Include\DoEasy\Objects\Chart\ChartObj.mqh zu verbessern. Jetzt hat es die Liste aller Unterfenster, die sich in seinem Hauptfenster befinden. Um die Fenstereigenschaften zu erhalten, müssen wir uns auf den Zeiger auf das notwendige Chartfensterobjekt beziehen, das oben erstellt wurde. Von dem erhaltenen Fensterobjekt können wir die Liste aller Indikatoren erhalten, die mit ihm verbunden sind. Von diesen Indikatoren wiederum können wir das Handle eines notwendigen Indikators erhalten, um mit ihm zu arbeiten.
Zunächst binden wir die Datei der Fensterobjekte und Indikatoren im Fenster in die Chart-Objektdatei ein und deklarieren das Listenobjekt, in dem wir die Zeiger auf alle Chart-Objektfenster speichern werden:
//+------------------------------------------------------------------+ //| ChartObj.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "..\..\Objects\BaseObj.mqh" #include "ChartWnd.mqh" //+------------------------------------------------------------------+ //| Chart object class | //+------------------------------------------------------------------+ class CChartObj : public CBaseObj { private: CArrayObj m_list_wnd; // List of chart window objects long m_long_prop[CHART_PROP_INTEGER_TOTAL]; // Integer properties double m_double_prop[CHART_PROP_DOUBLE_TOTAL]; // Real properties string m_string_prop[CHART_PROP_STRING_TOTAL]; // String properties int m_digits; // Symbol's Digits()
Fügen wir der Liste der Methoden zum Setzen von Eigenschaftswerten des privaten Abschnitts der Klasse die Methode zum Setzen der Sichtbarkeit des Chartfensters hinzu:
//--- The methods of setting property values bool SetMode(const string source,const ENUM_CHART_MODE mode,const bool redraw=false); bool SetScale(const string source,const int scale,const bool redraw=false); bool SetModeVolume(const string source,const ENUM_CHART_VOLUME_MODE mode,const bool redraw=false); void SetVisibleBars(void); void SetWindowsTotal(void); void SetVisible(void); void SetFirstVisibleBars(void); void SetWidthInBars(void); void SetWidthInPixels(void); void SetMaximizedFlag(void); void SetMinimizedFlag(void); void SetExpertName(void); void SetScriptName(void); public:
Da die Eigenschaft "Abstand in Y-Achsen-Pixeln zwischen dem oberen Rahmen des Indikator-Unterfensters und dem oberen Rahmen des Chart-Hauptfensters" nicht auf das Hauptfenster anwendbar ist (sie ist dort immer 0), ändern wir den Wert, der zurückgegeben wird, wenn es sich um die Eigenschaft CHART_PROP_WINDOW_YDISTANCE in der Methode handelt, die das Flag eines Objekts zurückgibt, das eine Integer-Eigenschaft unterstützt:
//--- Return the flag of the object supporting this property virtual bool SupportProperty(ENUM_CHART_PROP_INTEGER property) { return (property!=CHART_PROP_WINDOW_YDISTANCE ? true : false); } virtual bool SupportProperty(ENUM_CHART_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_CHART_PROP_STRING property) { return true; }
Wenn die an die Methode übergebene Eigenschaft ungleich CHART_PROP_WINDOW_YDISTANCE ist, wird true zurückgegeben, sonst false.
In der Liste der Methoden für einen vereinfachten Zugriff auf die Objekteigenschaften fügen Sie die Methode hinzu, die die Fenstersichtbarkeit zurückgibt:
//--- Return the total number of chart windows including indicator subwindows int WindowsTotal(void) const { return (int)this.GetProperty(CHART_PROP_WINDOWS_TOTAL); } //--- Return the window visibility bool Visible(void) const { return (bool)this.GetProperty(CHART_PROP_WINDOW_IS_VISIBLE); } //--- Return the chart window handle int Handle(void) const { return (int)this.GetProperty(CHART_PROP_WINDOW_HANDLE); }
Hier soll die Methode nur die Eigenschaft des Hauptfensters des Charts zurückgeben.
Die Methoden, die den Abstand in Pixeln der Y-Achse zwischen dem oberen Rahmen des Indikator-Unterfensters und dem oberen Rahmen des Chart-Hauptfensters zurückgeben, sowie die, die die Höhe eines angegebenen Charts in Pixeln zurückgeben und setzen, wurden geändert. Jetzt müssen wir das notwendige Fensterobjekt zum Setzen und Zurückgeben dieser Eigenschaften finden, um diese Werte in den Objekteigenschaften zu setzen oder zu erhalten. Die Implementierung der Methoden werden wir etwas später betrachten.
//--- Return the name of a script launched on the chart string ScriptName(void) const { return this.GetProperty(CHART_PROP_SCRIPT_NAME); } //--- Return the distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window int WindowYDistance(const int sub_window) const; //--- (1) Return and (2) set the height of the specified chart in pixels int WindowHeightInPixels(const int sub_window) const; bool SetWindowHeightInPixels(const int height,const int sub_window,const bool redraw=false); //--- Return the specified subwindow visibility
Ganz unten im Klassenkörper deklarieren wir zusätzliche Methoden für den Empfang des erforderlichen Fensterobjekts und die Anzeige der Eigenschaften aller Chart-Unterfenster und der Daten aller Indikatoren, die dem angegebenen Chartfenster im Journal zugeordnet sind:
//--- Emulate a tick (chart updates - similar to the terminal Refresh command) void EmulateTick(void) { ::ChartSetSymbolPeriod(this.ID(),this.Symbol(),this.Timeframe());} //--- Return the chart window specified by index CChartWnd *GetWindowByIndex(const int index) const { return this.m_list_wnd.At(index); } //--- Return the window object by its subwindow index CChartWnd *GetWindowByNum(const int win_num) const; //--- Display data of all indicators of all chart windows in the journal void PrintWndIndicators(void); //--- Display the properties of all chart windows in the journal void PrintWndParameters(void); }; //+------------------------------------------------------------------+
Im parametrischen Klassenkonstruktor setzen wir die Chart-ID im Elternobjekt der Klasse und geben drei Hauptfenstereigenschaften für das Chart-Objekt an (das ist eigentlich unnötig, da sich das Hauptfenster-Objekt jetzt in der Liste aller Chartfenster befindet, aber da das Objekt solche Eigenschaften besitzt, werde ich sie mit den richtigen Daten füllen). Ganz am Ende der Methode fügen wir alle zum Chart gehörenden Fensterobjekte in die Liste aller Chartfenster hinzu:
//+------------------------------------------------------------------+ //| Parametric constructor | //+------------------------------------------------------------------+ CChartObj::CChartObj(const long chart_id) { //--- Set chart ID to the base object CBaseObj::SetChartID(chart_id); //--- Set integer properties this.SetProperty(CHART_PROP_ID,chart_id); // Chart ID this.SetProperty(CHART_PROP_TIMEFRAME,::ChartPeriod(this.ID())); // Chart timeframe this.SetProperty(CHART_PROP_SHOW,::ChartGetInteger(this.ID(),CHART_SHOW)); // Price chart drawing attribute this.SetProperty(CHART_PROP_IS_OBJECT,::ChartGetInteger(this.ID(),CHART_IS_OBJECT)); // Chart object identification attribute this.SetProperty(CHART_PROP_BRING_TO_TOP,false); // Show chart above all others this.SetProperty(CHART_PROP_CONTEXT_MENU,::ChartGetInteger(this.ID(),CHART_CONTEXT_MENU)); // Access to the context menu using the right click this.SetProperty(CHART_PROP_CROSSHAIR_TOOL,::ChartGetInteger(this.ID(),CHART_CROSSHAIR_TOOL)); // Access the Crosshair tool by pressing the middle mouse button this.SetProperty(CHART_PROP_MOUSE_SCROLL,::ChartGetInteger(this.ID(),CHART_MOUSE_SCROLL)); // Scroll the chart horizontally using the left mouse button this.SetProperty(CHART_PROP_EVENT_MOUSE_WHEEL,::ChartGetInteger(this.ID(),CHART_EVENT_MOUSE_WHEEL)); // Send messages about mouse wheel events to all MQL5 programs on a chart this.SetProperty(CHART_PROP_EVENT_MOUSE_MOVE,::ChartGetInteger(this.ID(),CHART_EVENT_MOUSE_MOVE)); // Send messages about mouse button click and movement events to all MQL5 programs on a chart this.SetProperty(CHART_PROP_EVENT_OBJECT_CREATE,::ChartGetInteger(this.ID(),CHART_EVENT_OBJECT_CREATE)); // Send messages about the graphical object creation event to all MQL5 programs on a chart this.SetProperty(CHART_PROP_EVENT_OBJECT_DELETE,::ChartGetInteger(this.ID(),CHART_EVENT_OBJECT_DELETE)); // Send messages about the graphical object destruction event to all MQL5 programs on a chart this.SetProperty(CHART_PROP_MODE,::ChartGetInteger(this.ID(),CHART_MODE)); // Type of the chart (candlesticks, bars or line) this.SetProperty(CHART_PROP_FOREGROUND,::ChartGetInteger(this.ID(),CHART_FOREGROUND)); // Price chart in the foreground this.SetProperty(CHART_PROP_SHIFT,::ChartGetInteger(this.ID(),CHART_SHIFT)); // Mode of shift of the price chart from the right border this.SetProperty(CHART_PROP_AUTOSCROLL,::ChartGetInteger(this.ID(),CHART_AUTOSCROLL)); // The mode of automatic shift to the right border of the chart this.SetProperty(CHART_PROP_KEYBOARD_CONTROL,::ChartGetInteger(this.ID(),CHART_KEYBOARD_CONTROL)); // Allow managing the chart using a keyboard this.SetProperty(CHART_PROP_QUICK_NAVIGATION,::ChartGetInteger(this.ID(),CHART_QUICK_NAVIGATION)); // Allow the chart to intercept Space and Enter key strokes to activate the quick navigation bar this.SetProperty(CHART_PROP_SCALE,::ChartGetInteger(this.ID(),CHART_SCALE)); // Scale this.SetProperty(CHART_PROP_SCALEFIX,::ChartGetInteger(this.ID(),CHART_SCALEFIX)); // Fixed scale mode this.SetProperty(CHART_PROP_SCALEFIX_11,::ChartGetInteger(this.ID(),CHART_SCALEFIX_11)); // 1:1 scale mode this.SetProperty(CHART_PROP_SCALE_PT_PER_BAR,::ChartGetInteger(this.ID(),CHART_SCALE_PT_PER_BAR)); // Mode for specifying the scale in points per bar this.SetProperty(CHART_PROP_SHOW_TICKER,::ChartGetInteger(this.ID(),CHART_SHOW_TICKER)); // Display a symbol ticker in the upper left corner this.SetProperty(CHART_PROP_SHOW_OHLC,::ChartGetInteger(this.ID(),CHART_SHOW_OHLC)); // Display OHLC values in the upper left corner this.SetProperty(CHART_PROP_SHOW_BID_LINE,::ChartGetInteger(this.ID(),CHART_SHOW_BID_LINE)); // Display Bid value as a horizontal line on the chart this.SetProperty(CHART_PROP_SHOW_ASK_LINE,::ChartGetInteger(this.ID(),CHART_SHOW_ASK_LINE)); // Display Ask value as a horizontal line on the chart this.SetProperty(CHART_PROP_SHOW_LAST_LINE,::ChartGetInteger(this.ID(),CHART_SHOW_LAST_LINE)); // Display Last value as a horizontal line on the chart this.SetProperty(CHART_PROP_SHOW_PERIOD_SEP,::ChartGetInteger(this.ID(),CHART_SHOW_PERIOD_SEP)); // Display vertical separators between adjacent periods this.SetProperty(CHART_PROP_SHOW_GRID,::ChartGetInteger(this.ID(),CHART_SHOW_GRID)); // Display the chart grid this.SetProperty(CHART_PROP_SHOW_VOLUMES,::ChartGetInteger(this.ID(),CHART_SHOW_VOLUMES)); // Display volumes on the chart this.SetProperty(CHART_PROP_SHOW_OBJECT_DESCR,::ChartGetInteger(this.ID(),CHART_SHOW_OBJECT_DESCR)); // Display text descriptions of the objects this.SetProperty(CHART_PROP_VISIBLE_BARS,::ChartGetInteger(this.ID(),CHART_VISIBLE_BARS)); // Number of bars on a chart that are available for display this.SetProperty(CHART_PROP_WINDOWS_TOTAL,::ChartGetInteger(this.ID(),CHART_WINDOWS_TOTAL)); // The total number of chart windows including indicator subwindows this.SetProperty(CHART_PROP_WINDOW_IS_VISIBLE,::ChartGetInteger(this.ID(),CHART_WINDOW_IS_VISIBLE,0));// Window visibility this.SetProperty(CHART_PROP_WINDOW_HANDLE,::ChartGetInteger(this.ID(),CHART_WINDOW_HANDLE)); // Chart window handle this.SetProperty(CHART_PROP_WINDOW_YDISTANCE,::ChartGetInteger(this.ID(),CHART_WINDOW_YDISTANCE,0)); // Distance in Y axis pixels between the upper frame of the indicator subwindow and the upper frame of the chart main window this.SetProperty(CHART_PROP_FIRST_VISIBLE_BAR,::ChartGetInteger(this.ID(),CHART_FIRST_VISIBLE_BAR)); // Number of the first visible bar on the chart this.SetProperty(CHART_PROP_WIDTH_IN_BARS,::ChartGetInteger(this.ID(),CHART_WIDTH_IN_BARS)); // Chart width in bars this.SetProperty(CHART_PROP_WIDTH_IN_PIXELS,::ChartGetInteger(this.ID(),CHART_WIDTH_IN_PIXELS)); // Chart width in pixels this.SetProperty(CHART_PROP_HEIGHT_IN_PIXELS,::ChartGetInteger(this.ID(),CHART_HEIGHT_IN_PIXELS,0)); // Chart height in pixels this.SetProperty(CHART_PROP_COLOR_BACKGROUND,::ChartGetInteger(this.ID(),CHART_COLOR_BACKGROUND)); // Chart background color this.SetProperty(CHART_PROP_COLOR_FOREGROUND,::ChartGetInteger(this.ID(),CHART_COLOR_FOREGROUND)); // Color of axes, scale and OHLC line this.SetProperty(CHART_PROP_COLOR_GRID,::ChartGetInteger(this.ID(),CHART_COLOR_GRID)); // Grid color this.SetProperty(CHART_PROP_COLOR_VOLUME,::ChartGetInteger(this.ID(),CHART_COLOR_VOLUME)); // Color of volumes and position opening levels this.SetProperty(CHART_PROP_COLOR_CHART_UP,::ChartGetInteger(this.ID(),CHART_COLOR_CHART_UP)); // Color for the up bar, shadows and body borders of bullish candlesticks this.SetProperty(CHART_PROP_COLOR_CHART_DOWN,::ChartGetInteger(this.ID(),CHART_COLOR_CHART_DOWN)); // Color for the down bar, shadows and body borders of bearish candlesticks this.SetProperty(CHART_PROP_COLOR_CHART_LINE,::ChartGetInteger(this.ID(),CHART_COLOR_CHART_LINE)); // Color of the chart line and the Doji candlesticks this.SetProperty(CHART_PROP_COLOR_CANDLE_BULL,::ChartGetInteger(this.ID(),CHART_COLOR_CANDLE_BULL)); // Color of the bullish candle body this.SetProperty(CHART_PROP_COLOR_CANDLE_BEAR,::ChartGetInteger(this.ID(),CHART_COLOR_CANDLE_BEAR)); // Color of the bearish candle body this.SetProperty(CHART_PROP_COLOR_BID,::ChartGetInteger(this.ID(),CHART_COLOR_BID)); // Bid price line color this.SetProperty(CHART_PROP_COLOR_ASK,::ChartGetInteger(this.ID(),CHART_COLOR_ASK)); // Ask price line color this.SetProperty(CHART_PROP_COLOR_LAST,::ChartGetInteger(this.ID(),CHART_COLOR_LAST)); // Color of the last performed deal's price line (Last) this.SetProperty(CHART_PROP_COLOR_STOP_LEVEL,::ChartGetInteger(this.ID(),CHART_COLOR_STOP_LEVEL)); // Color of stop order levels (Stop Loss and Take Profit) this.SetProperty(CHART_PROP_SHOW_TRADE_LEVELS,::ChartGetInteger(this.ID(),CHART_SHOW_TRADE_LEVELS)); // Display trade levels on the chart (levels of open positions, Stop Loss, Take Profit and pending orders) this.SetProperty(CHART_PROP_DRAG_TRADE_LEVELS,::ChartGetInteger(this.ID(),CHART_DRAG_TRADE_LEVELS)); // Enable the ability to drag trading levels on a chart using mouse this.SetProperty(CHART_PROP_SHOW_DATE_SCALE,::ChartGetInteger(this.ID(),CHART_SHOW_DATE_SCALE)); // Display the time scale on the chart this.SetProperty(CHART_PROP_SHOW_PRICE_SCALE,::ChartGetInteger(this.ID(),CHART_SHOW_PRICE_SCALE)); // Display the price scale on the chart this.SetProperty(CHART_PROP_SHOW_ONE_CLICK,::ChartGetInteger(this.ID(),CHART_SHOW_ONE_CLICK)); // Display the quick trading panel on the chart this.SetProperty(CHART_PROP_IS_MAXIMIZED,::ChartGetInteger(this.ID(),CHART_IS_MAXIMIZED)); // Chart window maximized this.SetProperty(CHART_PROP_IS_MINIMIZED,::ChartGetInteger(this.ID(),CHART_IS_MINIMIZED)); // Chart window minimized this.SetProperty(CHART_PROP_IS_DOCKED,::ChartGetInteger(this.ID(),CHART_IS_DOCKED)); // Chart window docked this.SetProperty(CHART_PROP_FLOAT_LEFT,::ChartGetInteger(this.ID(),CHART_FLOAT_LEFT)); // Left coordinate of the undocked chart window relative to the virtual screen this.SetProperty(CHART_PROP_FLOAT_TOP,::ChartGetInteger(this.ID(),CHART_FLOAT_TOP)); // Upper coordinate of the undocked chart window relative to the virtual screen this.SetProperty(CHART_PROP_FLOAT_RIGHT,::ChartGetInteger(this.ID(),CHART_FLOAT_RIGHT)); // Right coordinate of the undocked chart window relative to the virtual screen this.SetProperty(CHART_PROP_FLOAT_BOTTOM,::ChartGetInteger(this.ID(),CHART_FLOAT_BOTTOM)); // Bottom coordinate of the undocked chart window relative to the virtual screen //--- Set real properties this.SetProperty(CHART_PROP_SHIFT_SIZE,::ChartGetDouble(this.ID(),CHART_SHIFT_SIZE)); // Shift size of the zero bar from the right border in % this.SetProperty(CHART_PROP_FIXED_POSITION,::ChartGetDouble(this.ID(),CHART_FIXED_POSITION)); // Chart fixed position from the left border in % this.SetProperty(CHART_PROP_FIXED_MAX,::ChartGetDouble(this.ID(),CHART_FIXED_MAX)); // Fixed chart maximum this.SetProperty(CHART_PROP_FIXED_MIN,::ChartGetDouble(this.ID(),CHART_FIXED_MIN)); // Fixed chart minimum this.SetProperty(CHART_PROP_POINTS_PER_BAR,::ChartGetDouble(this.ID(),CHART_POINTS_PER_BAR)); // Scale in points per bar this.SetProperty(CHART_PROP_PRICE_MIN,::ChartGetDouble(this.ID(),CHART_PRICE_MIN)); // Chart minimum this.SetProperty(CHART_PROP_PRICE_MAX,::ChartGetDouble(this.ID(),CHART_PRICE_MAX)); // Chart maximum //--- Set string properties this.SetProperty(CHART_PROP_COMMENT,::ChartGetString(this.ID(),CHART_COMMENT)); // Comment text on the chart this.SetProperty(CHART_PROP_EXPERT_NAME,::ChartGetString(this.ID(),CHART_EXPERT_NAME)); // name of an EA launched on the chart this.SetProperty(CHART_PROP_SCRIPT_NAME,::ChartGetString(this.ID(),CHART_SCRIPT_NAME)); // name of a script launched on the chart this.SetProperty(CHART_PROP_SYMBOL,::ChartSymbol(this.ID())); // Chart symbol this.m_digits=(int)::SymbolInfoInteger(this.Symbol(),SYMBOL_DIGITS); int total=this.WindowsTotal(); for(int i=0;i<total;i++) { CChartWnd *wnd=new CChartWnd(m_chart_id,i); if(wnd==NULL) continue; m_list_wnd.Sort(); if(!m_list_wnd.Add(wnd)) delete wnd; } } //+------------------------------------------------------------------+
Um die Chartfensterlisten zu erstellen, ermitteln wir die Gesamtzahl aller Chartfenster. In der Schleife durch alle Fenster erstellen wir ein neues Chartfenster-Objekt und fügen es der Liste hinzu.
Bei der im vorigen Artikel entwickelten Methode zum Vergleich zweier Chart-Objekte wurde ein logischer Fehler gemacht: Jedes Chart hat eine eindeutige Chart-ID und ein Fenster-Handle. Daher liefert der Vergleich anhand dieser beiden Eigenschaften immer false. Das Ziel der Methode ist jedoch, sicherzustellen, dass die Charts übereinstimmen, während der Vergleich ihrer IDs und Handles immer zeigen wird, dass sie nicht identisch sind.
Lassen Sie uns dies beheben, indem wir diese beiden Eigenschaften beim Vergleich überspringen:
//+------------------------------------------------------------------+ //| Compare the CChartObj objects by all properties | //+------------------------------------------------------------------+ bool CChartObj::IsEqual(CChartObj *compared_obj) const { int beg=0, end=CHART_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_INTEGER prop=(ENUM_CHART_PROP_INTEGER)i; if(prop==CHART_PROP_ID || prop==CHART_PROP_WINDOW_HANDLE) continue; if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; } beg=end; end+=CHART_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_DOUBLE prop=(ENUM_CHART_PROP_DOUBLE)i; if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; } beg=end; end+=CHART_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_STRING prop=(ENUM_CHART_PROP_STRING)i; if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; } return true; } //+------------------------------------------------------------------+
Fügen wir in der Methode, die die Beschreibung einer Integer-Objekteigenschaft zurückgibt, die Rückgabe der Beschreibung von drei hinzugefügten Eigenschaften hinzu:
//+------------------------------------------------------------------+ //| Return description of object's integer property | //+------------------------------------------------------------------+ string CChartObj::GetPropertyDescription(ENUM_CHART_PROP_INTEGER property) { return ( property==CHART_PROP_ID ? CMessage::Text(MSG_CHART_OBJ_ID)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_TIMEFRAME ? CMessage::Text(MSG_LIB_TEXT_BAR_PERIOD)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+TimeframeDescription((ENUM_TIMEFRAMES)this.GetProperty(property)) ) : property==CHART_PROP_SHOW ? CMessage::Text(MSG_CHART_OBJ_SHOW)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_IS_OBJECT ? CMessage::Text(MSG_CHART_OBJ_IS_OBJECT)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_BRING_TO_TOP ? CMessage::Text(MSG_CHART_OBJ_BRING_TO_TOP)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_CONTEXT_MENU ? CMessage::Text(MSG_CHART_OBJ_CONTEXT_MENU)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_CROSSHAIR_TOOL ? CMessage::Text(MSG_CHART_OBJ_CROSSHAIR_TOOL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_MOUSE_SCROLL ? CMessage::Text(MSG_CHART_OBJ_MOUSE_SCROLL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_EVENT_MOUSE_WHEEL ? CMessage::Text(MSG_CHART_OBJ_EVENT_MOUSE_WHEEL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_EVENT_MOUSE_MOVE ? CMessage::Text(MSG_CHART_OBJ_EVENT_MOUSE_MOVE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_EVENT_OBJECT_CREATE ? CMessage::Text(MSG_CHART_OBJ_EVENT_OBJECT_CREATE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_EVENT_OBJECT_DELETE ? CMessage::Text(MSG_CHART_OBJ_EVENT_OBJECT_DELETE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_MODE ? CMessage::Text(MSG_CHART_OBJ_MODE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ChartModeDescription((ENUM_CHART_MODE)this.GetProperty(property)) ) : property==CHART_PROP_FOREGROUND ? CMessage::Text(MSG_CHART_OBJ_FOREGROUND)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHIFT ? CMessage::Text(MSG_CHART_OBJ_SHIFT)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_AUTOSCROLL ? CMessage::Text(MSG_CHART_OBJ_AUTOSCROLL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_KEYBOARD_CONTROL ? CMessage::Text(MSG_CHART_OBJ_KEYBOARD_CONTROL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_QUICK_NAVIGATION ? CMessage::Text(MSG_CHART_OBJ_QUICK_NAVIGATION)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SCALE ? CMessage::Text(MSG_CHART_OBJ_SCALE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_SCALEFIX ? CMessage::Text(MSG_CHART_OBJ_SCALEFIX)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SCALEFIX_11 ? CMessage::Text(MSG_CHART_OBJ_SCALEFIX_11)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SCALE_PT_PER_BAR ? CMessage::Text(MSG_CHART_OBJ_SCALE_PT_PER_BAR)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_TICKER ? CMessage::Text(MSG_CHART_OBJ_SHOW_TICKER)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_OHLC ? CMessage::Text(MSG_CHART_OBJ_SHOW_OHLC)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_BID_LINE ? CMessage::Text(MSG_CHART_OBJ_SHOW_BID_LINE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_ASK_LINE ? CMessage::Text(MSG_CHART_OBJ_SHOW_ASK_LINE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_LAST_LINE ? CMessage::Text(MSG_CHART_OBJ_SHOW_LAST_LINE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_PERIOD_SEP ? CMessage::Text(MSG_CHART_OBJ_SHOW_PERIOD_SEP)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_GRID ? CMessage::Text(MSG_CHART_OBJ_SHOW_GRID)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_VOLUMES ? CMessage::Text(MSG_CHART_OBJ_SHOW_VOLUMES)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+ChartModeVolumeDescription((ENUM_CHART_VOLUME_MODE)this.GetProperty(property)) ) : property==CHART_PROP_SHOW_OBJECT_DESCR ? CMessage::Text(MSG_CHART_OBJ_SHOW_OBJECT_DESCR)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_VISIBLE_BARS ? CMessage::Text(MSG_CHART_OBJ_VISIBLE_BARS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_WINDOWS_TOTAL ? CMessage::Text(MSG_CHART_OBJ_WINDOWS_TOTAL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_WINDOW_IS_VISIBLE ? CMessage::Text(MSG_CHART_OBJ_WINDOW_IS_VISIBLE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_WINDOW_HANDLE ? CMessage::Text(MSG_CHART_OBJ_WINDOW_HANDLE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_WINDOW_YDISTANCE ? CMessage::Text(MSG_CHART_OBJ_WINDOW_YDISTANCE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_FIRST_VISIBLE_BAR ? CMessage::Text(MSG_CHART_OBJ_FIRST_VISIBLE_BAR)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_WIDTH_IN_BARS ? CMessage::Text(MSG_CHART_OBJ_WIDTH_IN_BARS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_WIDTH_IN_PIXELS ? CMessage::Text(MSG_CHART_OBJ_WIDTH_IN_PIXELS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_HEIGHT_IN_PIXELS ? CMessage::Text(MSG_CHART_OBJ_HEIGHT_IN_PIXELS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_COLOR_BACKGROUND ? CMessage::Text(MSG_CHART_OBJ_COLOR_BACKGROUND)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_FOREGROUND ? CMessage::Text(MSG_CHART_OBJ_COLOR_FOREGROUND)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_GRID ? CMessage::Text(MSG_CHART_OBJ_COLOR_GRID)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_VOLUME ? CMessage::Text(MSG_CHART_OBJ_COLOR_VOLUME)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_CHART_UP ? CMessage::Text(MSG_CHART_OBJ_COLOR_CHART_UP)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_CHART_DOWN ? CMessage::Text(MSG_CHART_OBJ_COLOR_CHART_DOWN)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_CHART_LINE ? CMessage::Text(MSG_CHART_OBJ_COLOR_CHART_LINE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_CANDLE_BULL ? CMessage::Text(MSG_CHART_OBJ_COLOR_CANDLE_BULL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_CANDLE_BEAR ? CMessage::Text(MSG_CHART_OBJ_COLOR_CANDLE_BEAR)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_BID ? CMessage::Text(MSG_CHART_OBJ_COLOR_BID)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_ASK ? CMessage::Text(MSG_CHART_OBJ_COLOR_ASK)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_LAST ? CMessage::Text(MSG_CHART_OBJ_COLOR_LAST)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_COLOR_STOP_LEVEL ? CMessage::Text(MSG_CHART_OBJ_COLOR_STOP_LEVEL)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+::ColorToString((color)this.GetProperty(property),true) ) : property==CHART_PROP_SHOW_TRADE_LEVELS ? CMessage::Text(MSG_CHART_OBJ_SHOW_TRADE_LEVELS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_DRAG_TRADE_LEVELS ? CMessage::Text(MSG_CHART_OBJ_DRAG_TRADE_LEVELS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_DATE_SCALE ? CMessage::Text(MSG_CHART_OBJ_SHOW_DATE_SCALE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_PRICE_SCALE ? CMessage::Text(MSG_CHART_OBJ_SHOW_PRICE_SCALE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_SHOW_ONE_CLICK ? CMessage::Text(MSG_CHART_OBJ_SHOW_ONE_CLICK)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_IS_MAXIMIZED ? CMessage::Text(MSG_CHART_OBJ_IS_MAXIMIZED)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_IS_MINIMIZED ? CMessage::Text(MSG_CHART_OBJ_IS_MINIMIZED)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_IS_DOCKED ? CMessage::Text(MSG_CHART_OBJ_IS_DOCKED)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) ) : property==CHART_PROP_FLOAT_LEFT ? CMessage::Text(MSG_CHART_OBJ_FLOAT_LEFT)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_FLOAT_TOP ? CMessage::Text(MSG_CHART_OBJ_FLOAT_TOP)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_FLOAT_RIGHT ? CMessage::Text(MSG_CHART_OBJ_FLOAT_RIGHT)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : property==CHART_PROP_FLOAT_BOTTOM ? CMessage::Text(MSG_CHART_OBJ_FLOAT_BOTTOM)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+(string)this.GetProperty(property) ) : "" ); } //+------------------------------------------------------------------+
Die Blöcke des hinzugefügten Codes sind identisch mit allen anderen — abhängig von der an die Methode übergebenen Eigenschaft wird die Zeichenkette mit ihrer Beschreibung und ihrem Wert erstellt und zurückgegeben.
Verbessern wir nun die Methode, die alle Objekteigenschaften im Journal anzeigt:
//+------------------------------------------------------------------+ //| Display object properties in the journal | //+------------------------------------------------------------------+ void CChartObj::Print(const bool full_prop=false) { ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") ============="); int beg=0, end=CHART_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_INTEGER prop=(ENUM_CHART_PROP_INTEGER)i; if(!full_prop && !this.SupportProperty(prop)) continue; if(prop==CHART_PROP_WINDOW_IND_HANDLE || prop==CHART_PROP_WINDOW_IND_INDEX) continue; if(prop==CHART_PROP_HEIGHT_IN_PIXELS) { this.PrintWndParameters(); continue; } ::Print(this.GetPropertyDescription(prop)); } ::Print("------"); beg=end; end+=CHART_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_DOUBLE prop=(ENUM_CHART_PROP_DOUBLE)i; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("------"); beg=end; end+=CHART_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_CHART_PROP_STRING prop=(ENUM_CHART_PROP_STRING)i; if(!full_prop && !this.SupportProperty(prop)) continue; if(prop==CHART_PROP_INDICATOR_NAME) { this.PrintWndIndicators(); continue; } ::Print(this.GetPropertyDescription(prop)); } ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.Header(),") =============\n"); } //+------------------------------------------------------------------+
Wenn die Schleife die Eigenschaften "Indikatorhandle" und "Indikatorindex im Fenster" aufweist, werden diese übersprungen. Sie stehen in keinem Zusammenhang mit dem Chart-Objekt.
Bei der Eigenschaft "Chart-Höhe in Pixel" wird die Methode aufgerufen, die die Beschreibung der Eigenschaft für alle Chartfenster anzeigt.
Bei der Eigenschaft "Indikatorname im Fenster" wird die Methode aufgerufen, die die Beschreibung aller Indikatoren anzeigt, die an allen Chartfenstern angebracht sind. Wir werden diese Methoden später besprechen.
Die Methode, die eine kurze Objektbeschreibung anzeigt, wurde ebenfalls verbessert.
Sie zeigt jetzt auch die Anzahl der Chartfenster-Unterfenster an, wenn sie vorhanden sind oder informiert, dass keine Unterfenster vorhanden sind:
//+------------------------------------------------------------------+ //| Display a short description of the object in the journal | //+------------------------------------------------------------------+ void CChartObj::PrintShort(const bool dash=false) { ::Print ( (dash ? "- " : ""),this.Header()," ID: ",(string)this.ID(),", HWND: ",(string)this.Handle(), ", ",CMessage::Text(MSG_CHART_OBJ_CHART_SUBWINDOWS_NUM),": ",(this.WindowsTotal()>1 ? string(this.WindowsTotal()-1) : CMessage::Text(MSG_LIB_TEXT_NO)) ); } //+------------------------------------------------------------------+
Die Methode, die Daten aller Indikatoren aller Chartfenster im Journal anzeigt:
//+-------------------------------------------------------------------+ //| Display data of all indicators of all chart windows in the journal| //+-------------------------------------------------------------------+ void CChartObj::PrintWndIndicators(void) { for(int i=0;i<this.WindowsTotal();i++) { CChartWnd *wnd=m_list_wnd.At(i); if(wnd==NULL) continue; wnd.PrintIndicators(true); } } //+------------------------------------------------------------------+
Hier in der Schleife durch alle Chartfenster-Objekte, das nächste Chartfenster-Objekt holen und die Beschreibungen aller Indikatoren anzeigen, die dem Fenster im Journal zugeordnet sind. Die Methode erhält true , damit der Bindestrich vor einer Indikatorbeschreibung angezeigt wird.
Die Methode, die die Eigenschaften aller Chartfenster im Journal anzeigt:
//+------------------------------------------------------------------+ //| Display the properties of all chart windows in the journal | //+------------------------------------------------------------------+ void CChartObj::PrintWndParameters(void) { for(int i=0;i<this.WindowsTotal();i++) { CChartWnd *wnd=m_list_wnd.At(i); if(wnd==NULL) continue; wnd.PrintParameters(true); } } //+------------------------------------------------------------------+
Hier in der Schleife durch alle Chartfensterobjekte, das nächste Chartfensterobjekt holen und die Beschreibung seiner Parameter im Journal anzeigen. Die Methode erhält true, damit der Bindestrich vor einer Fensterbeschreibung angezeigt wird.
Die Methode gibt das Window-Objekt anhand des Index seines Unterfensters zurück:
//+------------------------------------------------------------------+ //| Return the window object by its subwindow index | //+------------------------------------------------------------------+ CChartWnd *CChartObj::GetWindowByNum(const int win_num) const { int total=m_list_wnd.Total(); for(int i=0;i<total;i++) { CChartWnd *wnd=m_list_wnd.At(i); if(wnd==NULL) continue; if(wnd.WindowNum()==win_num) return wnd; } return NULL; } //+------------------------------------------------------------------+
Hier holen wir uns in der Schleife durch die Gesamtzahl der Chartfenster-Objekte das nächste Fenster-Objekt. Wenn sein Index mit dem an die Methode übergebenen übereinstimmt, geben wir den Zeiger auf das gefundene Objekt in der Liste zurück. Nach dem Ende der Schleife wird NULL zurückgegeben — das Objekt wurde nicht gefunden.
Die Methode, die die Eigenschaft "Unterfenster sichtbar" auf das Chart-Objekt setzt:
//+------------------------------------------------------------------+ //| Set the "Subwindow visibility" property | //+------------------------------------------------------------------+ void CChartObj::SetVisible(void) { this.SetProperty(CHART_PROP_WINDOW_IS_VISIBLE,::ChartGetInteger(this.ID(),CHART_WINDOW_IS_VISIBLE,0)); } //+------------------------------------------------------------------+
Hier fügen wir einfach die entsprechende Nur-Lese-Eigenschaft des Hauptfensters des Charts hinzu.
Die Methode gibt den Abstand in Pixeln der Y-Achse zwischen dem oberen Rahmen des Indikator-Unterfensters und dem oberen Rahmen des Hauptfensters zurück:
//+-----------------------------------------------------------------------------------+ //| Return the distance in pixels by Y axis between | //| the upper frame of the indicator subwindow and the upper frame of the main window | //+-----------------------------------------------------------------------------------+ int CChartObj::WindowYDistance(const int sub_window) const { CChartWnd *wnd=GetWindowByNum(sub_window); return(wnd!=NULL ? wnd.YDistance() : WRONG_VALUE); } //+------------------------------------------------------------------+
Hier erhalten wir das Chartfenster-Objekt durch den Index seines Unterfensters und geben den Eigenschaftswert des erhaltenen Objekts zurück.
Wenn das Objekt nicht empfangen wird, geben wir -1 zurück.
Die Methode gibt die Höhe des angegebenen Charts in Pixel zurück:
//+------------------------------------------------------------------+ //| Return the height of the specified chart in pixels | //+------------------------------------------------------------------+ int CChartObj::WindowHeightInPixels(const int sub_window) const { CChartWnd *wnd=GetWindowByNum(sub_window); return(wnd!=NULL ? wnd.HeightInPixels() : WRONG_VALUE); } //+------------------------------------------------------------------+
Hier erhalten wir das Chartfenster-Objekt durch den Index seines Unterfensters und geben den Eigenschaftswert des erhaltenen Objekts zurück.
Wenn das Objekt nicht empfangen wird, wird -1 zurückgegeben.
Die Methode setzt die Höhe des angegebenen Charts in Pixel:
//+------------------------------------------------------------------+ //| Set the height of the specified chart in pixels | //+------------------------------------------------------------------+ bool CChartObj::SetWindowHeightInPixels(const int height,const int sub_window,const bool redraw=false) { CChartWnd *wnd=GetWindowByNum(sub_window); return(wnd!=NULL ? wnd.SetHeightInPixels(height,redraw) : false); } //+------------------------------------------------------------------+
Hier erhalten wir das Chartfenster-Objekt über den Indes seines Unterfensters und geben das Ergebnis des Setzens der entsprechenden Eigenschaft für das erhaltene Objekt zurück.
Wenn das Objekt nicht empfangen wird, geben wir false zurück.
Entfernen wir die alte Methode, die ich im vorherigen Artikel hinzugefügt habe:
//+------------------------------------------------------------------+
//| Set the height of the specified chart in pixels |
//+------------------------------------------------------------------+
bool CChartObj::SetWindowHeightInPixels(const int height,const int sub_window,const bool redraw=false)
{
::ResetLastError();
if(!::ChartSetInteger(this.ID(),CHART_HEIGHT_IN_PIXELS,sub_window,height))
{
CMessage::ToLog(DFUN,::GetLastError(),true);
return false;
}
if(redraw)
::ChartRedraw(this.ID());
return true;
}
//+------------------------------------------------------------------+
Damit ist die Verbesserung der Chart-Objektklasse abgeschlossen.
Test
Um die Leistung der erstellten Objekte zu überprüfen, öffnen wir einfach drei beliebige Charts. Fügen wir den Fraktal-Indikator in den Chart mit dem EA ein und wir fügen ein weiteres Indikatorfenster hinzu, z.B. DeMarker, das einen anderen Indikator enthält, z.B. AMA, der auf DeMarker-Daten basiert.
Auf dem zweiten Chart werde ich das Stochastik-Fenster platzieren, während das dritte Fenster abgedockt wird (Alt+D):
Ich werde kurze Beschreibungen aller drei Chart-Objekte und die vollständige Beschreibung des aktuellen Charts, in dem sich der EA befindet, im Journal anzeigen.
Für den Test verwende ich den EA aus dem vorherigen Artikel und speichere ihn in \MQL5\Experts\TestDoEasy\Teil68\ als TestDoEasyPart68.mq5.
Der EA bleibt nahezu unverändert. Wir müssen lediglich die Logik in OnTick() einfügen:
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Handle the NewTick event in the library engine.OnTick(rates_data); //--- If working in the tester if(MQLInfoInteger(MQL_TESTER)) { engine.OnTimer(rates_data); // Working in the timer PressButtonsControl(); // Button pressing control engine.EventsHandling(); // Working with events } //--- If the trailing flag is set if(trailing_on) { TrailingPositions(); // Trailing positions TrailingOrders(); // Trailing pending orders } //--- If it is the first launch static bool done=false; if(!done) { //--- Create the list object for storing chart objects CArrayObj *list=new CArrayObj(); if(list==NULL) return; //--- Declare the variables and get the first chart ID long currChart,prevChart=ChartFirst(); int i=0; //--- Create the chart object and add it to the list CChartObj *chart_first=new CChartObj(prevChart); list.Add(chart_first); //--- In the loop by the total number of terminal charts (not more than 100) while(i<CHARTS_MAX) { //--- based on the previous one, get the new chart currChart=ChartNext(prevChart); //--- When reaching the end of the chart list, complete the loop if(currChart<0) break; //--- Create the chart object based on the current chart ID in the loop and add it to the list CChartObj *chart=new CChartObj(currChart); list.Add(chart); //--- remember the current chart ID for ChartNext() and increase the loop counter prevChart=currChart; i++; } Print(""); //--- From the filled list in the loop, receive the next chart object and display its short description int total=list.Total(); for(int j=0;j<total;j++) { CChartObj *chart_obj=list.At(j); if(chart_obj!=NULL) chart_obj.PrintShort(); } Print(""); //--- Display the full description of the current chart: in the loop by all objects of the created list for(int j=0;j<total;j++) { //--- get the next chart object and CChartObj *chart_obj=list.At(j); //--- if its symbol matches the current chart symbol, display its full description in the journal if(chart_obj!=NULL && chart_obj.Symbol()==Symbol()) chart_obj.Print(); } //--- Destroy the list of chart objects delete list; done=true; } //--- } //+------------------------------------------------------------------+
Kompilieren Sie den EA und starten Sie ihn auf dem Chart, während Sie zuvor die erforderliche Terminalumgebung erstellen, die ganz am Anfang des Abschnitts beschrieben wurde.
Im Journal werden Kurzbeschreibungen aller drei geöffneten Charts angezeigt:
Main chart window EURUSD H4 ID: 131733844391938630, HWND: 5179646, Subwindows: 1 Main chart window AUDUSD H4 ID: 131733844391938634, HWND: 3672036, Subwindows: 1 Main chart window GBPUSD H4 ID: 131733844391938633, HWND: 3473910, Subwindows: No
und die vollständige Beschreibung des aktuellen. Das Ergebnis der im aktuellen Artikel entwickelten Klassen wird im Journal in Form mehrerer Zeilen mit den Fensterobjekteigenschaften und den daran angehängten Indikatoren dargestellt:
============= The beginning of the parameter list (Main chart window EURUSD H4) ============= Chart ID: 131733844391938630 Timeframe: H4 Drawing attributes of a price chart: Yes Object "Chart": No Chart on top of other charts: No Accessing the context menu by pressing the right mouse button: Yes Accessing the "Crosshair tool" by pressing the middle mouse button: Yes Scrolling the chart horizontally using the left mouse button: Yes Sending messages about mouse wheel events to all mql5 programs on a chart: No Send notifications of mouse move and mouse click events to all mql5 programs on a chart: No Send a notification of an event of new object creation to all mql5-programs on a chart: No Send a notification of an event of object deletion to all mql5-programs on a chart: No Chart type: Display as Japanese candlesticks Price chart in the foreground: No Price chart indent from the right border: Yes Automatic moving to the right border of the chart: Yes Managing the chart using a keyboard: Yes Allowed to intercept Space and Enter key presses on the chart to activate the quick navigation bar: Yes Scale: 2 Fixed scale mode: No Scale 1:1 mode: No Scale to be specified in points per bar: No Display a symbol ticker in the upper left corner: Yes Display OHLC values in the upper left corner: Yes Display Bid values as a horizontal line in a chart: Yes Display Ask values as a horizontal line in a chart: Yes Display Last values as a horizontal line in a chart: No Display vertical separators between adjacent periods: No Display grid in the chart: No Display volume in the chart: Trade volumes Display textual descriptions of objects: Yes The number of bars on the chart that can be displayed: 137 The total number of chart windows, including indicator subwindows: 2 Visibility of subwindow: Yes Chart window handle: 5179646 Number of the first visible bar in the chart: 136 Chart width in bars: 168 Chart width in pixels: 670 Main chart window: - Chart height in pixels: 301 Chart subwindow 1: - The distance between the upper frame of the indicator subwindow and the upper frame of the main chart window: 303 - Chart height in pixels: 13 Chart background color: clrWhite Color of axes, scales and OHLC line: clrBlack Grid color: clrSilver Color of volumes and position opening levels: clrGreen Color for the up bar, shadows and body borders of bull candlesticks: clrBlack Color for the down bar, shadows and body borders of bear candlesticks: clrBlack Line chart color and color of "Doji" Japanese candlesticks: clrBlack Body color of a bull candlestick: clrWhite Body color of a bear candlestick: clrBlack Bid price level color: clrLightSkyBlue Ask price level color: clrCoral Line color of the last executed deal price (Last): clrSilver Color of stop order levels (Stop Loss and Take Profit): clrOrangeRed Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders): Yes Permission to drag trading levels on a chart with a mouse: Yes Showing the time scale on a chart: Yes Showing the price scale on a chart: Yes Showing the "One click trading" panel on a chart: No Chart window is maximized: Yes Chart window is minimized: No The chart window is docked: Yes The left coordinate of the undocked chart window relative to the virtual screen: 0 The top coordinate of the undocked chart window relative to the virtual screen: 0 The right coordinate of the undocked chart window relative to the virtual screen: 0 The bottom coordinate of the undocked chart window relative to the virtual screen: 0 ------ The size of the zero bar indent from the right border in percents: 18.93 Chart fixed position from the left border in percent value: 0.00 Fixed chart maximum: 1.22620 Fixed chart minimum : 1.17940 Scale in points per bar: 1.00 Chart minimum: 1.17940 Chart maximum: 1.22620 ------ Text of a comment in a chart: "" The name of the Expert Advisor running on the chart: "TestDoEasyPart68" The name of the script running on the chart: "" Indicators in the main chart window: - Indicator Fractals Indicators in the chart window 1: - Indicator DeM(14) - Indicator AMA(14,2,30) Symbol: "EURUSD" ============= End of the parameter list (Main chart window EURUSD H4) =============
Was kommt als Nächstes?
Im nächsten Artikel werde ich mit der Entwicklung der Kollektionsklasse der Chartobjekte beginnen.
Alle Dateien der aktuellen Version der Bibliothek sind unten zusammen mit der Test-EA-Datei für MQL5 zum Testen und Herunterladen angehängt.
Ich empfehle nicht, Chart-Objekte in ihrem aktuellen Zustand in Ihrer Arbeit zu verwenden, da sie weiter verändert werden sollen.
Ihre Fragen und Vorschläge schreiben Sie bitte in den Kommentarteil.
*Frühere Artikel dieser Serie:
Preise in der DoEasy-Bibliothek (Teil 62): Aktualisieren der Tick-Serien in Echtzeit, Vorbereitung für die Arbeit mit Markttiefe
Preise in der DoEasy-Bibliothek (Teil 63): Markttiefe und deren abstrakte Anforderungsklasse
Preise in der DoEasy-Bibliothek (Teil 64): Markttiefe, Klassenobjekte für Schnappschüsse der Markttiefe und der Schnappschuss-Reihen
Preise und Signale in der DoEasy-Bibliothek (Teil 65): Kollektion der Markttiefe und die Klasse für die Arbeit mit MQL5.com- Signalen
Andere Klassen in der Bibliothek DoEasy (Teil 66): MQL5.com die Kollektionsklasse der Signale
Andere Klassen in der Bibliothek DoEasy (Teil 67): Objektklasse der Charts
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/9236
- 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.