English Русский Español Deutsch 日本語 Português
DoEasy 函数库中的图形(第九十三部分):准备创建复合图形对象的功能

DoEasy 函数库中的图形(第九十三部分):准备创建复合图形对象的功能

MetaTrader 5示例 | 8 四月 2022, 13:01
647 0
Artyom Trishkin
Artyom Trishkin

内容


概述

MetaTrader 5 客户端 提供了一套广泛的图形分析工具,可用于图表上构造的各种图形。 但我还是经常听到一些用户抱怨缺乏某些工具。 该终端拥有 44 种分析工具。 想象一下,如果我们能够将这些图形对象组合成捆绑的集合,从而创建新的技术分析工具,我们会做什么。 MQL5 语言令我们可以做到这一切!

该函数库将支持创建复合图形对象,允许这些对象含有任意层次的连接。 每个这样的对象都有一个基本的图形对象,该对象含有附于其上的其它图形对象的列表。 基准对象将拥有管理从属图形对象属性的功能,而从属对象又拥有一组它们加载时的基准对象 X 和 Y 坐标。 整个基准对象属性列表均可用作坐标。 例如,为了计算从属对象的 X 坐标,我们可以使用多个 X 坐标(例如,两个坐标 — 趋势线的点 0 和点 1),而非基准对象点的 X 坐标。 在此情况下,基准对象的两个 X 坐标的平均值可以用作从属对象的 X 坐标。

在基准对象列表中的每个从属对象也可以是其列表中其它图形对象的基准对象。 这样就允许从不同的组合图形对象创建各种集合。
甚而,我将尝试以编程方式实现创建这样的对象(其中每个从属对象都被添加到程序代码中的基准对象列表中),不光如此,而且还可以实时创建它们。 当把一个图形对象拖动到另一个图形对象上时,它将依据视觉选择的定位点附着到该图形对象上,这些定位点可以在以后重新定义。

在本文中,我将创建扩展标准图形对象的功能 — 标准图形对象的新属性,指示对象已扩展,以及存储基准对象坐标相关属性的类,用于计算和指定从属对象的坐标。


改进库类

在 \MQL5\Include\DoEasy\Defines.mqh 中的图形元素类型枚举里,添加另一个种类 — 扩展标准图形对象:

//+------------------------------------------------------------------+
//| The list of graphical element types                              |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_ELEMENT_TYPE
  {
   GRAPH_ELEMENT_TYPE_STANDARD,                       // Standard graphical object
   GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED,              // Extended standard graphical object
   GRAPH_ELEMENT_TYPE_ELEMENT,                        // Element
   GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                     // Shadow object
   GRAPH_ELEMENT_TYPE_FORM,                           // Form
   GRAPH_ELEMENT_TYPE_WINDOW,                         // Window
  };
//+------------------------------------------------------------------+

在图形对象整数型属性的枚举中,添加属性(基准图形对象 ID),并将整数型属性的数量从 54 增加到 55

//+------------------------------------------------------------------+
//| Integer properties of a standard graphical object                |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_OBJ_PROP_INTEGER
  {
   //--- Additional properties
   GRAPH_OBJ_PROP_ID = 0,                             // Object ID
   GRAPH_OBJ_PROP_BASE_ID,                            // Base object ID
   GRAPH_OBJ_PROP_TYPE,                               // Graphical object type (ENUM_OBJECT)
   GRAPH_OBJ_PROP_ELEMENT_TYPE,                       // Graphical element type (ENUM_GRAPH_ELEMENT_TYPE)
   GRAPH_OBJ_PROP_SPECIES,                            // Graphical object species (ENUM_GRAPH_OBJ_SPECIES)
   GRAPH_OBJ_PROP_BELONG,                             // Graphical object affiliation
   GRAPH_OBJ_PROP_CHART_ID,                           // Chart ID
   GRAPH_OBJ_PROP_WND_NUM,                            // Chart subwindow index
   GRAPH_OBJ_PROP_NUM,                                // Object index in the list
   GRAPH_OBJ_PROP_CHANGE_HISTORY,                     // Flag of storing the change history
   GRAPH_OBJ_PROP_GROUP,                              // Group of objects the graphical object belongs to
   //--- Common properties of all graphical objects
   GRAPH_OBJ_PROP_CREATETIME,                         // Object creation time
   GRAPH_OBJ_PROP_TIMEFRAMES,                         // Object visibility on timeframes
   GRAPH_OBJ_PROP_BACK,                               // Background object
   GRAPH_OBJ_PROP_ZORDER,                             // Priority of a graphical object for receiving the event of clicking on a chart
   GRAPH_OBJ_PROP_HIDDEN,                             // Disable displaying the name of a graphical object in the terminal object list
   GRAPH_OBJ_PROP_SELECTED,                           // Object selection
   GRAPH_OBJ_PROP_SELECTABLE,                         // Object availability
//--- Properties belonging to different graphical objects
   GRAPH_OBJ_PROP_TIME,                               // Time coordinate
   GRAPH_OBJ_PROP_COLOR,                              // Color
   GRAPH_OBJ_PROP_STYLE,                              // Style
   GRAPH_OBJ_PROP_WIDTH,                              // Line width
   GRAPH_OBJ_PROP_FILL,                               // Object color filling
   GRAPH_OBJ_PROP_READONLY,                           // Ability to edit text in the Edit object
   GRAPH_OBJ_PROP_LEVELS,                             // Number of levels
   GRAPH_OBJ_PROP_LEVELCOLOR,                         // Level line color
   GRAPH_OBJ_PROP_LEVELSTYLE,                         // Level line style
   GRAPH_OBJ_PROP_LEVELWIDTH,                         // Level line width
   GRAPH_OBJ_PROP_ALIGN,                              // Horizontal text alignment in the Edit object (OBJ_EDIT)
   GRAPH_OBJ_PROP_FONTSIZE,                           // Font size
   GRAPH_OBJ_PROP_RAY_LEFT,                           // Ray goes to the left
   GRAPH_OBJ_PROP_RAY_RIGHT,                          // Ray goes to the right
   GRAPH_OBJ_PROP_RAY,                                // Vertical line goes through all windows of a chart
   GRAPH_OBJ_PROP_ELLIPSE,                            // Display the full ellipse of the Fibonacci Arc object
   GRAPH_OBJ_PROP_ARROWCODE,                          // Arrow code for the "Arrow" object
   GRAPH_OBJ_PROP_ANCHOR,                             // Position of the binding point of the graphical object
   GRAPH_OBJ_PROP_XDISTANCE,                          // Distance from the base corner along the X axis in pixels
   GRAPH_OBJ_PROP_YDISTANCE,                          // Distance from the base corner along the Y axis in pixels
   GRAPH_OBJ_PROP_DIRECTION,                          // Gann object trend
   GRAPH_OBJ_PROP_DEGREE,                             // Elliott wave marking level
   GRAPH_OBJ_PROP_DRAWLINES,                          // Display lines for Elliott wave marking
   GRAPH_OBJ_PROP_STATE,                              // Button state (pressed/released)
   GRAPH_OBJ_PROP_CHART_OBJ_CHART_ID,                 // Chart object ID (OBJ_CHART).
   GRAPH_OBJ_PROP_CHART_OBJ_PERIOD,                   // Chart object period
   GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE,               // Time scale display flag for the Chart object
   GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE,              // Price scale display flag for the Chart object
   GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE,              // Chart object scale
   GRAPH_OBJ_PROP_XSIZE,                              // Object width along the X axis in pixels.
   GRAPH_OBJ_PROP_YSIZE,                              // Object height along the Y axis in pixels.
   GRAPH_OBJ_PROP_XOFFSET,                            // X coordinate of the upper-left corner of the visibility area.
   GRAPH_OBJ_PROP_YOFFSET,                            // Y coordinate of the upper-left corner of the visibility area.
   GRAPH_OBJ_PROP_BGCOLOR,                            // Background color for OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
   GRAPH_OBJ_PROP_CORNER,                             // Chart corner for binding a graphical object
   GRAPH_OBJ_PROP_BORDER_TYPE,                        // Border type for "Rectangle border"
   GRAPH_OBJ_PROP_BORDER_COLOR,                       // Border color for OBJ_EDIT and OBJ_BUTTON
  };
#define GRAPH_OBJ_PROP_INTEGER_TOTAL (55)             // Total number of integer properties
#define GRAPH_OBJ_PROP_INTEGER_SKIP  (0)              // Number of integer properties not used in sorting
//+------------------------------------------------------------------+

在每个从属对象中设置基准对象 ID(从 1 开始)。 属性为零值表示该对象未附于到任何其它对象,且不是从属对象。

在图形对象的字符串型属性枚举中,添加属性 — 基准图形对象的名称,将字符串型属性的数量从 7 增加到 8

//+------------------------------------------------------------------+
//| String properties of a standard graphical object                 |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_OBJ_PROP_STRING
  {
   GRAPH_OBJ_PROP_NAME = (GRAPH_OBJ_PROP_INTEGER_TOTAL+GRAPH_OBJ_PROP_DOUBLE_TOTAL), // Object name
   GRAPH_OBJ_PROP_BASE_NAME,                          // Base object name
   GRAPH_OBJ_PROP_TEXT,                               // Object description (text contained in the object)
   GRAPH_OBJ_PROP_TOOLTIP,                            // Tooltip text
   GRAPH_OBJ_PROP_LEVELTEXT,                          // Level description
   GRAPH_OBJ_PROP_FONT,                               // Font
   GRAPH_OBJ_PROP_BMPFILE,                            // BMP file name for the "Bitmap Level" object
   GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL,                   // Symbol for the Chart object 
  };
#define GRAPH_OBJ_PROP_STRING_TOTAL  (8)              // Total number of string properties
//+------------------------------------------------------------------+

在可能的图形对象排序标准的枚举中加入新常量(对应于上面添加的新图形对象属性):

//+------------------------------------------------------------------+
//| Possible sorting criteria of graphical objects                   |
//+------------------------------------------------------------------+
#define FIRST_GRAPH_OBJ_DBL_PROP  (GRAPH_OBJ_PROP_INTEGER_TOTAL-GRAPH_OBJ_PROP_INTEGER_SKIP)
#define FIRST_GRAPH_OBJ_STR_PROP  (GRAPH_OBJ_PROP_INTEGER_TOTAL-GRAPH_OBJ_PROP_INTEGER_SKIP+GRAPH_OBJ_PROP_DOUBLE_TOTAL-GRAPH_OBJ_PROP_DOUBLE_SKIP)
enum ENUM_SORT_GRAPH_OBJ_MODE
  {
//--- Sort by integer properties
   SORT_BY_GRAPH_OBJ_ID = 0,                             // Sort by object ID
   SORT_BY_GRAPH_OBJ_BASE_ID,                            // Sort by object ID
   SORT_BY_GRAPH_OBJ_TYPE,                               // Sort by object type
   SORT_BY_GRAPH_OBJ_ELEMENT_TYPE,                       // Sort by graphical element type
   SORT_BY_GRAPH_OBJ_SPECIES,                            // Sort by a graphical object species
   SORT_BY_GRAPH_OBJ_BELONG,                             //  Sort by a graphical element affiliation
   SORT_BY_GRAPH_OBJ_CHART_ID,                           // Sort by chart ID
   SORT_BY_GRAPH_OBJ_WND_NUM,                            // Sort by chart subwindow index
   SORT_BY_GRAPH_OBJ_NUM,                                // Sort by object index in the list
   SORT_BY_GRAPH_OBJ_CHANGE_HISTORY,                     // Sort by the flag of storing the change history
   SORT_BY_GRAPH_OBJ_GROUP,                              // Sort by the group of objects the graphical object belongs to
   SORT_BY_GRAPH_OBJ_CREATETIME,                         // Sort by object creation time
   SORT_BY_GRAPH_OBJ_TIMEFRAMES,                         // Sort by object visibility on timeframes
   SORT_BY_GRAPH_OBJ_BACK,                               // Sort by the "Background object" property
   SORT_BY_GRAPH_OBJ_ZORDER,                             // Sort by the priority of a graphical object for receiving the event of clicking on a chart
   SORT_BY_GRAPH_OBJ_HIDDEN,                             // Sort by a disabling display of the name of a graphical object in the terminal object list
   SORT_BY_GRAPH_OBJ_SELECTED,                           // Sort by the "Object selection" property
   SORT_BY_GRAPH_OBJ_SELECTABLE,                         // Sort by the "Object availability" property
   SORT_BY_GRAPH_OBJ_TIME,                               // Sort by time coordinate
   SORT_BY_GRAPH_OBJ_COLOR,                              // Sort by color
   SORT_BY_GRAPH_OBJ_STYLE,                              // Sort by style
   SORT_BY_GRAPH_OBJ_WIDTH,                              // Sort by line width
   SORT_BY_GRAPH_OBJ_FILL,                               // Sort by the "Object color filling" property
   SORT_BY_GRAPH_OBJ_READONLY,                           // Sort by the ability to edit text in the Edit object
   SORT_BY_GRAPH_OBJ_LEVELS,                             // Sort by number of levels
   SORT_BY_GRAPH_OBJ_LEVELCOLOR,                         // Sort by line level color
   SORT_BY_GRAPH_OBJ_LEVELSTYLE,                         // Sort by line level style
   SORT_BY_GRAPH_OBJ_LEVELWIDTH,                         // Sort by line level width
   SORT_BY_GRAPH_OBJ_ALIGN,                              // Sort by the "Horizontal text alignment in the Entry field" property
   SORT_BY_GRAPH_OBJ_FONTSIZE,                           // Sort by font size
   SORT_BY_GRAPH_OBJ_RAY_LEFT,                           // Sort by "Ray goes to the left" property
   SORT_BY_GRAPH_OBJ_RAY_RIGHT,                          // Sort by "Ray goes to the right" property
   SORT_BY_GRAPH_OBJ_RAY,                                // Sort by the "Vertical line goes through all windows of a chart" property
   SORT_BY_GRAPH_OBJ_ELLIPSE,                            // Sort by the "Display the full ellipse of the Fibonacci Arc object" property
   SORT_BY_GRAPH_OBJ_ARROWCODE,                          // Sort by an arrow code for the Arrow object
   SORT_BY_GRAPH_OBJ_ANCHOR,                             // Sort by the position of a binding point of a graphical object
   SORT_BY_GRAPH_OBJ_XDISTANCE,                          // Sort by a distance from the base corner along the X axis in pixels
   SORT_BY_GRAPH_OBJ_YDISTANCE,                          // Sort by a distance from the base corner along the Y axis in pixels
   SORT_BY_GRAPH_OBJ_DIRECTION,                          // Sort by the "Gann object trend" property
   SORT_BY_GRAPH_OBJ_DEGREE,                             // Sort by the "Elliott wave marking level" property
   SORT_BY_GRAPH_OBJ_DRAWLINES,                          // Sort by the "Display lines for Elliott wave marking" property
   SORT_BY_GRAPH_OBJ_STATE,                              // Sort by button state (pressed/released)
   SORT_BY_GRAPH_OBJ_OBJ_CHART_ID,                       // Sort by Chart object ID.
   SORT_BY_GRAPH_OBJ_CHART_OBJ_PERIOD,                   // Sort by Chart object period
   SORT_BY_GRAPH_OBJ_CHART_OBJ_DATE_SCALE,               // Sort by time scale display flag for the Chart object
   SORT_BY_GRAPH_OBJ_CHART_OBJ_PRICE_SCALE,              // Sort by price scale display flag for the Chart object
   SORT_BY_GRAPH_OBJ_CHART_OBJ_CHART_SCALE,              // Sort by Chart object scale
   SORT_BY_GRAPH_OBJ_XSIZE,                              // Sort by Object width along the X axis in pixels
   SORT_BY_GRAPH_OBJ_YSIZE,                              // Sort by object height along the Y axis in pixels
   SORT_BY_GRAPH_OBJ_XOFFSET,                            // Sort by X coordinate of the upper-left corner of the visibility area
   SORT_BY_GRAPH_OBJ_YOFFSET,                            // Sort by Y coordinate of the upper-left corner of the visibility area
   SORT_BY_GRAPH_OBJ_BGCOLOR,                            // Sort by background color for OBJ_EDIT, OBJ_BUTTON and OBJ_RECTANGLE_LABEL
   SORT_BY_GRAPH_OBJ_CORNER,                             // Sort by chart corner for binding a graphical object
   SORT_BY_GRAPH_OBJ_BORDER_TYPE,                        // Sort by border type for the "Rectangle border" object
   SORT_BY_GRAPH_OBJ_BORDER_COLOR,                       // Sort by frame color for the OBJ_EDIT and OBJ_BUTTON objects
//--- Sort by real properties
   SORT_BY_GRAPH_OBJ_PRICE = FIRST_GRAPH_OBJ_DBL_PROP,   // Sort by price coordinate
   SORT_BY_GRAPH_OBJ_LEVELVALUE,                         // Sort by level value
   SORT_BY_GRAPH_OBJ_SCALE,                              // Sort by scale (property of Gann objects and Fibonacci Arcs objects)
   SORT_BY_GRAPH_OBJ_ANGLE,                              // Sort by angle
   SORT_BY_GRAPH_OBJ_DEVIATION,                          // Sort by a deviation of the standard deviation channel
//--- Sort by string properties
   SORT_BY_GRAPH_OBJ_NAME = FIRST_GRAPH_OBJ_STR_PROP,    // Sort by object name
   SORT_BY_GRAPH_OBJ_BASE_NAME,                          // Sort by base object name
   SORT_BY_GRAPH_OBJ_TEXT,                               // Sort by object description
   SORT_BY_GRAPH_OBJ_TOOLTIP,                            // Sort by tooltip text
   SORT_BY_GRAPH_OBJ_LEVELTEXT,                          // Sort by level description
   SORT_BY_GRAPH_OBJ_FONT,                               // Sort by font
   SORT_BY_GRAPH_OBJ_BMPFILE,                            // Sort by BMP file name for the "Bitmap Level" object
   SORT_BY_GRAPH_OBJ_CHART_OBJ_SYMBOL,                   // Sort by Chart object period symbol
  };
//+------------------------------------------------------------------+

现在我们可以根据相应的属性选择对象,按它们排序,并创建拥有类似属性的对象列表。


在 \MQL5\Include\DoEasy\Data.mqh 中,添加函数库新消息索引

   MSG_LIB_SYS_REQUEST_OUTSIDE_LONG_ARRAY,            // Request outside long array
   MSG_LIB_SYS_REQUEST_OUTSIDE_DOUBLE_ARRAY,          // Request outside double array
   MSG_LIB_SYS_REQUEST_OUTSIDE_STRING_ARRAY,          // Request outside string array
   MSG_LIB_SYS_REQUEST_OUTSIDE_ARRAY,                 // Request outside the array

...

   MSG_GRAPH_ELEMENT_TYPE_STANDARD,                   // Standard graphical object
   MSG_GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED,          // Extended standard graphical object
   MSG_GRAPH_ELEMENT_TYPE_ELEMENT,                    // Element
   MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                 // Shadow object
   MSG_GRAPH_ELEMENT_TYPE_FORM,                       // Form
   MSG_GRAPH_ELEMENT_TYPE_WINDOW,                     // Window

...

   MSG_GRAPH_OBJ_PROP_ID,                             // Object ID
   MSG_GRAPH_OBJ_PROP_BASE_ID,                        // Base object ID
   MSG_GRAPH_OBJ_PROP_TYPE,                           // Graphical object type (ENUM_OBJECT)
   MSG_GRAPH_OBJ_PROP_ELEMENT_TYPE,                   // Graphical element type (ENUM_GRAPH_ELEMENT_TYPE)

...

   MSG_GRAPH_OBJ_PROP_NAME,                           // Object name
   MSG_GRAPH_OBJ_PROP_BASE_NAME,                      // Base object name
   MSG_GRAPH_OBJ_PROP_TEXT,                           // Object description (text contained in the object)
   MSG_GRAPH_OBJ_PROP_TOOLTIP,                        // Tooltip text
   MSG_GRAPH_OBJ_PROP_LEVELTEXT,                      // Level description
   MSG_GRAPH_OBJ_PROP_FONT,                           // Font
   MSG_GRAPH_OBJ_PROP_BMPFILE,                        // BMP file name for the "Bitmap Level" object
   MSG_GRAPH_OBJ_PROP_SYMBOL,                         // Chart object symbol

...

   MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_CREATE,                // New graphical object created
   MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_CHANGE,                // Changed the graphical object property
   MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_RENAME,                // Graphical object renamed
   MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_DELETE,                // Graphical object removed
   MSG_GRAPH_OBJ_EVN_GRAPH_OBJ_DEL_CHART,             // Graphical object removed together with the chart
   
//--- CGStdGraphObj (Extended)
   MSG_GRAPH_OBJ_FAILED_CREATE_NEW_EXT_OBJ,           //  Failed to create the class object of an extended graphical object
   MSG_GRAPH_OBJ_FAILED_CREATE_NEW_BASE_EXT_OBJ,      // Failed to create the base object for an extended graphical object
   MSG_GRAPH_OBJ_FAILED_ADD_EXT_OBJ_TO_LIST,          // Failed to add the extended standard graphical object to the list
   MSG_GRAPH_OBJ_FAILED_ADD_BASE_EXT_OBJ_TO_LIST,     // Failed to add the base object to the list
   MSG_GRAPH_OBJ_FAILED_CREATE_NEW_DEP_EXT_OBJ,       // Failed to create the subordinate object of an extended graphical object
   MSG_GRAPH_OBJ_FAILED_ADD_DEP_EXT_OBJ_TO_LIST,      // Failed to add the subordinate object to the list
   MSG_GRAPH_OBJ_FAILED_GET_EXT_OBJ_FROM_LIST,        // Failed to receive the extended graphical object from the list
   MSG_GRAPH_OBJ_PROP_NUM_EXT_BASE_OBJ,               // Base object of the extended graphical object
   MSG_GRAPH_OBJ_NOT_EXT_OBJ,                         // The object is not an extended standard graphical object
   
//--- CLinkedPivotPoint
   MSG_GRAPH_OBJ_EXT_NOT_ANY_PIVOTS_X,                // Not a single pivot point is set for the object along the X axis
   MSG_GRAPH_OBJ_EXT_NOT_ANY_PIVOTS_Y,                // Not a single pivot point is set for the object along the Y axis
   MSG_GRAPH_OBJ_EXT_NOT_ATACHED_TO_BASE,             // The object is not attached to the basic graphical object
   MSG_GRAPH_OBJ_EXT_FAILED_CREATE_PP_DATA_OBJ,       // Failed to create a data object for the X and Y pivot points
  };
//+------------------------------------------------------------------+

与新增索引相对应的消息

   {"Запрос за пределами long-массива","Data requested outside the long-array"},
   {"Запрос за пределами double-массива","Data requested outside the double-array"},
   {"Запрос за пределами string-массива","Data requested outside the string-array"},
   {"Запрос за пределами массива","Data requested outside the array"},

...

   {"Стандартный графический объект","Standard graphic object"},
   {"Расширенный стандартный графический объект","Extended standard graphic object"},
   {"Элемент","Element"},
   {"Объект тени","Shadow object"},
   {"Форма","Form"},
   {"Окно","Window"},

...

   {"Идентификатор объекта","Object ID"},
   {"Идентификатор базового объекта","Base object ID"},
   {"Тип объекта","Object type"},
   {"Тип графического элемента","Graphic element type"},

...

   {"Имя","Name"},
   {"Имя базового объекта","Base object name"},
   {"Описание","Description"},
   {"Текст всплывающей подсказки","The text of a tooltip"},
   {"Описание уровня","Level description"},
   {"Шрифт","Font"},
   {"Имя BMP-файла","BMP-file name"},
   {"Символ графика","Chart Symbol"},

...

   {"Создан новый графический объект","New graphic object created"},
   {"Изменено свойство графического объекта","Changed graphic object property"},
   {"Графический объект переименован","Graphic object renamed"},
   {"Удалён графический объект","Graphic object deleted"},
   {"Графический объект удалён вместе с графиком","The graphic object has been removed along with the chart"},
   
//--- CGStdGraphObj (Extended)
   {"Не удалось создать объект класса расширенного графического объекта","Failed to create the class object of extended standart graphics object"},
   {"Не удалось создать базовый объект расширенного графического объекта","Failed to create the base object of a extended graphics object"},
   {"Не удалось добавить расширенный стандартный графический объект в список","Failed to add extended standard graphic object to the list"},
   {"Не удалось добавить базовый объект в список","Failed to add base object to list"},
   {"Не удалось создать подчинённый объект расширенного графического объекта","Failed to create the dependent object of a extended graphics object"},
   {"Не удалось добавить подчинённый объект в список","Failed to add dependent object to list"},
   {"Не удалось получить расширенный графический объект из списка","Failed to get extended graphic object from list"},
   {"Базовый объект расширенного графического объекта","The base object of the extended graphical object"},
   {"Объект не является расширенным стандартным графическим объектом","The object is not an extended standard graphical object"},
   
//--- CLinkedPivotPoint
   {"Для объекта не установлено ни одной опорной точки по оси X","The object does not have any pivot points set along the x-axis"},
   {"Для объекта не установлено ни одной опорной точки по оси Y","The object does not have any pivot points set along the y-axis"},
   {"Объект не привязан к базовому графическому объекту","The object is not attached to the base graphical object"},
   {"Не удалось создать объект данных опорной точки X и Y.","Failed to create X and Y reference point data object"},
   
  };
//+---------------------------------------------------------------------+


扩展的标准图形对象基于标准图形对象。 为了让对象能够扩展,为其设置扩展图形对象属性。 它将调用为处理扩展的标准图形对象而创建的功能,方法是将从属对象添加到其列表中,并对其进行管控。

我们已拥有所有标准图形对象的类,它们是抽象标准图形对象类的衍生后代。 在此,我们需要做的就是指定一个标志,标记正在创建的是扩展图形对象,而非常规图形对象。

这样的一个对象是以编程方式创建的,故此对象的从属属性应设置为“对象属于程序”(手动创建对象的属性默认设置)。 标准扩展图形对象类型的设置方式相同。 所有这些都是根据图形对象的构造函数在创建期间传递给它的标志值来完成的。

除了这些改进,我们还需要在返回表示支持该对象属性标志的方法里设置新的图形对象属性。
由于所有这些变更对于位于
\MQL5\Include\DoEasy\Objects\Graph\Standard\ 中的所有标准图形对象类都相同,那么我考虑只修改 GStdArrowBuyObj.mqh 的实现作为一个例子。

类构造函数会接收扩展标准图形对象的标志依赖标志值我们应该明确这是否是一个标准图形对象或是标准扩展图形对象,以及对象是否由手动创建或由程序生成:

public:
   //--- Constructor
                     CGStdArrowBuyObj(const long chart_id,const string name,const bool extended) : 
                        CGStdGraphObj(OBJECT_DE_TYPE_GSTD_ARROW_BUY,(!extended ? GRAPH_ELEMENT_TYPE_STANDARD : GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED),(!extended ? GRAPH_OBJ_BELONG_NO_PROGRAM : GRAPH_OBJ_BELONG_PROGRAM),GRAPH_OBJ_SPECIES_ARROWS,chart_id,1,name)
                          {
                           //--- Specify the object property
                           CGStdGraphObj::SetProperty(GRAPH_OBJ_PROP_ANCHOR,0,ANCHOR_TOP);
                          }

在返回指示对象可支持的整数型字符串型属性标志的方法中,添加上面实现的新属性

//+------------------------------------------------------------------+
//| Return 'true' if an object supports a passed                     |
//| integer property, otherwise return 'false'                       |
//+------------------------------------------------------------------+
bool CGStdArrowBuyObj::SupportProperty(ENUM_GRAPH_OBJ_PROP_INTEGER property)
  {
   switch((int)property)
     {
      //--- Supported properties
      case GRAPH_OBJ_PROP_ID           :
      case GRAPH_OBJ_PROP_BASE_ID      :
      case GRAPH_OBJ_PROP_TYPE         :
      case GRAPH_OBJ_PROP_ELEMENT_TYPE : 
      case GRAPH_OBJ_PROP_GROUP        : 
      case GRAPH_OBJ_PROP_BELONG       :
      case GRAPH_OBJ_PROP_CHART_ID     :
      case GRAPH_OBJ_PROP_WND_NUM      :
      case GRAPH_OBJ_PROP_NUM          :
      case GRAPH_OBJ_PROP_CREATETIME   :
      case GRAPH_OBJ_PROP_CHANGE_HISTORY:
      case GRAPH_OBJ_PROP_TIMEFRAMES   :
      case GRAPH_OBJ_PROP_BACK         :
      case GRAPH_OBJ_PROP_ZORDER       :
      case GRAPH_OBJ_PROP_HIDDEN       :
      case GRAPH_OBJ_PROP_SELECTED     :
      case GRAPH_OBJ_PROP_SELECTABLE   :
      case GRAPH_OBJ_PROP_TIME         :
      case GRAPH_OBJ_PROP_COLOR        :
      case GRAPH_OBJ_PROP_STYLE        :
      case GRAPH_OBJ_PROP_WIDTH        :
      case GRAPH_OBJ_PROP_ANCHOR       : return true;
      //--- Other properties are not supported
      //--- Default is 'false'
      default: break;
     }
   return false;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an object supports a passed                     |
//| real property, otherwise return 'false'                          |
//+------------------------------------------------------------------+
bool CGStdArrowBuyObj::SupportProperty(ENUM_GRAPH_OBJ_PROP_DOUBLE property)
  {
   switch((int)property)
     {
      //--- Supported properties
      case GRAPH_OBJ_PROP_PRICE        : return true;
      //--- Other properties are not supported
      //--- Default is 'false'
      default: break;
     }
   return false;
  }
//+------------------------------------------------------------------+
//| Return 'true' if an object supports a passed                     |
//| string property, otherwise return 'false'                        |
//+------------------------------------------------------------------+
bool CGStdArrowBuyObj::SupportProperty(ENUM_GRAPH_OBJ_PROP_STRING property)
  {
   switch((int)property)
     {
      //--- Supported properties
      case GRAPH_OBJ_PROP_NAME            :
      case GRAPH_OBJ_PROP_BASE_NAME       :
      case GRAPH_OBJ_PROP_TEXT            :
      case GRAPH_OBJ_PROP_TOOLTIP         :  return true;
      //--- Other properties are not supported
      //--- Default is 'false'
      default: break;
     }
   return false;
  }
//+------------------------------------------------------------------+

这些更改应在 \MQL5\Include\DoEasy\Objects\Graph\Standard\ 中的所有文件中实现。 这项工作已经完成。 您可以在文后附件中看到所有的改进。

在实现了这些改进之后,新属性可由标准图形对象类的所有对象进行处理,因此我们能够以最高的效率处理这些属性,因为每个这样的对象现在都拥有支持这些新属性的标志。

在 \MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqh 基准图形对象类文件里,也就是说,在返回图形元素类型描述的方法中,添加“扩展标准图形对象”图形元素类型的验证,从而我们能够正确显示图形对象描述:

//+------------------------------------------------------------------+
//| Return the description of the graphical element type             |
//+------------------------------------------------------------------+
string CGBaseObj::TypeElementDescription(void)
  {
   return
     (
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_STANDARD           ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD)           :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED  ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)  :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_ELEMENT            ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_ELEMENT)            :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_SHADOW_OBJ         ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ)         :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_FORM               ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_FORM)               :
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_WINDOW             ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_WINDOW)             :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+


用于指定对象从属坐标的类

基准图形对象列表中的任何从属对象都有自己的构造坐标。 同时,基准图形对象应该知道如何管控从属对象坐标。 为了让基准对象知道从属图形对象所绑定的坐标,后者应该拥有某些属性以便基准对象能够计算,并在其自身坐标发生更改时向从属对象发送坐标变更的命令。

为了在基准对象属性和从属对象属性之间建立这样的连接,请创建该类,并将其称为对象轴点连接类。

我们将会有三个类:

  1. 轴点数据类,用于存储从属对象所附于的基准对象坐标的轴点属性;
  2. 两个轴点数据的类,用于存储前两个类对象。 第一个类存储属性的数据,这些属性是附着于基准对象上的从属对象 X 坐标,而第二个类则存储 Y 坐标;
  3. 连接轴心的类。 该类用于存储第二个类型对象的列表。 两个锚定点数据类中其一的对象负责其轴点的每一个。 换言之,每个对象将存储构造从属对象单个锚定点的基准对象的属性 — 其 X 和 Y 坐标;反过来,可用多个基准对象坐标进行计算,这些坐标的相关列表存储在每个坐标轴的第一个类对象当中。

第一种类型的对象将基于通常的二维数组创建。
数组的第二维度为 2,零单元格表示属性本身,例如时间或价格,而第一维度包含属性修饰符。 假设趋势线有两个锚定点。 在此情况下,坐标点数据设置到数组第二维度的单元格 1。 趋势线左侧锚点的索引值为 0,右侧点的索引值为 1。
在大多数情况下,第一维数组的大小为 1,这意味着只指定了一个基准对象属性,其坐标则表示所附着的从属对象。 但如果我们需要将对象附加到计算出的坐标上,例如,在两个趋势线点之间,那么我们就需要将数组维数增加到两。 第一个设置基准对象的第一个锚点的属性,而第二个包含第二个锚点的属性。 在此情况下,从属对象根据函数库用户在代码中设置的特定等式附着于基准对象。 此功能将在稍后实现。 在本文中,我将进行所有必要的准备。

我们直接在 \MQL5\Include\DoEasy\Objects\Graph\Standard\GStdGraphObj.mqh 里实现抽象标准图形对象类。 如果所创建对象是扩展标准图形对象,则在该文件中声明该类。

在文件清单的最开始,添加从属对象轴点数据类:

//+------------------------------------------------------------------+
//|                                                 GStdGraphObj.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 "..\GBaseObj.mqh"
#include "..\..\..\Services\Properties.mqh"
//+------------------------------------------------------------------+
//| Class of the dependent object pivot point data                   |
//+------------------------------------------------------------------+
class CPivotPointData
  {
private:
   bool              m_axis_x;
   int               m_property_x[][2];
public:
//--- (1) Set and (2) return the flag indicating that the pivot point belongs to the X coordinate
   void              SetAxisX(const bool axis_x)         { this.m_axis_x=axis_x; }
   bool              IsAxisX(void)                 const { return this.m_axis_x; }
//--- Return the number of base object pivot points for calculating the coordinate of the dependent one
   int               GetBasePivotsNum(void)  const { return ::ArrayRange(this.m_property_x,0);  }
//--- Add the new pivot point of the base object for calculating the coordinate of a dependent one
   bool              AddNewBasePivotPoint(const string source,const int pivot_prop,const int pivot_num)
                       {
                        //--- Get the array size 
                        int pivot_index=this.GetBasePivotsNum();
                        //--- if failed to increase the array size, inform of that and return 'false'
                        if(::ArrayResize(this.m_property_x,pivot_index+1)!=pivot_index+1)
                          {
                           CMessage::ToLog(source,MSG_LIB_SYS_FAILED_ARRAY_RESIZE);
                           return false;
                          }
                        //--- Return the result of changing the values of a newly added new array dimension
                        return this.ChangeBasePivotPoint(source,pivot_index,pivot_prop,pivot_num);
                       }
//--- Change the specified pivot point of the base object for calculating the coordinate of a dependent one
   bool              ChangeBasePivotPoint(const string source,const int pivot_index,const int pivot_prop,const int pivot_num)
                       {
                        //--- Get the array size. If it is zero, inform of that and return 'false'
                        int n=this.GetBasePivotsNum();
                        if(n==0)
                          {
                           CMessage::ToLog(source,(this.IsAxisX() ? MSG_GRAPH_OBJ_EXT_NOT_ANY_PIVOTS_X : MSG_GRAPH_OBJ_EXT_NOT_ANY_PIVOTS_Y));
                           return false;
                          }
                        //--- If the specified index goes beyond the array range, inform of that and return 'false'
                        if(pivot_index<0 || pivot_index>n-1)
                          {
                           CMessage::ToLog(source,MSG_LIB_SYS_REQUEST_OUTSIDE_ARRAY);
                           return false;
                          }
                        //--- Set the values, passed to the method, in the specified array cells by index
                        this.m_property_x[pivot_index][0]=pivot_prop;
                        this.m_property_x[pivot_index][1]=pivot_num;
                        return true;
                       }

//--- Constructor/destructor
                     CPivotPointData(void){;}
                    ~CPivotPointData(void){;}
  };
//+------------------------------------------------------------------+

该类包含一个二维数组和两个方法,其一更改其大小(添加新的轴心点)其二把数值设置为指定的第一个数组维度。 该类还拥有指示是否在数组里设定了坐标的方法 — X 或 Y。当显示来自该类的消息时,会检查该标志,并显示相应的错误消息

类清单后随复合对象的轴点 X 和 Y 坐标数据类:

//+------------------------------------------------------------------+
//| Class of data on X and Y pivot points of a composite object      |
//+------------------------------------------------------------------+
class CPivotPointXY : public CObject
  {
private:
   CPivotPointData   m_pivot_point_x;            // X coordinate pivot point
   CPivotPointData   m_pivot_point_y;            // Y coordinate pivot point
public:
//--- Return the pointer to the (1) X and (2) Y coordinate pivot point data object
   CPivotPointData  *GetPivotPointDataX(void)      { return &this.m_pivot_point_x;                    }
   CPivotPointData  *GetPivotPointDataY(void)      { return &this.m_pivot_point_y;                    }
//--- Return the number of base object pivot points for calculating the (1) X and (2) Y coordinate
   int               GetBasePivotsNumX(void) const { return this.m_pivot_point_x.GetBasePivotsNum();  }
   int               GetBasePivotsNumY(void) const { return this.m_pivot_point_y.GetBasePivotsNum();  }
//--- Add the new pivot point of the base object for calculating the X coordinate of a dependent one
   bool              AddNewBasePivotPointX(const int pivot_prop,const int pivot_num)
                       {
                        return this.m_pivot_point_x.AddNewBasePivotPoint(DFUN,pivot_prop,pivot_num);
                       }
//--- Add the new pivot point of the base object for calculating the Y coordinate of a dependent one
   bool              AddNewBasePivotPointY(const int pivot_prop,const int pivot_num)
                       {
                        return this.m_pivot_point_y.AddNewBasePivotPoint(DFUN,pivot_prop,pivot_num);
                       }
//--- Add new pivot points of the base object for calculating the X and Y coordinates of a dependent one
   bool              AddNewBasePivotPointXY(const int pivot_prop_x,const int pivot_num_x,
                                            const int pivot_prop_y,const int pivot_num_y)
                       {
                        bool res=true;
                        res &=this.m_pivot_point_x.AddNewBasePivotPoint(DFUN,pivot_prop_x,pivot_num_x);
                        res &=this.m_pivot_point_y.AddNewBasePivotPoint(DFUN,pivot_prop_y,pivot_num_y);
                        return res;
                       }
//--- Change the specified pivot point of the base object for calculating the X coordinate of a dependent one
   bool              ChangeBasePivotPointX(const int pivot_index,const int pivot_prop,const int pivot_num)
                       {
                        return this.m_pivot_point_x.ChangeBasePivotPoint(DFUN,pivot_index,pivot_prop,pivot_num);
                       }
//--- Change the specified pivot point of the base object for calculating the Y coordinate of a dependent one
   bool              ChangeBasePivotPointY(const int pivot_index,const int pivot_prop,const int pivot_num)
                       {
                        return this.m_pivot_point_y.ChangeBasePivotPoint(DFUN,pivot_index,pivot_prop,pivot_num);
                       }
//--- Change specified pivot points of the base object for calculating the X and Y coordinates
   bool              ChangeBasePivotPointXY(const int pivot_index,
                                            const int pivot_prop_x,const int pivot_num_x,
                                            const int pivot_prop_y,const int pivot_num_y)
                       {
                        bool res=true;
                        res &=this.m_pivot_point_x.ChangeBasePivotPoint(DFUN,pivot_index,pivot_prop_x,pivot_num_x);
                        res &=this.m_pivot_point_y.ChangeBasePivotPoint(DFUN,pivot_index,pivot_prop_y,pivot_num_y);
                        return res;
                       }
                       
//--- Constructor/destructor
                     CPivotPointXY(void){ this.m_pivot_point_x.SetAxisX(true); this.m_pivot_point_y.SetAxisX(false); }
                    ~CPivotPointXY(void){;}
  };  
//+------------------------------------------------------------------+

该类包含上面所研究的两个对象 — 分别对应 XY 坐标,以及处理这些对象的方法,实际上,这些方法只简单返回第一个类方法的处理结果。 XY 轴标志会在每个对象的构造函数中设置。
该类还拥有同时设置 X 和 Y 坐标属性值的方法 — 立即调用前两个类的方法,并返回调用它们的叠加结果。 如果至少有一种方法返回 false,则结果为 false

这个类后随第三个类 — 复合对象轴心点上的连接数据类:

//+------------------------------------------------------------------+
//| Class of connected data on composite object pivot points         |
//+------------------------------------------------------------------+
class CLinkedPivotPoint
  {
private:
   CArrayObj         m_list;                       // List of pivot points of the bound object X and Y coordinates
   int               m_base_obj_index;             // Base object index
public:
//--- (1) Set and (2) return the base object index
   void              SetBaseObjIndex(const int index)       { this.m_base_obj_index=index;                  }
   int               GetBaseObjIndex(void)            const { return this.m_base_obj_index;                 }
//--- Create a new object of the class of data on X and Y pivot points of a composite object and add it to the object list
   bool              CreateNewLinkedPivotPoint(const int pivot_prop_x,const int pivot_num_x,const int pivot_prop_y,const int pivot_num_y)
                       {
                        //--- Create an object of data on X and Y pivot points
                        CPivotPointXY *obj=new CPivotPointXY();
                        if(obj==NULL)
                           return false;
                        //--- Add a single dimension with data on pivot points of the base object by X and Y to each object
                        if(!obj.AddNewBasePivotPointXY(pivot_prop_x,pivot_num_x,pivot_prop_y,pivot_num_y))
                           return false;
                        //--- If failed to add the newly created object to the list, inform of that, remove the object and return 'false'
                        if(!this.m_list.Add(obj))
                          {
                           CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST);
                           delete obj;
                           return false;
                          }
                        //--- If all is successful, return 'true'
                        return true;
                       }
   
//--- Return the amount of data on pivot points of X and Y coordinates
   int               GetNumLinkedPivotPoints(void)    const {  return this.m_list.Total();                  }
//--- Return the pointer to the (1) first and (2) the last object of data on X and Y pivot points (3) by index
   CPivotPointXY    *GetLinkedPivotPointXYFirst(void)       const { return this.m_list.At(0);                     }
   CPivotPointXY    *GetLinkedPivotPointXYLast(void)        const { return this.m_list.At(this.m_list.Total()-1); }
   CPivotPointXY    *GetLinkedPivotPointXY(const int index) const { return this.m_list.At(index);                 }
//--- Return the pointer to the X coordinate pivot point data object by index
   CPivotPointData  *GetBasePivotPointDataX(const int index) const
                       {
                        CPivotPointXY *obj=this.GetLinkedPivotPointXY(index);
                        if(obj==NULL)
                           return NULL;
                        return obj.GetPivotPointDataX();
                       }
//--- Return the pointer to the Y coordinate pivot point data object by index
   CPivotPointData  *GetBasePivotPointDataY(const int index) const
                       {
                        CPivotPointXY *obj=this.GetLinkedPivotPointXY(index);
                        if(obj==NULL)
                           return NULL;
                        return obj.GetPivotPointDataY();
                       }
//--- Return the number of base object pivot points for calculating the X coordinate by index
   int               GetBasePivotsNumX(const int index) const
                       {
                        CPivotPointData *obj=this.GetBasePivotPointDataX(index);
                        if(obj==NULL)
                           return NULL;
                        return obj.GetBasePivotsNum();
                       }
//--- Return the number of base object pivot points for calculating the Y coordinate by index
   int               GetBasePivotsNumY(const int index) const
                       {
                        CPivotPointData *obj=this.GetBasePivotPointDataY(index);
                        if(obj==NULL)
                           return NULL;
                        return obj.GetBasePivotsNum();
                       }

//--- Constructor/destructor
                     CLinkedPivotPoint(void){;}
                    ~CLinkedPivotPoint(void){;}
  };  
//+------------------------------------------------------------------+

该类允许在复合对象 X 和 Y 轴点上创建数据类的对象,并返回指向欲处理类对象的指针。 其中一个对象利用 X 和 Y 坐标完全描述了基准对象的单一锚定点,并允许添加新的锚定点,并更改现有的锚定点。 此外,该对象包含一个基准对象 ID,它允许我们定义图形对象所附着的对象。

在抽象标准图形对象类的私密部分,声明从属对象的清单(附于其上),和上述连接轴点类的对象

//+------------------------------------------------------------------+
//| The class of the abstract standard graphical object              |
//+------------------------------------------------------------------+
class CGStdGraphObj : public CGBaseObj
  {
private:
   CArrayObj         m_list;                                            // List of dependent graphical objects
   CProperties      *Prop;                                              // Pointer to the property object
   CLinkedPivotPoint m_linked_pivots;                                   // Connected pivot points
   int               m_pivots;                                          // Number of object reference points
//--- Read and set (1) the time and (2) the price of the specified object pivot point
   void              SetTimePivot(const int index);
   void              SetPricePivot(const int index);
//--- Read and set (1) color, (2) style, (3) width, (4) value, (5) text of the specified object level
   void              SetLevelColor(const int index);
   void              SetLevelStyle(const int index);
   void              SetLevelWidth(const int index);
   void              SetLevelValue(const int index);
   void              SetLevelText(const int index);
//--- Read and set the BMP file name for the "Bitmap Level" object. Index: 0 - ON, 1 - OFF
   void              SetBMPFile(const int index);

public:

在类的公开部分,添加处理绑定图形对象列表连接轴点对象的方法:

//--- Set the object previous name
   bool              SetNamePrev(const string name)
                       {
                        if(!this.Prop.SetSizeRange(GRAPH_OBJ_PROP_NAME,this.Prop.CurrSize(GRAPH_OBJ_PROP_NAME)+1))
                           return false;
                        this.SetProperty(GRAPH_OBJ_PROP_NAME,this.Prop.CurrSize(GRAPH_OBJ_PROP_NAME)-1,name);
                        return true;
                       }
                       
//--- Return (1) the list of dependent objects and (2) dependent graphical object by index
   CArrayObj        *GetListDependentObj(void)        { return &this.m_list;           }
   CGStdGraphObj    *GetDependentObj(const int index) { return this.m_list.At(index);  }
//--- Return the name of the dependent object by index
   string            NameDependent(const int index);
//--- Add the dependent graphical object to the list
   bool              AddDependentObj(CGStdGraphObj *obj);

//--- Return the object of data on pivot points
   CLinkedPivotPoint*GetLinkedPivotPoint(void)        { return &this.m_linked_pivots;  }
   
//--- Add a new pivot point for calculating X and Y coordinates to the current object
   bool              AddNewLinkedPivotPointXY(const int pivot_prop_x,const int pivot_num_x,const int pivot_prop_y,const int pivot_num_y)
                       {
                        //--- If the current object is not bound to the base one, display the appropriate message and return 'false'
                        if(this.BaseObjectID()==0)
                          {
                           CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_EXT_NOT_ATACHED_TO_BASE);
                           return false;
                          }
                        //--- Return the result of adding a new connected pivot point from the CLinkedPivotPoint class to the current object
                        return this.m_linked_pivots.CreateNewLinkedPivotPoint(pivot_prop_x,pivot_num_x,pivot_prop_y,pivot_num_y);
                       }
//--- Add a new pivot point for calculating X and Y coordinates to the specified object
   bool              AddNewLinkedPivotPointXY(CGStdGraphObj *obj,const int pivot_prop_x,const int pivot_num_x,const int pivot_prop_y,const int pivot_num_y)
                       {
                        //--- If the current object is not an extended one, display the appropriate message and return 'false'
                        if(this.TypeGraphElement()!=GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)
                          {
                           CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_NOT_EXT_OBJ);
                           return false;
                          }
                        //--- If a zero pointer to the object is passed, return 'false'
                        if(obj==NULL)
                           return false;
                        //--- Return the result of adding a new connected pivot point from the CLinkedPivotPoint class to the specified object
                        return obj.AddNewLinkedPivotPointXY(pivot_prop_x,pivot_num_x,pivot_prop_y,pivot_num_y);
                       }
                       
//--- Add the new base object anchor point for calculating the X coordinate
   bool              AddNewBaseLinkedPivotX(const int index,const int pivot_prop,const int pivot_num)
                       {
                        //--- If the current object is not bound to the base one, display the appropriate message and return 'false'
                        if(this.BaseObjectID()==0)
                          {
                           CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_EXT_NOT_ATACHED_TO_BASE);
                           return false;
                          }
                        //--- Get the pointer to the necessary pivot point data
                        CPivotPointData *data=m_linked_pivots.GetBasePivotPointDataX(index); 
                        if(data==NULL)
                           return false;
                        //--- Return the result of adding a new anchor point to the current object
                        return data.AddNewBasePivotPoint(DFUN,pivot_prop,pivot_num);
                       }
//--- Add the new base object anchor point for calculating the Y coordinate
   bool              AddNewBaseLinkedPivotY(const int index,const int pivot_prop,const int pivot_num)
                       {
                        //--- If the current object is not bound to the base one, display the appropriate message and return 'false'
                        if(this.BaseObjectID()==0)
                          {
                           CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_EXT_NOT_ATACHED_TO_BASE);
                           return false;
                          }
                        //--- Get the pointer to the necessary pivot point data
                        CPivotPointData *data=m_linked_pivots.GetBasePivotPointDataY(index); 
                        if(data==NULL)
                           return false;
                        //--- Return the result of adding a new anchor point to the current object
                        return data.AddNewBasePivotPoint(DFUN,pivot_prop,pivot_num);
                       }

//--- Add the new base object anchor point for calculating the X coordinate to the specified subordinate graphical object
   bool              AddNewBaseLinkedPivotX(CGStdGraphObj *obj,const int index,const int pivot_prop,const int pivot_num)
                       {
                        //--- If the current object is not an extended one, display the appropriate message and return 'false'
                        if(this.TypeGraphElement()!=GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)
                          {
                           CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_NOT_EXT_OBJ);
                           return false;
                          }
                        //--- If a zero pointer to the object is passed, return 'false'
                        if(obj==NULL)
                           return false;
                        //--- Return the result of adding a new anchor point to the specified object
                        return obj.AddNewBaseLinkedPivotX(index,pivot_prop,pivot_num);
                       }
//--- Add the new base object anchor point for calculating the Y coordinate to the specified subordinate graphical object
   bool              AddNewBaseLinkedPivotY(CGStdGraphObj *obj,const int index,const int pivot_prop,const int pivot_num)
                       {
                        //--- If the current object is not an extended one, display the appropriate message and return 'false'
                        if(this.TypeGraphElement()!=GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)
                          {
                           CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_NOT_EXT_OBJ);
                           return false;
                          }
                        //--- If a zero pointer to the object is passed, return 'false'
                        if(obj==NULL)
                           return false;
                        //--- Return the result of adding a new anchor point to the specified object
                        return obj.AddNewBaseLinkedPivotY(index,pivot_prop,pivot_num);
                       }

//--- Return the number of base object pivot points for calculating the (1) X and (2) Y coordinate in the current object
   int               GetBasePivotsNumX(const int index)           { return this.m_linked_pivots.GetBasePivotsNumX(index);  }
   int               GetBasePivotsNumY(const int index)           { return this.m_linked_pivots.GetBasePivotsNumY(index);  }
//--- Return the number of base object pivot points for calculating the (1) X and (2) Y coordinate in the specified object
   int               GetBasePivotsNumX(CGStdGraphObj *obj,const int index) const { return(obj!=NULL ? obj.GetBasePivotsNumX(index): 0); }
   int               GetBasePivotsNumY(CGStdGraphObj *obj,const int index) const { return(obj!=NULL ? obj.GetBasePivotsNumY(index): 0); }
//--- Return the number of base object pivot points for calculating the coordinates in the (1) current (2) object
   int               GetLinkedPivotsNum(void)               const { return this.m_linked_pivots.GetNumLinkedPivotPoints(); }
   int               GetLinkedPivotsNum(CGStdGraphObj *obj) const { return(obj!=NULL ? obj.GetLinkedPivotsNum() : 0);      }
   
//--- Default constructor
                     CGStdGraphObj(){ this.m_type=OBJECT_DE_TYPE_GSTD_OBJ; this.m_species=WRONG_VALUE; }
//--- Destructor
                    ~CGStdGraphObj()
                       {
                        if(this.Prop!=NULL)
                           delete this.Prop;
                       }
protected:

所有方法都返回调用之前研究过的类同名方法结果,并提供存取这些对象的访问权限。 有些方法在代码中有注释,所以这些全部都应该是清晰的。 如果您有任何疑问,请随时在评论中提问。

受保护的参数化构造函数现在可接收已创建图形元素的类型

//--- Default constructor
                     CGStdGraphObj(){ this.m_type=OBJECT_DE_TYPE_GSTD_OBJ; this.m_species=WRONG_VALUE; }
//--- Destructor
                    ~CGStdGraphObj()
                       {
                        if(this.Prop!=NULL)
                           delete this.Prop;
                       }
protected:
//--- Protected parametric constructor
                     CGStdGraphObj(const ENUM_OBJECT_DE_TYPE obj_type,
                                   const ENUM_GRAPH_ELEMENT_TYPE elm_type,
                                   const ENUM_GRAPH_OBJ_BELONG belong,
                                   const ENUM_GRAPH_OBJ_SPECIES species,
                                   const long chart_id, const int pivots,
                                   const string name);
                     
public:

当创建对象时,我们现在可以指定来自 ENUM_GRAPH_ELEMENT_TYPE 枚举的 GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED 作为创建扩展标准图形对象时传递的元素类型。 这是在其衍生子类的构造函数中完成的。

在简化的访问和设置图形对象属性的方法模块中,添加处理基准对象 ID处理基准对象名称的方法:

public:
//+--------------------------------------------------------------------+ 
//|Methods of simplified access and setting graphical object properties|
//+--------------------------------------------------------------------+
//--- Object index in the list
   int               Number(void)                  const { return (int)this.GetProperty(GRAPH_OBJ_PROP_NUM,0);                            }
   void              SetNumber(const int number)         { this.SetProperty(GRAPH_OBJ_PROP_NUM,0,number);                                 }
//--- Flag of storing the change history
   bool              AllowChangeHistory(void)      const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_CHANGE_HISTORY,0);                }
   void              SetAllowChangeMemory(const bool flag){ this.SetProperty(GRAPH_OBJ_PROP_CHANGE_HISTORY,0,flag);                       }
//--- Object ID
   long              ObjectID(void)                const { return this.GetProperty(GRAPH_OBJ_PROP_ID,0);                                  }
   void              SetObjectID(const long obj_id)
                       {
                        CGBaseObj::SetObjectID(obj_id);
                        this.SetProperty(GRAPH_OBJ_PROP_ID,0,obj_id);
                        this.SetPropertyPrev(GRAPH_OBJ_PROP_ID,0,obj_id);
                       }
//--- Base object ID
   long              BaseObjectID(void)            const { return this.GetProperty(GRAPH_OBJ_PROP_BASE_ID,0);                                  }
   void              SetBaseObjectID(const long obj_id)
                       {
                        this.SetProperty(GRAPH_OBJ_PROP_BASE_ID,0,obj_id);
                        this.SetPropertyPrev(GRAPH_OBJ_PROP_BASE_ID,0,obj_id);
                       }
//--- Graphical object type
   ENUM_OBJECT       GraphObjectType(void)         const { return (ENUM_OBJECT)this.GetProperty(GRAPH_OBJ_PROP_TYPE,0);                   }
   void              SetGraphObjectType(const ENUM_OBJECT obj_type)
                       {
                        CGBaseObj::SetTypeGraphObject(obj_type);
                        this.SetProperty(GRAPH_OBJ_PROP_TYPE,0,obj_type);
                       }

...

//--- Object name
   string            Name(void)                    const { return this.GetProperty(GRAPH_OBJ_PROP_NAME,0);                                }
   bool              SetName(const string name)
                       {
                        if(CGBaseObj::Name()==name)
                           return true;
                        if(CGBaseObj::Name()=="")
                          {
                           CGBaseObj::SetName(name);
                           this.SetProperty(GRAPH_OBJ_PROP_NAME,0,name);
                           return true;
                          }
                        else
                          {
                           if(!::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_NAME,name))
                              return false;
                           CGBaseObj::SetName(name);
                           this.SetProperty(GRAPH_OBJ_PROP_NAME,0,name);
                           return true;
                          }
                       }
//--- Base object name
   string            BaseName(void)                const { return this.GetProperty(GRAPH_OBJ_PROP_BASE_NAME,0);                           }
   bool              SetBaseName(const string name)
                       {
                        this.SetProperty(GRAPH_OBJ_PROP_BASE_NAME,0,name);
                        return true;
                       }
//--- Object description (text contained in the object)

这些方法能够为对象属性设置基准对象 ID 和名称,并返回数据。

接下来,插入返回绑定图形对象列表中对象索引的方法声明

//--- Return the flags indicating object visibility on timeframes
   bool              IsVisibleOnTimeframeM1(void)  const { return IsVisibleOnTimeframe(PERIOD_M1, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM2(void)  const { return IsVisibleOnTimeframe(PERIOD_M2, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM3(void)  const { return IsVisibleOnTimeframe(PERIOD_M3, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM4(void)  const { return IsVisibleOnTimeframe(PERIOD_M4, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM5(void)  const { return IsVisibleOnTimeframe(PERIOD_M5, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM6(void)  const { return IsVisibleOnTimeframe(PERIOD_M6, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM10(void) const { return IsVisibleOnTimeframe(PERIOD_M10,(int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM12(void) const { return IsVisibleOnTimeframe(PERIOD_M12,(int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM15(void) const { return IsVisibleOnTimeframe(PERIOD_M15,(int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM20(void) const { return IsVisibleOnTimeframe(PERIOD_M20,(int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeM30(void) const { return IsVisibleOnTimeframe(PERIOD_M30,(int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeH1(void)  const { return IsVisibleOnTimeframe(PERIOD_H1, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeH2(void)  const { return IsVisibleOnTimeframe(PERIOD_H2, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeH3(void)  const { return IsVisibleOnTimeframe(PERIOD_H3, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeH4(void)  const { return IsVisibleOnTimeframe(PERIOD_H4, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeH6(void)  const { return IsVisibleOnTimeframe(PERIOD_H6, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeH8(void)  const { return IsVisibleOnTimeframe(PERIOD_H8, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeH12(void) const { return IsVisibleOnTimeframe(PERIOD_H12,(int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeD1(void)  const { return IsVisibleOnTimeframe(PERIOD_D1, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeW1(void)  const { return IsVisibleOnTimeframe(PERIOD_W1, (int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }
   bool              IsVisibleOnTimeframeMN1(void) const { return IsVisibleOnTimeframe(PERIOD_MN1,(int)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,0)); }

//--- Return the description of the (1) object visibility on timeframes and (2) the index in the composite graphical object list
   string            VisibleOnTimeframeDescription(void);
   string            NumberDescription(void);

//--- Re-write all graphical object properties


在类的受保护参数化构造函数中添加含有图形元素类型的变量将传入的值写入基准图形对象,并为上面创建的新图形对象属性设置默认值:

//+------------------------------------------------------------------+
//| Protected parametric constructor                                 |
//+------------------------------------------------------------------+
CGStdGraphObj::CGStdGraphObj(const ENUM_OBJECT_DE_TYPE obj_type,
                             const ENUM_GRAPH_ELEMENT_TYPE elm_type,
                             const ENUM_GRAPH_OBJ_BELONG belong,
                             const ENUM_GRAPH_OBJ_SPECIES species,
                             const long chart_id,const int pivots,
                             const string name)
  {
   //--- Create the property object with the default values
   this.Prop=new CProperties(GRAPH_OBJ_PROP_INTEGER_TOTAL,GRAPH_OBJ_PROP_DOUBLE_TOTAL,GRAPH_OBJ_PROP_STRING_TOTAL);
   
//--- Set the number of pivot points and object levels
   this.m_pivots=pivots;
   int levels=(int)::ObjectGetInteger(chart_id,name,OBJPROP_LEVELS);

//--- Set the property array dimensionalities according to the number of pivot points and levels
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_TIME,this.m_pivots);
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_PRICE,this.m_pivots);
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELCOLOR,levels);
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELSTYLE,levels);
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELWIDTH,levels);
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELVALUE,levels);
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_LEVELTEXT,levels);
   this.Prop.SetSizeRange(GRAPH_OBJ_PROP_BMPFILE,2);
   
//--- Set the object (1) type, type of graphical (2) object, (3) element, (4) subwindow affiliation and (5) index, as well as (6) chart symbol Digits
   this.m_type=obj_type;
   this.SetName(name);
   CGBaseObj::SetChartID(chart_id);
   CGBaseObj::SetTypeGraphObject(CGBaseObj::GraphObjectType(obj_type));
   CGBaseObj::SetTypeElement(elm_type);
   CGBaseObj::SetBelong(belong);
   CGBaseObj::SetSpecies(species);
   CGBaseObj::SetSubwindow(chart_id,name);
   CGBaseObj::SetDigits((int)::SymbolInfoInteger(::ChartSymbol(chart_id),SYMBOL_DIGITS));
   
//--- Save the integer properties inherent in all graphical objects but not present in the current one
   this.SetProperty(GRAPH_OBJ_PROP_CHART_ID,0,CGBaseObj::ChartID());                // Chart ID
   this.SetProperty(GRAPH_OBJ_PROP_WND_NUM,0,CGBaseObj::SubWindow());               // Chart subwindow index
   this.SetProperty(GRAPH_OBJ_PROP_TYPE,0,CGBaseObj::TypeGraphObject());            // Graphical object type (ENUM_OBJECT)
   this.SetProperty(GRAPH_OBJ_PROP_ELEMENT_TYPE,0,CGBaseObj::TypeGraphElement());   // Graphical element type (ENUM_GRAPH_ELEMENT_TYPE)
   this.SetProperty(GRAPH_OBJ_PROP_BELONG,0,CGBaseObj::Belong());                   // Graphical object affiliation
   this.SetProperty(GRAPH_OBJ_PROP_SPECIES,0,CGBaseObj::Species());                 // Graphical object species
   this.SetProperty(GRAPH_OBJ_PROP_GROUP,0,0);                                      // Graphical object group
   this.SetProperty(GRAPH_OBJ_PROP_ID,0,0);                                         // Object ID
   this.SetProperty(GRAPH_OBJ_PROP_BASE_ID,0,0);                                    // Base object ID
   this.SetProperty(GRAPH_OBJ_PROP_NUM,0,0);                                        // Object index in the list
   this.SetProperty(GRAPH_OBJ_PROP_CHANGE_HISTORY,0,false);                         // Flag of storing the change history
   this.SetProperty(GRAPH_OBJ_PROP_BASE_NAME,0,this.Name());                        // Base object name
   
//--- Save the properties inherent in all graphical objects and present in a graphical object
   this.PropertiesRefresh();
   
//--- Save basic properties in the parent object
   this.m_create_time=(datetime)this.GetProperty(GRAPH_OBJ_PROP_CREATETIME,0);
   this.m_back=(bool)this.GetProperty(GRAPH_OBJ_PROP_BACK,0);
   this.m_selected=(bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTED,0);
   this.m_selectable=(bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTABLE,0);
   this.m_hidden=(bool)this.GetProperty(GRAPH_OBJ_PROP_HIDDEN,0);

//--- Save the current properties to the previous ones
   this.PropertiesCopyToPrevData();
  }
//+-------------------------------------------------------------------+

默认情况下,基准对象 ID 为零(不存在),而基准对象名称等于当前图形对象的名称,即对象指向自身,意即与基准对象没有连接。

在返回对象整数型属性描述的方法中添加显示基准对象 ID 描述的内容。 在返回绑定对象列表中的对象索引描述的模块中,加入调用方法完成操作(稍后添加):

//+------------------------------------------------------------------+
//| Return description of object's integer property                  |
//+------------------------------------------------------------------+
string CGStdGraphObj::GetPropertyDescription(ENUM_GRAPH_OBJ_PROP_INTEGER property)
  {
   return
     (
      property==GRAPH_OBJ_PROP_ID         ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_BASE_ID    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BASE_ID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_TYPE       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_TYPE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.TypeDescription()
         )  :
      property==GRAPH_OBJ_PROP_ELEMENT_TYPE  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ELEMENT_TYPE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+CGBaseObj::TypeElementDescription()
         )  :
      property==GRAPH_OBJ_PROP_SPECIES    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_SPECIES)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+CGBaseObj::SpeciesDescription()
         )  :
      property==GRAPH_OBJ_PROP_GROUP    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_GROUP)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(CGBaseObj::Group()>0 ? (string)this.GetProperty(property,0) : CMessage::Text(MSG_LIB_PROP_EMPTY))
         )  :
      property==GRAPH_OBJ_PROP_BELONG     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BELONG)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+CGBaseObj::BelongDescription()
         )  :
      property==GRAPH_OBJ_PROP_CHART_ID   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CHART_ID)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_WND_NUM    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_WND_NUM)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_CHANGE_HISTORY ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CHANGE_MEMORY)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_CREATETIME   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CREATETIME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.GetProperty(property,0),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
         )  :
      property==GRAPH_OBJ_PROP_TIMEFRAMES ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_TIMEFRAMES)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.VisibleOnTimeframeDescription()
         )  :
      property==GRAPH_OBJ_PROP_BACK       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BACK)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.IsBack() ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_ZORDER     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ZORDER)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_HIDDEN     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_HIDDEN)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.IsHidden() ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_SELECTED   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_SELECTED)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.IsSelected() ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_SELECTABLE ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_SELECTABLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.IsSelectable() ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_NUM        ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_NUM)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.NumberDescription()
         )  :
      property==GRAPH_OBJ_PROP_TIME       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_TIME)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+"\n"+this.TimesDescription()
         )  :
      property==GRAPH_OBJ_PROP_COLOR      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_COLOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property,0),true)
         )  :
      property==GRAPH_OBJ_PROP_STYLE      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_STYLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+LineStyleDescription((ENUM_LINE_STYLE)this.GetProperty(property,0))
         )  :
      property==GRAPH_OBJ_PROP_WIDTH     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_WIDTH)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_FILL       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_FILL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_READONLY   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_READONLY)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_LEVELS     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELS)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_LEVELCOLOR ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELCOLOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ":\n"+this.LevelsColorDescription()
         )  :
      property==GRAPH_OBJ_PROP_LEVELSTYLE ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELSTYLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ":\n"+this.LevelsStyleDescription()
         )  :
      property==GRAPH_OBJ_PROP_LEVELWIDTH ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELWIDTH)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ":\n"+this.LevelsWidthDescription()
         )  :
      property==GRAPH_OBJ_PROP_ALIGN      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ALIGN)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+AlignModeDescription((ENUM_ALIGN_MODE)this.GetProperty(property,0))
         )  :
      property==GRAPH_OBJ_PROP_FONTSIZE   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_FONTSIZE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_RAY_LEFT   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_RAY_LEFT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_RAY_RIGHT  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_RAY_RIGHT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_RAY        ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_RAY)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_ELLIPSE    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ELLIPSE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_ARROWCODE  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ARROWCODE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_ANCHOR     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ANCHOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.AnchorDescription()
         )  :
      property==GRAPH_OBJ_PROP_XDISTANCE  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_XDISTANCE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_YDISTANCE  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_YDISTANCE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_DIRECTION  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_DIRECTION)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+GannDirectDescription((ENUM_GANN_DIRECTION)this.GetProperty(property,0))
         )  :
      property==GRAPH_OBJ_PROP_DEGREE     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_DEGREE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+ElliotWaveDegreeDescription((ENUM_ELLIOT_WAVE_DEGREE)this.GetProperty(property,0))
         )  :
      property==GRAPH_OBJ_PROP_DRAWLINES  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_DRAWLINES)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_STATE      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_STATE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_BUTTON_STATE_PRESSED) : CMessage::Text(MSG_LIB_TEXT_BUTTON_STATE_DEPRESSED))
         )  :
      property==GRAPH_OBJ_PROP_CHART_OBJ_CHART_ID  ?  CMessage::Text(MSG_CHART_OBJ_ID)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_CHART_OBJ_PERIOD ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CHART_OBJ_PERIOD)+
         (!this.SupportProperty(property)       ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+TimeframeDescription((ENUM_TIMEFRAMES)this.GetProperty(property,0))
         )  :
      property==GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE)+
         (!this.SupportProperty(property)             ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE)+
         (!this.SupportProperty(property)             ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO))
         )  :
      property==GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE)+
         (!this.SupportProperty(property)             ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_XSIZE      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_XSIZE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_YSIZE      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_YSIZE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_XOFFSET    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_XOFFSET)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_YOFFSET    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_YOFFSET)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property,0)
         )  :
      property==GRAPH_OBJ_PROP_BGCOLOR    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BGCOLOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property,0),true)
         )  :
      property==GRAPH_OBJ_PROP_CORNER     ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_CORNER)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+BaseCornerDescription((ENUM_BASE_CORNER)this.GetProperty(property,0))
         )  :
      property==GRAPH_OBJ_PROP_BORDER_TYPE   ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BORDER_TYPE)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+BorderTypeDescription((ENUM_BORDER_TYPE)this.GetProperty(property,0))
         )  :
      property==GRAPH_OBJ_PROP_BORDER_COLOR  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BORDER_COLOR)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property,0),true)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+


在返回对象字符串型属性描述的方法中,添加 返回基准对象名称描述的代码模块

//+------------------------------------------------------------------+
//| Return description of object's string property                   |
//+------------------------------------------------------------------+
string CGStdGraphObj::GetPropertyDescription(ENUM_GRAPH_OBJ_PROP_STRING property)
  {
   return
     (
      property==GRAPH_OBJ_PROP_NAME       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_NAME)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+"\""+this.GetProperty(property,0)+"\""
         )  :
      property==GRAPH_OBJ_PROP_BASE_NAME  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BASE_NAME)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+"\""+this.GetProperty(property,0)+"\""
         )  :
      property==GRAPH_OBJ_PROP_TEXT       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_TEXT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0)=="" ? CMessage::Text(MSG_LIB_PROP_EMPTY) : "\""+this.GetProperty(property,0)+"\"")
         )  :
      property==GRAPH_OBJ_PROP_TOOLTIP    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_TOOLTIP)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(this.GetProperty(property,0)=="" ? CMessage::Text(MSG_LIB_PROP_AUTO) : 
                this.GetProperty(property,0)=="\n" ? CMessage::Text(MSG_LIB_PROP_EMPTY) :
                "\""+this.GetProperty(property,0)+"\"")
         )  :
      property==GRAPH_OBJ_PROP_LEVELTEXT  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELTEXT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ":\n"+this.LevelsTextDescription()
         )  :
      property==GRAPH_OBJ_PROP_FONT       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_FONT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+"\""+this.GetProperty(property,0)+"\""
         )  :
      property==GRAPH_OBJ_PROP_BMPFILE    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BMPFILE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ":\n"+this.BMPFilesDescription()
         )  :
      property==GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_SYMBOL)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetProperty(property,0)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+


该方法返回复合图形对象对象列表中图形对象索引描述:

//+------------------------------------------------------------------+
//| Return the description of the graphical object index             |
//| in the list of objects of a composite graphical object           |
//+------------------------------------------------------------------+
string CGStdGraphObj::NumberDescription(void)
  {
   if(CGBaseObj::TypeGraphElement()==GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)
     {
      if(this.Number()==0)
         return CMessage::Text(MSG_GRAPH_OBJ_PROP_NUM_EXT_BASE_OBJ);
     }
   return (string)this.Number();
  }
//+------------------------------------------------------------------+

对于扩展标准图形对象检查其索引。 如果它等于零显示文本 “Base object of the extended graphical object”。 在所有其它情况下,索引显示为写入对象属性的字符串。


该方法返回依据索引提取的从属图形对象的名称

//+------------------------------------------------------------------+
//| Return the name of a subordinate graphical object by index       |
//+------------------------------------------------------------------+
string CGStdGraphObj::NameDependent(const int index)
  {
   CGStdGraphObj *obj=this.GetDependentObj(index);
   return(obj!=NULL ? obj.Name() : "");
  }
//+------------------------------------------------------------------+

依据指定的索引获取指向列表中已连接图形对象的指针,并返回其名称如果获取对象失败,则返回空字符串

将从属标准图形对象添加到列表中的方法:

//+------------------------------------------------------------------+
//| Add a subordinate standard graphical object to the list          |
//+------------------------------------------------------------------+
bool CGStdGraphObj::AddDependentObj(CGStdGraphObj *obj)
  {
   //--- If the current object is not an extended one, inform of that and return 'false'
   if(this.TypeGraphElement()!=GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED)
     {
      CMessage::ToLog(MSG_GRAPH_OBJ_NOT_EXT_OBJ);
      return false;
     }
   //--- If failed to add the pointer to the passed object into the list, inform of that and return 'false'
   if(!this.m_list.Add(obj))
     {
      CMessage::ToLog(DFUN,MSG_GRAPH_OBJ_FAILED_ADD_DEP_EXT_OBJ_TO_LIST);
      return false;
     }
   //--- Object added to the list - set its number in the list,
   //--- name and ID of the current object as the base one
   obj.SetNumber(this.m_list.Total()-1);
   obj.SetBaseName(this.Name());
   obj.SetBaseObjectID(this.ObjectID());
   return true;
  }
//+------------------------------------------------------------------+

所有非扩展图形对象都无法操控从属对象。 因此,我们需要在所有方法里检查接收到的指向要更改从属对象的指针。 如果是非扩展对象,则会显示相应的消息,且该方法返回 false。 类似地,我们应该在当前对象处理从属对象参数的方法中检查其是否为从属对象(绑定到基准对象)。 如果对象尚未绑定,则它不是从属对象。 将显示相应的消息,并返回 false

之所以这样做,是因为任何图形对象都可以是基准对象或从属对象,也可以同时是基准对象和从属对象。 因此,它拥有处理自身从属对象(基准对象模式)和从外部更改其属性(从属对象模式)的方法。


我们改进位于 \MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqh 里的图形元素集合类。

在管理图表对象类的公开部分,在创建标准图形对象类的新对象的方法中添加指示需要创建扩展图形对象的标志

public:
//--- Return the variable values
   ENUM_TIMEFRAMES   Timeframe(void)                           const { return this.m_chart_timeframe;    }
   long              ChartID(void)                             const { return this.m_chart_id;           }
   string            Symbol(void)                              const { return this.m_chart_symbol;       }
   bool              IsEvent(void)                             const { return this.m_is_graph_obj_event; }
   int               TotalObjects(void)                        const { return this.m_total_objects;      }
   int               Delta(void)                               const { return this.m_delta_graph_obj;    }
//--- Create a new standard (or extended) graphical object
   CGStdGraphObj    *CreateNewGraphObj(const ENUM_OBJECT obj_type,const string name,const bool extended);
//--- Return the list of newly added objects

在类中检查图表对象的方法里,当创建新对象时,预设 false

//+------------------------------------------------------------------+
//| CChartObjectsControl: Check objects on a chart                   |
//+------------------------------------------------------------------+
void CChartObjectsControl::Refresh(void)
  {
//--- Clear the list of newly added objects
   this.m_list_new_graph_obj.Clear();
//--- Calculate the number of new objects on the chart
   this.m_total_objects=::ObjectsTotal(this.ChartID());
   this.m_delta_graph_obj=this.m_total_objects-this.m_last_objects;
   //--- If an object is added to the chart

   if(this.m_delta_graph_obj>0)
     {
      //--- Create the list of added graphical objects
      for(int i=0;i<this.m_delta_graph_obj;i++)
        {
         //--- Get the name of the last added object (if a single new object is added),
         //--- or a name from the terminal object list by index (if several objects have been added)
         string name=(this.m_delta_graph_obj==1 ? this.LastAddedGraphObjName() : ::ObjectName(this.m_chart_id,i));
         //--- Handle only non-programmatically created objects
         if(name==NULL || ::StringFind(name,this.m_name_program)>WRONG_VALUE)
            continue;
         //--- Create the object of the graphical object class corresponding to the added graphical object type
         ENUM_OBJECT type=(ENUM_OBJECT)::ObjectGetInteger(this.ChartID(),name,OBJPROP_TYPE);
         ENUM_OBJECT_DE_TYPE obj_type=ENUM_OBJECT_DE_TYPE(type+OBJECT_DE_TYPE_GSTD_OBJ+1);
         CGStdGraphObj *obj=this.CreateNewGraphObj(type,name,false);
         //--- If failed to create an object, inform of that and move on to the new iteration
         if(obj==NULL)
           {
            CMessage::ToLog(DFUN,MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_CLASS_OBJ);
            continue;
           }
         //--- Set the object affiliation and add the created object to the list of new objects
         obj.SetBelong(GRAPH_OBJ_BELONG_NO_PROGRAM); 
         //--- If failed to add the object to the list, inform of that, remove the object and move on to the next iteration
         if(!this.m_list_new_graph_obj.Add(obj))
           {
            CMessage::ToLog(DFUN_ERR_LINE,MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST);
            delete obj;
            continue;
           }
        }
      //--- Send events to the control program chart from the created list
      for(int i=0;i<this.m_list_new_graph_obj.Total();i++)
        {
         CGStdGraphObj *obj=this.m_list_new_graph_obj.At(i);
         if(obj==NULL)
            continue;
         //--- Send an event to the control program chart
         ::EventChartCustom(this.m_chart_id_main,GRAPH_OBJ_EVENT_CREATE,this.ChartID(),obj.TimeCreate(),obj.Name());
        }
     }
//--- save the index of the last added graphical object and the difference with the last check
   this.m_last_objects=this.m_total_objects;
   this.m_is_graph_obj_event=(bool)this.m_delta_graph_obj;
  }
//+------------------------------------------------------------------+

由于该方法只跟踪图表上手动创建的图形对象,因此图形对象类的对象不应是扩展的。 因此,把 false 标志传递给创建普通标准图形对象的方法。

在创建新标准图形对象的方法中,在输入里加入扩展图形对象的标志。 以下是把标志传递给创建标准图形对象类的新对象的所有代码:

//+------------------------------------------------------------------+
//| CChartObjectsControl:                                            |
//| Create a new standard graphical object                           |
//+------------------------------------------------------------------+
CGStdGraphObj *CChartObjectsControl::CreateNewGraphObj(const ENUM_OBJECT obj_type,const string name,const bool extended)
  {

   switch((int)obj_type)
     {
      //--- Lines
      case OBJ_VLINE             : return new CGStdVLineObj(this.ChartID(),name,extended);
      case OBJ_HLINE             : return new CGStdHLineObj(this.ChartID(),name,extended);
      case OBJ_TREND             : return new CGStdTrendObj(this.ChartID(),name,extended);
      case OBJ_TRENDBYANGLE      : return new CGStdTrendByAngleObj(this.ChartID(),name,extended);
      case OBJ_CYCLES            : return new CGStdCyclesObj(this.ChartID(),name,extended);
      case OBJ_ARROWED_LINE      : return new CGStdArrowedLineObj(this.ChartID(),name,extended);
      //--- Channels
      case OBJ_CHANNEL           : return new CGStdChannelObj(this.ChartID(),name,extended);
      case OBJ_STDDEVCHANNEL     : return new CGStdStdDevChannelObj(this.ChartID(),name,extended);
      case OBJ_REGRESSION        : return new CGStdRegressionObj(this.ChartID(),name,extended);
      case OBJ_PITCHFORK         : return new CGStdPitchforkObj(this.ChartID(),name,extended);
      //--- Gann
      case OBJ_GANNLINE          : return new CGStdGannLineObj(this.ChartID(),name,extended);
      case OBJ_GANNFAN           : return new CGStdGannFanObj(this.ChartID(),name,extended);
      case OBJ_GANNGRID          : return new CGStdGannGridObj(this.ChartID(),name,extended);
      //--- Fibo
      case OBJ_FIBO              : return new CGStdFiboObj(this.ChartID(),name,extended);
      case OBJ_FIBOTIMES         : return new CGStdFiboTimesObj(this.ChartID(),name,extended);
      case OBJ_FIBOFAN           : return new CGStdFiboFanObj(this.ChartID(),name,extended);
      case OBJ_FIBOARC           : return new CGStdFiboArcObj(this.ChartID(),name,extended);
      case OBJ_FIBOCHANNEL       : return new CGStdFiboChannelObj(this.ChartID(),name,extended);
      case OBJ_EXPANSION         : return new CGStdExpansionObj(this.ChartID(),name,extended);
      //--- Elliott
      case OBJ_ELLIOTWAVE5       : return new CGStdElliotWave5Obj(this.ChartID(),name,extended);
      case OBJ_ELLIOTWAVE3       : return new CGStdElliotWave3Obj(this.ChartID(),name,extended);
      //--- Shapes
      case OBJ_RECTANGLE         : return new CGStdRectangleObj(this.ChartID(),name,extended);
      case OBJ_TRIANGLE          : return new CGStdTriangleObj(this.ChartID(),name,extended);
      case OBJ_ELLIPSE           : return new CGStdEllipseObj(this.ChartID(),name,extended);
      //--- Arrows
      case OBJ_ARROW_THUMB_UP    : return new CGStdArrowThumbUpObj(this.ChartID(),name,extended);
      case OBJ_ARROW_THUMB_DOWN  : return new CGStdArrowThumbDownObj(this.ChartID(),name,extended);
      case OBJ_ARROW_UP          : return new CGStdArrowUpObj(this.ChartID(),name,extended);
      case OBJ_ARROW_DOWN        : return new CGStdArrowDownObj(this.ChartID(),name,extended);
      case OBJ_ARROW_STOP        : return new CGStdArrowStopObj(this.ChartID(),name,extended);
      case OBJ_ARROW_CHECK       : return new CGStdArrowCheckObj(this.ChartID(),name,extended);
      case OBJ_ARROW_LEFT_PRICE  : return new CGStdArrowLeftPriceObj(this.ChartID(),name,extended);
      case OBJ_ARROW_RIGHT_PRICE : return new CGStdArrowRightPriceObj(this.ChartID(),name,extended);
      case OBJ_ARROW_BUY         : return new CGStdArrowBuyObj(this.ChartID(),name,extended);
      case OBJ_ARROW_SELL        : return new CGStdArrowSellObj(this.ChartID(),name,extended);
      case OBJ_ARROW             : return new CGStdArrowObj(this.ChartID(),name,extended);
      //--- Graphical objects
      case OBJ_TEXT              : return new CGStdTextObj(this.ChartID(),name,extended);
      case OBJ_LABEL             : return new CGStdLabelObj(this.ChartID(),name,extended);
      case OBJ_BUTTON            : return new CGStdButtonObj(this.ChartID(),name,extended);
      case OBJ_CHART             : return new CGStdChartObj(this.ChartID(),name,extended);
      case OBJ_BITMAP            : return new CGStdBitmapObj(this.ChartID(),name,extended);
      case OBJ_BITMAP_LABEL      : return new CGStdBitmapLabelObj(this.ChartID(),name,extended);
      case OBJ_EDIT              : return new CGStdEditObj(this.ChartID(),name,extended);
      case OBJ_EVENT             : return new CGStdEventObj(this.ChartID(),name,extended);
      case OBJ_RECTANGLE_LABEL   : return new CGStdRectangleLabelObj(this.ChartID(),name,extended);
      default                    : return NULL;
     }
  }
//+------------------------------------------------------------------+

现在,我们能够在创建标准图形对象类的对象时,立即指定构造对象的类型(常规或扩展)。 我们就能够在任何时刻将常规图形对象转换为扩展图形对象,反之亦然。

在图形元素集合类的私密部分,删除创建新标准图形对象,并从类清单中返回所创建对象名称的方法。 该方法被重新定位到服务函数文件,以便我们始终能够在图表上创建任何图形对象,无论它是基于图形对象的集合类,还是基于其它类,亦或程序本身:

//+------------------------------------------------------------------+
//| Collection of graphical objects                                  |
//+------------------------------------------------------------------+
#resource "\\"+PATH_TO_EVENT_CTRL_IND;          // Indicator for controlling graphical object events packed into the program resources
class CGraphElementsCollection : public CBaseObj
  {
private:
   CArrayObj         m_list_charts_control;     // List of chart management objects
   CListObj          m_list_all_canv_elm_obj;   // List of all graphical elements on canvas
   CListObj          m_list_all_graph_obj;      // List of all graphical objects
   CArrayObj         m_list_deleted_obj;        // List of removed graphical objects
   bool              m_is_graph_obj_event;      // Event flag in the list of graphical objects
   int               m_total_objects;           // Number of graphical objects
   int               m_delta_graph_obj;         // Difference in the number of graphical objects compared to the previous check
   
//--- Return the flag indicating the graphical element class object presence in the collection list of graphical elements
   bool              IsPresentGraphElmInList(const int id,const ENUM_GRAPH_ELEMENT_TYPE type_obj);
//--- Return the flag indicating the presence of the graphical object class in the graphical object collection list
   bool              IsPresentGraphObjInList(const long chart_id,const string name);
//--- Return the flag indicating the presence of a graphical object on a chart by name
   bool              IsPresentGraphObjOnChart(const long chart_id,const string name);
//--- Return the pointer to the object of managing objects of the specified chart
   CChartObjectsControl *GetChartObjectCtrlObj(const long chart_id);
//--- Create a new object of managing graphical objects of a specified chart and add it to the list
   CChartObjectsControl *CreateChartObjectCtrlObj(const long chart_id);
//--- Update the list of graphical objects by chart ID
   CChartObjectsControl *RefreshByChartID(const long chart_id);
//--- Check if the chart window is present
   bool              IsPresentChartWindow(const long chart_id);
//--- Handle removing the chart window
   void              RefreshForExtraObjects(void);
//--- Return the first free ID of the graphical (1) object and (2) element on canvas
   long              GetFreeGraphObjID(bool program_object);
   long              GetFreeCanvElmID(void);
//--- Add a graphical object to the collection
   bool              AddGraphObjToCollection(const string source,CChartObjectsControl *obj_control);
//--- Find an object present in the collection but not on a chart
   CGStdGraphObj    *FindMissingObj(const long chart_id);
   CGStdGraphObj    *FindMissingObj(const long chart_id,int &index);
//--- Find the graphical object present on a chart but not in the collection
   string            FindExtraObj(const long chart_id);
//--- Remove the graphical object class object from the graphical object collection list: (1) specified object, (2) by chart ID
   bool              DeleteGraphObjFromList(CGStdGraphObj *obj);
   void              DeleteGraphObjectsFromList(const long chart_id);
//--- Move the graphical object class object to the list of removed graphical objects: (1) specified object, (2) by index
   bool              MoveGraphObjToDeletedObjList(CGStdGraphObj *obj);
   bool              MoveGraphObjToDeletedObjList(const int index);
//--- Move all objects by chart ID to the list of removed graphical objects
   void              MoveGraphObjectsToDeletedObjList(const long chart_id);
//--- Remove the object of managing charts from the list
   bool              DeleteGraphObjCtrlObjFromList(CChartObjectsControl *obj);
//--- Create a new standard graphical object, return an object name
   bool              CreateNewStdGraphObject(const long chart_id,
                                             const string name,
                                             const ENUM_OBJECT type,
                                             const int subwindow,
                                             const datetime time1,
                                             const double price1,
                                             const datetime time2=0,
                                             const double price2=0,
                                             const datetime time3=0,
                                             const double price3=0,
                                             const datetime time4=0,
                                             const double price4=0,
                                             const datetime time5=0,
                                             const double price5=0);
public:


在类的公开部分,设置返回标准和扩展图形对象列表的两个方法

//--- Return an (1) existing and (2) removed graphical object by chart name and ID
   CGStdGraphObj    *GetStdGraphObject(const string name,const long chart_id);
   CGStdGraphObj    *GetStdDelGraphObject(const string name,const long chart_id);
//--- Return the list of (1) chart management objects and (2) removed graphical objects
   CArrayObj        *GetListChartsControl(void)                                                          { return &this.m_list_charts_control;  }
   CArrayObj        *GetListDeletedObj(void)                                                             { return &this.m_list_deleted_obj;     }
//--- Return the list of (1) standard and (2) extended graphical objects
   CArrayObj        *GetListStdGraphObject(void)                              { return CSelect::ByGraphicStdObjectProperty(this.GetListGraphObj(),GRAPH_OBJ_PROP_ELEMENT_TYPE,0,GRAPH_ELEMENT_TYPE_STANDARD,EQUAL);           }
   CArrayObj        *GetListStdGraphObjectExt(void)                           { return CSelect::ByGraphicStdObjectProperty(this.GetListGraphObj(),GRAPH_OBJ_PROP_ELEMENT_TYPE,0,GRAPH_ELEMENT_TYPE_STANDARD_EXTENDED,EQUAL);  }
//--- Return (1) the last removed graphical object and (2) the array size of graphical object properties

这些方法简单地依据图形元素类型属性,返回指向所有图形对象已排序列表之中的指针。

私秘方法创建一个新的图形对象,并返回指向图表管理对象的指针,现在调用的创建图形对象的方法不是来自类上下文,而是来自 DELib.mqh(只需从方法调用代码中删除 "this")

private:
//--- Create a new graphical object, return the pointer to the chart management object
   CChartObjectsControl *CreateNewStdGraphObjectAndGetCtrlObj(const long chart_id,
                                                              const string name,
                                                              int subwindow,
                                                              const ENUM_OBJECT type_object,
                                                              const datetime time1,
                                                              const double price1,
                                                              const datetime time2=0,
                                                              const double price2=0,
                                                              const datetime time3=0,
                                                              const double price3=0,
                                                              const datetime time4=0,
                                                              const double price4=0,
                                                              const datetime time5=0,
                                                              const double price5=0)
                       {
                        //--- If an object with a chart ID and name is already present in the collection, inform of that and return NULL
                        if(this.IsPresentGraphObjInList(chart_id,name))
                          {
                           ::Print(DFUN,CMessage::Text(MSG_GRAPH_ELM_COLLECTION_ERR_GR_OBJ_ALREADY_EXISTS)," ChartID ",(string)chart_id,", ",name);
                           return NULL;
                          }
                        //--- If failed to create a new standard graphical object, inform of that and return NULL
                        if(!CreateNewStdGraphObject(chart_id,name,type_object,subwindow,time1,price1,time2,price2,time3,price3,time4,price4,time5,price5))
                          {
                           ::Print(DFUN,CMessage::Text(MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_STD_GRAPH_OBJ),StdGraphObjectTypeDescription(type_object));
                           CMessage::ToLog(::GetLastError(),true);
                           return NULL;
                          }
                        //--- If failed to get a chart management object, inform of that
                        CChartObjectsControl *ctrl=this.GetChartObjectCtrlObj(chart_id);
                        if(ctrl==NULL)
                           ::Print(DFUN,CMessage::Text(MSG_GRAPH_ELM_COLLECTION_ERR_FAILED_GET_CTRL_OBJ),(string)chart_id);
                        //--- Return the pointer to a chart management object or NULL in case of a failed attempt to get it
                        return ctrl;
                       }


在创建图形对象的所有公开方法中添加类似的修改 — 方法输入中的扩展对象标志,并将标志传递给创建标准图形对象类的新对象的方法

public:
//--- Create the "Vertical line" graphical object
   bool              CreateLineVertical(const long chart_id,const string name,const int subwindow,const bool extended,const datetime time)
                       {
                        //--- Set the name and type of a created object
                        string nm=this.m_name_program+"_"+name;
                        ENUM_OBJECT type_object=OBJ_VLINE;
                        //--- Create a new graphical object and get the pointer to the chart management object
                        CChartObjectsControl *ctrl=this.CreateNewStdGraphObjectAndGetCtrlObj(chart_id,nm,subwindow,type_object,time,0);
                        if(ctrl==NULL)
                           return false;
                        //--- Create a new class object corresponding to the newly created graphical object
                        CGStdVLineObj *obj=ctrl.CreateNewGraphObj(type_object,nm,extended);
                        if(obj==NULL)
                          {
                           ::Print(DFUN,CMessage::Text(MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_CLASS_OBJ),StdGraphObjectTypeDescription(type_object));
                           return false;
                          }
                        //--- Set the necessary minimal parameters for an object
                        obj.SetBelong(GRAPH_OBJ_BELONG_PROGRAM);
                        obj.SetFlagSelectable(true,false);
                        obj.SetFlagSelected(true,false);
                        obj.SetObjectID(this.GetFreeGraphObjID(true));
                        obj.PropertiesCopyToPrevData();
                        //--- Return the result of adding the object to the list
                        return this.AddCreatedObjToList(DFUN,chart_id,nm,obj);
                       }

//--- Create the "Horizontal line" graphical object
   bool              CreateLineHorizontal(const long chart_id,const string name,const int subwindow,const bool extended,const double price)
                       {
                        string nm=this.m_name_program+"_"+name;
                        ENUM_OBJECT type_object=OBJ_HLINE;
                        CChartObjectsControl *ctrl=this.CreateNewStdGraphObjectAndGetCtrlObj(chart_id,nm,subwindow,type_object,0,price);
                        if(ctrl==NULL)
                           return false;
                        CGStdHLineObj *obj=ctrl.CreateNewGraphObj(type_object,nm,extended);

                        if(obj==NULL)
                          {
                           ::Print(DFUN,CMessage::Text(MSG_GRAPH_STD_OBJ_ERR_FAILED_CREATE_CLASS_OBJ),StdGraphObjectTypeDescription(type_object));
                           return false;
                          }
                        //--- Set the necessary minimal parameters for an object
                        obj.SetBelong(GRAPH_OBJ_BELONG_PROGRAM);
                        obj.SetFlagSelectable(true,false);
                        obj.SetFlagSelected(true,false);
                        obj.SetObjectID(this.GetFreeGraphObjID(true));
                        obj.PropertiesCopyToPrevData();
                        //--- Return the result of adding the object to the list
                        return this.AddCreatedObjToList(DFUN,chart_id,nm,obj);
                       }
 
//--- Create the "Trend line" graphical object

在此,我们可以看到两种方法的一个例子,它们的修改雷同。 其余的方法也以同样的方式进行了修改。 您可在文后所附的文件中找到它们。

把实现创建新标准图形对象的方法清单移到 \MQL5\Include\DoEasy\Services\DELib.mqh 函数库服务函数文件:

//+------------------------------------------------------------------+
//| Create a new standard graphical object                           |
//+------------------------------------------------------------------+
bool CreateNewStdGraphObject(const long chart_id,
                             const string name,
                             const ENUM_OBJECT type,
                             const int subwindow,
                             const datetime time1,
                             const double price1,
                             const datetime time2=0,
                             const double price2=0,
                             const datetime time3=0,
                             const double price3=0,
                             const datetime time4=0,
                             const double price4=0,
                             const datetime time5=0,
                             const double price5=0)
  {
   ::ResetLastError();
   switch(type)
     {
      //--- Lines
      case OBJ_VLINE             : return ::ObjectCreate(chart_id,name,OBJ_VLINE,subwindow,time1,0);
      case OBJ_HLINE             : return ::ObjectCreate(chart_id,name,OBJ_HLINE,subwindow,0,price1);
      case OBJ_TREND             : return ::ObjectCreate(chart_id,name,OBJ_TREND,subwindow,time1,price1,time2,price2);
      case OBJ_TRENDBYANGLE      : return ::ObjectCreate(chart_id,name,OBJ_TRENDBYANGLE,subwindow,time1,price1,time2,price2);
      case OBJ_CYCLES            : return ::ObjectCreate(chart_id,name,OBJ_CYCLES,subwindow,time1,price1,time2,price2);
      case OBJ_ARROWED_LINE      : return ::ObjectCreate(chart_id,name,OBJ_ARROWED_LINE,subwindow,time1,price1,time2,price2);
      //--- Channels
      case OBJ_CHANNEL           : return ::ObjectCreate(chart_id,name,OBJ_CHANNEL,subwindow,time1,price1,time2,price2,time3,price3);
      case OBJ_STDDEVCHANNEL     : return ::ObjectCreate(chart_id,name,OBJ_STDDEVCHANNEL,subwindow,time1,price1,time2,price2);
      case OBJ_REGRESSION        : return ::ObjectCreate(chart_id,name,OBJ_REGRESSION,subwindow,time1,price1,time2,price2);
      case OBJ_PITCHFORK         : return ::ObjectCreate(chart_id,name,OBJ_PITCHFORK,subwindow,time1,price1,time2,price2,time3,price3);
      //--- Gann
      case OBJ_GANNLINE          : return ::ObjectCreate(chart_id,name,OBJ_GANNLINE,subwindow,time1,price1,time2,price2);
      case OBJ_GANNFAN           : return ::ObjectCreate(chart_id,name,OBJ_GANNFAN,subwindow,time1,price1,time2,price2);
      case OBJ_GANNGRID          : return ::ObjectCreate(chart_id,name,OBJ_GANNGRID,subwindow,time1,price1,time2,price2);
      //--- Fibo
      case OBJ_FIBO              : return ::ObjectCreate(chart_id,name,OBJ_FIBO,subwindow,time1,price1,time2,price2);
      case OBJ_FIBOTIMES         : return ::ObjectCreate(chart_id,name,OBJ_FIBOTIMES,subwindow,time1,price1,time2,price2);
      case OBJ_FIBOFAN           : return ::ObjectCreate(chart_id,name,OBJ_FIBOFAN,subwindow,time1,price1,time2,price2);
      case OBJ_FIBOARC           : return ::ObjectCreate(chart_id,name,OBJ_FIBOARC,subwindow,time1,price1,time2,price2);
      case OBJ_FIBOCHANNEL       : return ::ObjectCreate(chart_id,name,OBJ_FIBOCHANNEL,subwindow,time1,price1,time2,price2,time3,price3);
      case OBJ_EXPANSION         : return ::ObjectCreate(chart_id,name,OBJ_EXPANSION,subwindow,time1,price1,time2,price2,time3,price3);
      //--- Elliott
      case OBJ_ELLIOTWAVE5       : return ::ObjectCreate(chart_id,name,OBJ_ELLIOTWAVE5,subwindow,time1,price1,time2,price2,time3,price3,time4,price4,time5,price5);
      case OBJ_ELLIOTWAVE3       : return ::ObjectCreate(chart_id,name,OBJ_ELLIOTWAVE3,subwindow,time1,price1,time2,price2,time3,price3);
      //--- Shapes
      case OBJ_RECTANGLE         : return ::ObjectCreate(chart_id,name,OBJ_RECTANGLE,subwindow,time1,price1,time2,price2);
      case OBJ_TRIANGLE          : return ::ObjectCreate(chart_id,name,OBJ_TRIANGLE,subwindow,time1,price1,time2,price2,time3,price3);
      case OBJ_ELLIPSE           : return ::ObjectCreate(chart_id,name,OBJ_ELLIPSE,subwindow,time1,price1,time2,price2,time3,price3);
      //--- Arrows
      case OBJ_ARROW_THUMB_UP    : return ::ObjectCreate(chart_id,name,OBJ_ARROW_THUMB_UP,subwindow,time1,price1);
      case OBJ_ARROW_THUMB_DOWN  : return ::ObjectCreate(chart_id,name,OBJ_ARROW_THUMB_DOWN,subwindow,time1,price1);
      case OBJ_ARROW_UP          : return ::ObjectCreate(chart_id,name,OBJ_ARROW_UP,subwindow,time1,price1);
      case OBJ_ARROW_DOWN        : return ::ObjectCreate(chart_id,name,OBJ_ARROW_DOWN,subwindow,time1,price1);
      case OBJ_ARROW_STOP        : return ::ObjectCreate(chart_id,name,OBJ_ARROW_STOP,subwindow,time1,price1);
      case OBJ_ARROW_CHECK       : return ::ObjectCreate(chart_id,name,OBJ_ARROW_CHECK,subwindow,time1,price1);
      case OBJ_ARROW_LEFT_PRICE  : return ::ObjectCreate(chart_id,name,OBJ_ARROW_LEFT_PRICE,subwindow,time1,price1);
      case OBJ_ARROW_RIGHT_PRICE : return ::ObjectCreate(chart_id,name,OBJ_ARROW_RIGHT_PRICE,subwindow,time1,price1);
      case OBJ_ARROW_BUY         : return ::ObjectCreate(chart_id,name,OBJ_ARROW_BUY,subwindow,time1,price1);
      case OBJ_ARROW_SELL        : return ::ObjectCreate(chart_id,name,OBJ_ARROW_SELL,subwindow,time1,price1);
      case OBJ_ARROW             : return ::ObjectCreate(chart_id,name,OBJ_ARROW,subwindow,time1,price1);
      //--- Graphical objects
      case OBJ_TEXT              : return ::ObjectCreate(chart_id,name,OBJ_TEXT,subwindow,time1,price1);
      case OBJ_LABEL             : return ::ObjectCreate(chart_id,name,OBJ_LABEL,subwindow,0,0);
      case OBJ_BUTTON            : return ::ObjectCreate(chart_id,name,OBJ_BUTTON,subwindow,0,0);
      case OBJ_CHART             : return ::ObjectCreate(chart_id,name,OBJ_CHART,subwindow,0,0);
      case OBJ_BITMAP            : return ::ObjectCreate(chart_id,name,OBJ_BITMAP,subwindow,time1,price1);
      case OBJ_BITMAP_LABEL      : return ::ObjectCreate(chart_id,name,OBJ_BITMAP_LABEL,subwindow,0,0);
      case OBJ_EDIT              : return ::ObjectCreate(chart_id,name,OBJ_EDIT,subwindow,0,0);
      case OBJ_EVENT             : return ::ObjectCreate(chart_id,name,OBJ_EVENT,subwindow,time1,0);
      case OBJ_RECTANGLE_LABEL   : return ::ObjectCreate(chart_id,name,OBJ_RECTANGLE_LABEL,subwindow,0,0);
      //---
      default: return false;
     }
  }
//+------------------------------------------------------------------+


现在,我们来改进 \MQL5\Include\DoEasy\Engine.mqh 里的 CEngine 函数库主类。mqh 。

返回程序名称的方法从原来非常没有特性的 Name() 重命名为更准确的 ProgramName()

//--- Return event (1) milliseconds, (2) reason and (3) source from its 'long' value
   ushort               EventMSC(const long lparam)               const { return this.LongToUshortFromByte(lparam,0);         }
   ushort               EventReason(const long lparam)            const { return this.LongToUshortFromByte(lparam,1);         }
   ushort               EventSource(const long lparam)            const { return this.LongToUshortFromByte(lparam,2);         }

//--- Return the program name
   string               ProgramName(void)                         const { return this.m_name;                                 }

//--- Set the new (1) pause countdown start time and (2) pause in milliseconds

由于对象名称的差别取决于图形对象的创建方式(手动或编程),因此我们把依据图表名称和 ID 返回标准图形对象的对象类的方法进行了一些修改,从而能够在程序中按名称搜索和选择对象:

//--- Return the class of the object of the standard graphical object by chart name and ID
   CGStdGraphObj       *GraphGetStdGraphObject(const string name,const long chart_id)
                          {
                           CGStdGraphObj *obj=this.m_graph_objects.GetStdGraphObject(name,chart_id);
                           if(obj==NULL)
                              obj=this.m_graph_objects.GetStdGraphObject(this.ProgramName()+"_"+name,chart_id);
                           return obj;
                          }

如果对象是手动创建的,则函数库不会更改其名称。 如果是我们以编程方式创建的图形对象,其创建方法会在对象名称中添加带有程序名的前缀。 例如,如果我们从一个自定义程序创建名为 “object_name” 的对象,然后尝试搜索它,我们将无法找到它,因为该名称现在拥有与程序名相同的前缀,因此该对象名看起来像 “program_name_object_name”。 考虑到这一点,我们首先搜索传递给方法的名称。 接下来,如果没有找到含有这个名称的对象,我们将尝试找到在其名称中添加了程序名前缀的对象

另外,添加依据图表名和 ID 返回扩展标准图形对象对象类的方法

//--- Return the class of the object of the extended standard graphical object by chart name and ID
   CGStdGraphObj       *GraphGetStdGraphObjectExt(const string name,const long chart_id)
                          {
                           CArrayObj *list=this.m_graph_objects.GetListStdGraphObjectExt();
                           string nm=(::StringFind(name,this.ProgramName()+"_")==WRONG_VALUE ? this.ProgramName()+"_"+name : name);
                           list=CSelect::ByGraphicStdObjectProperty(list,GRAPH_OBJ_PROP_NAME,0,nm,EQUAL);
                           return(list!=NULL ? list.At(0) : NULL);
                          }

在此,我们首先接收所有扩展图形对象的列表。 接下来,检查传递给方法的名称中是否含有程序名的字符串如果未发现该字符串,则将程序名添加到对象名当中如果对象名已经含有程序名,则传递给方法的名称将按原样使用。 接下来,从先前得到的扩展图形对象列表中,提取含有所要名称的对象如果找到该对象,则返回列表中的唯一对象如果搜索失败,则返回 NULL

扩展对象标志现在被传递给所有创建图形对象的方法。 该标志还传递给图形元素集合类的相应被调用方法:

//--- Create the "Vertical line" graphical object
   bool              CreateLineVertical(const long chart_id,const string name,const int subwindow,const bool extended,const datetime time)
                       { return this.m_graph_objects.CreateLineVertical(chart_id,name,subwindow,extended,time); }
   bool              CreateLineVertical(const string name,const int subwindow,const bool extended,const datetime time)
                       { return this.m_graph_objects.CreateLineVertical(::ChartID(),name,subwindow,extended,time); }

//--- Create the "Horizontal line" graphical object
   bool              CreateLineHorizontal(const long chart_id,const string name,const int subwindow,const bool extended,const double price)
                       { return this.m_graph_objects.CreateLineHorizontal(chart_id,name,subwindow,extended,price); }
   bool              CreateLineHorizontal(const string name,const int subwindow,const bool extended,const double price)
                       { return this.m_graph_objects.CreateLineHorizontal(::ChartID(),name,subwindow,extended,price); }

这些改进与上述所有图形对象创建方法的四个改进雷同。 因此,不需要再啰嗦其它方法。 您可在文后所附的文件中找到它们。

函数库的改进至此完毕。 几乎所有准备好的东西,就可以创建扩展的标准图形对象。


测试

为了执行测试,我将借助来自上一篇文章中的 EA,并将其保存在 \MQL5\Experts\TestDoEasy\Part93\ 中,命名为 TestDoEasyPart93.mq5

我将创建“趋势线”标准图形对象,并将“左价格标签”和“右价格标签”沿其边缘(在其两个轴心点)放置在点 0 的左侧,和点 1 的右侧。 按住 Ctrl 键的同时单击图表,可以创建趋势线。 线的左锚定点位于点击图表处,而右锚定点位于第一根图表柱线的开盘价上。
显示趋势线特性的完整描述,以及在日志中显示价格标签对象(即,在其连接的轴点类的对象中)中设置的值。 测试其余部分没有意义,因为我们还需要一些对象属性和功能方面的改进,从而全面创建扩展的标准图形对象。 这将在后续的文章中完成。

将以下代码添加到模块中,以便 EA 的 OnChartEvent() 响应程序能处理在图表上点击:

   if(id==CHARTEVENT_CLICK)
     {
      if(!IsCtrlKeyPressed())
         return;
      //--- Get the chart click coordinates
      datetime time=0;
      double price=0;
      int sw=0;
      if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,sw,time,price))
        {
         //--- Get the right point coordinates for a trend line
         datetime time2=iTime(Symbol(),PERIOD_CURRENT,1);
         double price2=iOpen(Symbol(),PERIOD_CURRENT,1);
         
         //--- Create the "Trend line" object
         string name_base="TrendLineExt";
         engine.CreateLineTrend(name_base,0,true,time,price,time2,price2);
         //--- Get the object from the list of graphical objects by chart name and ID and pass its properties to the journal
         CGStdGraphObj *obj=engine.GraphGetStdGraphObjectExt(name_base,ChartID());
         obj.Print();
         
         //--- Create the "Left price label" object
         string name_dep="PriceLeft";
         engine.CreatePriceLabelLeft(name_dep,0,false,time,price);
         //--- Get the object from the list of graphical objects by chart name and ID and
         CGStdGraphObj *dep=engine.GraphGetStdGraphObject(name_dep,ChartID());
         //--- add it to the list of graphical objects bound to the "Trend line" object
         obj.AddDependentObj(dep);
         //--- Set its pivot point by X and Y axis to the trend line left point
         obj.AddNewLinkedPivotPointXY(dep,GRAPH_OBJ_PROP_TIME,0,GRAPH_OBJ_PROP_PRICE,0);
         //--- Send the number of pivot anchor points by both axes (one point per axis) to the journal
         Print(DFUN,"PriceLeft: Num linked coord X: ",dep.GetBasePivotsNumX(0),", Num linked coord Y: ",dep.GetBasePivotsNumY(0));
         
         //--- Create the "Right price label" object
         name_dep="PriceRight";
         engine.CreatePriceLabelRight(name_dep,0,false,time2,price2);
         //--- Get the object from the list of graphical objects by chart name and ID and
         dep=engine.GraphGetStdGraphObject(name_dep,ChartID());
         //--- add it to the list of graphical objects bound to the "Trend line" object
         obj.AddDependentObj(dep);
         //--- Set its pivot point by X and Y axis to the trend line right point
         obj.AddNewLinkedPivotPointXY(dep,GRAPH_OBJ_PROP_TIME,1,GRAPH_OBJ_PROP_PRICE,1);
         //--- Send the number of pivot anchor points by both axes (one point per axis) to the journal
         Print(DFUN,"PriceRight: Num linked coord X: ",dep.GetBasePivotsNumX(0),", Num linked coord Y: ",dep.GetBasePivotsNumY(0));
        }
     }

完整逻辑已在清单中进行了注释。 所以,一切都应该很清晰。

编译 EA,在图表上启动它,然后单击图表右边缘之外的某个地方。

结果出现一条趋势线,沿其边缘有价格标签对象:


日志里显示趋势线的属性和趋势线轴点的数量,可用于计算两个价格标签的 X 和 Y 坐标。 由于已为每个标签指定了一个轴点,因此该轴点将显示在日志中。

2022.01.20 16:37:29.340 ============= The beginning of the parameter list (Trend Line) =============
2022.01.20 16:37:29.340 Object ID: 1
2022.01.20 16:37:29.340 Base object ID: 0
2022.01.20 16:37:29.340 Object type: Trend Line
2022.01.20 16:37:29.340 Graphic element type: Extended standard graphic object
2022.01.20 16:37:29.340 Object belongs to: The graphic object belongs to the program
2022.01.20 16:37:29.340 Object chart ID: 131733844391938630
2022.01.20 16:37:29.340 Chart subwindow number: 0
2022.01.20 16:37:29.340 Object number in the list: The base object of the extended graphical object
2022.01.20 16:37:29.340 Change history: No
2022.01.20 16:37:29.340 Object group: Not set
2022.01.20 16:37:29.340 Time of creation: 2022.01.20 16:37:29
2022.01.20 16:37:29.340 Visibility of an object at timeframes: Drawn on all timeframes
2022.01.20 16:37:29.340 Object in the background: No
2022.01.20 16:37:29.340 Priority of a graphical object for receiving events of clicking on a chart: 0
2022.01.20 16:37:29.340 Prohibit showing of the name of a graphical object in the terminal objects list: Yes
2022.01.20 16:37:29.340 Object is selected: Yes
2022.01.20 16:37:29.340 Object availability: Yes
2022.01.20 16:37:29.340 Time coordinate: 
2022.01.20 16:37:29.340  - Pivot point 0: 2022.01.13 09:00
2022.01.20 16:37:29.340  - Pivot point 1: 2022.01.20 10:00
2022.01.20 16:37:29.340 Color: clrRed
2022.01.20 16:37:29.340 Style: Solid line
2022.01.20 16:37:29.340 Line thickness: 1
2022.01.20 16:37:29.340 Ray goes to the left: No
2022.01.20 16:37:29.340 Ray goes to the right: No
2022.01.20 16:37:29.340 ------
2022.01.20 16:37:29.340 Price coordinate: 
2022.01.20 16:37:29.340  - Pivot point 0: 1.14728
2022.01.20 16:37:29.340  - Pivot point 1: 1.13598
2022.01.20 16:37:29.340 ------
2022.01.20 16:37:29.340 Name: "TestDoEasyPart93_TrendLineExt"
2022.01.20 16:37:29.340 Base object name: "TestDoEasyPart93_TrendLineExt"
2022.01.20 16:37:29.340 Description: Not set
2022.01.20 16:37:29.340 The text of a tooltip: Formed by the terminal
2022.01.20 16:37:29.340 ============= End of the parameter list (Trend Line) =============
2022.01.20 16:37:29.340 
2022.01.20 16:37:29.352 OnChartEvent: PriceLeft: Num linked coord X: 1, Num linked coord Y: 1
2022.01.20 16:37:29.364 OnChartEvent: PriceRight: Num linked coord X: 1, Num linked coord Y: 1

目前,我们只是简单地构造单独的图形对象,并设置属性,指示这些对象属于同一扩展标准图形对象。 如果我们移动趋势线,价格标签还不能自动跟随它。 然而,这并不是我当前的主题。 我的目标是为创建完整的扩展图形对象准备必要的功能。

下一步是什么?

在下一篇文章中,我将继续在扩展标准图形对象上的工作,并开始为它们“设置动画”。

以下是 MQL5 的当前函数库版本、测试 EA,和图表事件控制指标的所有文件,供您测试和下载。 在评论中留下您的问题、意见和建议。

返回内容目录

*该系列的前几篇文章:

DoEasy 函数库中的图形(第八十九部分):标准图形对象编程。 基本功能
DoEasy 函数库中的图形(第九十部分):标准图形对象事件。 基本功能
DoEasy 函数库中的图形(第九十一部分):标准图形对象事件。 对象名称变更历史记录
DoEasy 函数库中的图形(第九十二部分):标准图形对象记忆类。 对象属性变更历史记录

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/10331

附加的文件 |
MQL5.zip (4196.8 KB)
MetaTrader 5 的 WebSocket — 使用 Windows API MetaTrader 5 的 WebSocket — 使用 Windows API
在本文中,我们将使用 WinHttp.dll 针对 MetaTrader 5 平台创建 WebSocket 客户端程序。 客户端最终将作为一个类实现,并借助 Binary.com 的 WebSocket API 进行测试。
学习为什么、以及如何设计算法交易系统 学习为什么、以及如何设计算法交易系统
本文在介绍了 MQL5 的一些基础知识之后,通过设计一个简单的算法交易系统,向初学者展示了如何运用 MQL 的基础知识设计他们的算法交易系统(智能交易系统)
DoEasy 函数库中的图形(第九十四部分):移动和删除复合图形对象 DoEasy 函数库中的图形(第九十四部分):移动和删除复合图形对象
在本文中,我将启动开发各种复合图形对象事件。 我们还将部分研究移动和删除复合图形对象。 实际上,在此,我还会把前一篇文章中实现的东西进行微调。
交易中的数学:夏普(Sharpe)和索蒂诺(Sortino)比率 交易中的数学:夏普(Sharpe)和索蒂诺(Sortino)比率
投资回报率是投资者和萌新交易员用来分析交易绩效的最明显指标。 专业交易者会采用更可靠的工具来分析策略,比如夏普(Sharpe)比率和索蒂诺(Sortino)比率等。