English 中文 Español Deutsch 日本語 Português
Графика в библиотеке DoEasy (Часть 83): Класс абстрактного стандартного графического объекта

Графика в библиотеке DoEasy (Часть 83): Класс абстрактного стандартного графического объекта

MetaTrader 5Примеры | 24 сентября 2021, 10:39
2 010 5
Artyom Trishkin
Artyom Trishkin

Содержание


Концепция

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

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

Сделать это можно будет, например, из контекстного меню, вызываемого по некоему условию. Т.е. здесь нам уже потребуется создание какой-то графической панели, в которой можно будет организовать выбор возможных действий с графическим объектом. А такие панельки мы можем создавать при помощи классов, созданных на основе CCanvas, и их объектов, которые мы начали делать несколько статей назад, и к которым мы далее вернёмся (мы приостановили их разработку как раз из-за потребности создания коллекции графических объектов, для которой теперь требуется создание классов для стандартных графических объектов — это результат моей ошибки в планировании последовательности разработки — нужно было начинать со стандартных графических объектов).

Итак. Структура стандартных графических объектов будет точно такой же, как и у всех объектов библиотеки, — будет иметься один общий класс абстрактного графического объекта, имеющего в своём составе базовые свойства, присущие всем графическим объектам, и от него будут наследоваться классы, описывающие каждый отдельный стандартный графический объект, где будут уточняться свойства, которые есть только у этого объекта.

Сегодня создадим класс абстрактного графического объекта и добавим в него методы для работы со свойствами, присущими абсолютно всем графическим объектам, — это все свойства графических объектов, которые можно получить при помощи функций ObjectGetInteger(), ObjectGetDouble() и ObjectGetString(). При создании классов объектов-наследников от этого абстрактного графического объекта, методы, которые будут присущи только объекту-наследнику, описывающему конкретный графический объект, но прописанные в базовый объект, мы перенесём из базового объекта в объект-наследник — чтобы у других объектов, не имеющих таких свойств, эти методы не были доступны.
Для понимания и как пример:

  • в терминале есть графический объект-значок "Стрелка". У этого объекта есть свойство "Код стрелки", но нет свойства "Луч вправо";
  • в терминале есть графический объект "Трендовая линия". У этого объекта есть свойство "Луч вправо", но нет свойства "Код стрелки".

Сейчас эти свойства и методы работы с ними мы пропишем в классе абстрактного графического объекта. И эти методы будут доступны из любого объекта, который будет унаследован от этого базового — абстрактного графического объекта.
Далее, когда мы будем создавать объекты-наследники, а для этого примера — объект значка "Стрелка" и объект графического объекта "Трендовая линия", мы в каждый из них перенесём методы для работы с только присущим им свойствами:

  • в объект значка "Стрелка" перенесём методы для указания кода стрелки;
  • в объект графического объекта "Трендовая линия" перенесём методы для указания свойства "Луч вправо" ("Луч влево").

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

Свойств у графических объектов много, и сегодня, прежде чем создать класс абстрактного графического объекта, нам необходимо будет сделать объёмную подготовительную работу — прописать эти свойства в перечислениях библиотеки, создать тексты описаний каждого свойства графического объекта и создать функции, возвращающие описания некоторых свойств графических объектов.


Доработка классов библиотеки

В списке типов объектов библиотеки, созданном нами в прошлой статье, есть типы стандартных графических объектов. Но нам нужен ещё один тип для абстрактного графического объекта. В файле \MQL5\Include\DoEasy\Defines.mqh в перечислении типов объектов библиотеки впишем для него константу, и расчёт значений последующих констант типов объектов будем начинать от значения этой новой константы:

//+------------------------------------------------------------------+
//| Список типов объектов библиотеки                                 |
//+------------------------------------------------------------------+
enum ENUM_OBJECT_DE_TYPE
  {
//--- Графика
   OBJECT_DE_TYPE_GBASE =  COLLECTION_ID_LIST_END+1,              // Тип объекта "Базовый объект всех графических объектов библиотеки"
   OBJECT_DE_TYPE_GELEMENT,                                       // Тип объекта "Графический элемент"
   OBJECT_DE_TYPE_GFORM,                                          // Тип объекта "Форма"
   OBJECT_DE_TYPE_GSHADOW,                                        // Тип объекта "Тень"
//--- Анимация
   OBJECT_DE_TYPE_GFRAME,                                         // Тип объекта "Один кадр анимации"
   OBJECT_DE_TYPE_GFRAME_TEXT,                                    // Тип объекта "Один кадр текстовой анимации"
   OBJECT_DE_TYPE_GFRAME_QUAD,                                    // Тип объекта "Один кадр прямоугольной анимации"
   OBJECT_DE_TYPE_GFRAME_GEOMETRY,                                // Тип объекта "Один кадр геометрической анимации"
   OBJECT_DE_TYPE_GANIMATIONS,                                    // Тип объекта "Анимации"
//--- Управление графическими объектами
   OBJECT_DE_TYPE_GELEMENT_CONTROL,                               // Тип объекта "Управление графическими элементами"
//--- Стандартные графические объекты
   OBJECT_DE_TYPE_GSTD_OBJ,                                       // Тип объекта "Стандартный графический объект"
   OBJECT_DE_TYPE_GSTD_VLINE              =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_VLINE,            // Тип объекта "Вертикальная линия
   OBJECT_DE_TYPE_GSTD_HLINE              =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_HLINE,            // Тип объекта "Горизонтальная линия
   OBJECT_DE_TYPE_GSTD_TREND              =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_TREND,            // Тип объекта "Трендовая линия
   OBJECT_DE_TYPE_GSTD_TRENDBYANGLE       =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_TRENDBYANGLE,     // Тип объекта "Трендовая линия по углу
   OBJECT_DE_TYPE_GSTD_CYCLES             =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_CYCLES,           // Тип объекта "Циклические линии
   OBJECT_DE_TYPE_GSTD_ARROWED_LINE       =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROWED_LINE,     // Тип объекта "Линия со стрелкой"
   OBJECT_DE_TYPE_GSTD_CHANNEL            =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_CHANNEL,          // Тип объекта "Равноудаленный канал
   OBJECT_DE_TYPE_GSTD_STDDEVCHANNEL      =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_STDDEVCHANNEL,    // Тип объекта "Канал стандартного отклонения
   OBJECT_DE_TYPE_GSTD_REGRESSION         =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_REGRESSION,       // Тип объекта "Канал на линейной регрессии
   OBJECT_DE_TYPE_GSTD_PITCHFORK          =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_PITCHFORK,        // Тип объекта "Вилы Эндрюса
   OBJECT_DE_TYPE_GSTD_GANNLINE           =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_GANNLINE,         // Тип объекта "Линия Ганна
   OBJECT_DE_TYPE_GSTD_GANNFAN            =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_GANNFAN,          // Тип объекта "Веер Ганна
   OBJECT_DE_TYPE_GSTD_GANNGRID           =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_GANNGRID,         // Тип объекта "Сетка Ганна
   OBJECT_DE_TYPE_GSTD_FIBO               =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_FIBO,             // Тип объекта "Уровни Фибоначчи
   OBJECT_DE_TYPE_GSTD_FIBOTIMES          =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_FIBOTIMES,        // Тип объекта "Временные зоны Фибоначчи
   OBJECT_DE_TYPE_GSTD_FIBOFAN            =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_FIBOFAN,          // Тип объекта "Веер Фибоначчи
   OBJECT_DE_TYPE_GSTD_FIBOARC            =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_FIBOARC,          // Тип объекта "Дуги Фибоначчи
   OBJECT_DE_TYPE_GSTD_FIBOCHANNEL        =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_FIBOCHANNEL,      // Тип объекта "Канал Фибоначчи
   OBJECT_DE_TYPE_GSTD_EXPANSION          =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_EXPANSION,        // Тип объекта "Расширение Фибоначчи
   OBJECT_DE_TYPE_GSTD_ELLIOTWAVE5        =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ELLIOTWAVE5,      // Тип объекта "5-волновка Эллиотта
   OBJECT_DE_TYPE_GSTD_ELLIOTWAVE3        =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ELLIOTWAVE3,      // Тип объекта "3-волновка Эллиотта
   OBJECT_DE_TYPE_GSTD_RECTANGLE          =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_RECTANGLE,        // Тип объекта "Прямоугольник
   OBJECT_DE_TYPE_GSTD_TRIANGLE           =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_TRIANGLE,         // Тип объекта "Треугольник
   OBJECT_DE_TYPE_GSTD_ELLIPSE            =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ELLIPSE,          // Тип объекта "Эллипс
   OBJECT_DE_TYPE_GSTD_ARROW_THUMB_UP     =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_THUMB_UP,   // Тип объекта "Знак "Хорошо" (большой палец вверх)
   OBJECT_DE_TYPE_GSTD_ARROW_THUMB_DOWN   =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_THUMB_DOWN, // Тип объекта "Знак "Плохо" (большой палец вниз)
   OBJECT_DE_TYPE_GSTD_ARROW_UP           =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_UP,         // Тип объекта "Знак "Стрелка вверх"
   OBJECT_DE_TYPE_GSTD_ARROW_DOWN         =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_DOWN,       // Тип объекта "Знак "Стрелка вниз"
   OBJECT_DE_TYPE_GSTD_ARROW_STOP         =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_STOP,       // Тип объекта "Знак "Стоп"
   OBJECT_DE_TYPE_GSTD_ARROW_CHECK        =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_CHECK,      // Тип объекта "Знак "Птичка" (галка)
   OBJECT_DE_TYPE_GSTD_ARROW_LEFT_PRICE   =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_LEFT_PRICE, // Тип объекта "Левая ценовая метка
   OBJECT_DE_TYPE_GSTD_ARROW_RIGHT_PRICE  =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_RIGHT_PRICE,// Тип объекта "Правая ценовая метка
   OBJECT_DE_TYPE_GSTD_ARROW_BUY          =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_BUY,        // Тип объекта "Знак "Buy"
   OBJECT_DE_TYPE_GSTD_ARROW_SELL         =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW_SELL,       // Тип объекта "Знак "Sell"
   OBJECT_DE_TYPE_GSTD_ARROW              =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_ARROW,            // Тип объекта "Стрелка"
   OBJECT_DE_TYPE_GSTD_TEXT               =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_TEXT,             // Тип объекта "Текст"
   OBJECT_DE_TYPE_GSTD_LABEL              =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_LABEL,            // Тип объекта "Текстовая метка"
   OBJECT_DE_TYPE_GSTD_BUTTON             =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_BUTTON,           // Тип объекта "Кнопка"
   OBJECT_DE_TYPE_GSTD_CHART              =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_CHART,            // Тип объекта "График"
   OBJECT_DE_TYPE_GSTD_BITMAP             =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_BITMAP,           // Тип объекта "Рисунок"
   OBJECT_DE_TYPE_GSTD_BITMAP_LABEL       =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_BITMAP_LABEL,     // Тип объекта "Графическая метка"
   OBJECT_DE_TYPE_GSTD_EDIT               =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_EDIT,             // Тип объекта "Поле ввода"
   OBJECT_DE_TYPE_GSTD_EVENT              =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_EVENT,            // Тип объекта "Событие, соответствующий событию в экономическом календаре"
   OBJECT_DE_TYPE_GSTD_RECTANGLE_LABEL    =  OBJECT_DE_TYPE_GSTD_OBJ+1+OBJ_RECTANGLE_LABEL,  // Тип объекта "Прямоугольная метка для создания и оформления пользовательского графического интерфейса"
   
//--- Объекты
   OBJECT_DE_TYPE_BASE  =  OBJECT_DE_TYPE_GSTD_RECTANGLE_LABEL+1, // Базовый объект всех объектов библиотеки
   OBJECT_DE_TYPE_BASE_EXT,                                       // Расширенный базовый объект всех объектов библиотеки
   
   // .......... Для краткости пропущены константы других типов объектов
   // ..........
   // ..........

  };

В перечислении списка принадлежности графических объектов изменим константу GRAPH_OBJ_BELONG_TERMINAL, наименование которой указывает на принадлежность графического объекта терминалу. Сделаем его более подходящим: GRAPH_OBJ_BELONG_NO_PROGRAM, так как объект может не принадлежать программе, работающей под управлением библиотеки, но, тем не менее, принадлежать другой программе, а не терминалу:

//+------------------------------------------------------------------+
//| Список принадлежностей графических объектов                      |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_OBJ_BELONG
  {
   GRAPH_OBJ_BELONG_PROGRAM,                          // Графический объект принадлежит программе
   GRAPH_OBJ_BELONG_NO_PROGRAM,                       // Графический объект не принадлежит программе
  };
//+------------------------------------------------------------------+

В перечисление типов графических элементов добавим новую константу:

//+------------------------------------------------------------------+
//| Список типов графических элементов                               |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_ELEMENT_TYPE
  {
   GRAPH_ELEMENT_TYPE_STANDART,                       // Стандартный графический объект
   GRAPH_ELEMENT_TYPE_ELEMENT,                        // Элемент
   GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                     // Объект тени
   GRAPH_ELEMENT_TYPE_FORM,                           // Форма
   GRAPH_ELEMENT_TYPE_WINDOW,                         // Окно
  };
//+------------------------------------------------------------------+

Так как все объекты, описывающие созданные в программе графические объекты, будут храниться в одном списке, то указание типа графического элемента позволит нам быстро выбирать из всего списка только нужные графические элементы. Соответственно, если выбрать "Стандартный графический объект" в качестве условия фильтра для списка-коллекции, то на выходе получим список, состоящий только из объектов, описывающих созданные стандартные графические объекты.

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

//+------------------------------------------------------------------+
//| Целочисленные свойства стандартного графического объекта         |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_OBJ_PROP_INTEGER
  {
   //--- Дополнительные свойства
   GRAPH_OBJ_PROP_ID = 0,                             // Идентификатор объекта
   GRAPH_OBJ_PROP_TYPE,                               // Тип графичесеого объекта (ENUM_OBJECT)
   GRAPH_OBJ_PROP_ELEMENT_TYPE,                       // Тип графического элемента (ENUM_GRAPH_ELEMENT_TYPE)
   GRAPH_OBJ_PROP_BELONG,                             // Принадлежность графического объекта
   GRAPH_OBJ_PROP_CHART_ID,                           // Идентификатор графика
   GRAPH_OBJ_PROP_WND_NUM,                            // Номер подокна графика
   GRAPH_OBJ_PROP_NUM,                                // Номер объекта в списке
   //--- Общие свойства всех графических объектов
   GRAPH_OBJ_PROP_CREATETIME,                         // Время создания объекта
   GRAPH_OBJ_PROP_TIMEFRAMES,                         // Видимость объекта на таймфреймах
   GRAPH_OBJ_PROP_BACK,                               // Объект на заднем плане
   GRAPH_OBJ_PROP_ZORDER,                             // Приоритет графического объекта на получение события нажатия мышки на графике
   GRAPH_OBJ_PROP_HIDDEN,                             // Запрет на показ имени графического объекта в списке объектов терминала
   GRAPH_OBJ_PROP_SELECTED,                           // Выделенность объекта
   GRAPH_OBJ_PROP_SELECTABLE,                         // Доступность объекта
//--- Свойства, принадлежащие различным графическим объектам
   GRAPH_OBJ_PROP_TIME,                               // Координата времени
   GRAPH_OBJ_PROP_COLOR,                              // Цвет
   GRAPH_OBJ_PROP_STYLE,                              // Стиль
   GRAPH_OBJ_PROP_WIDTH,                              // Толщина линии
   GRAPH_OBJ_PROP_FILL,                               // Заливка объекта цветом
   GRAPH_OBJ_PROP_READONLY,                           // Возможность редактирования текста в объекте Edit
   GRAPH_OBJ_PROP_LEVELS,                             // Количество уровней
   GRAPH_OBJ_PROP_LEVELCOLOR,                         // Цвет линии-уровня
   GRAPH_OBJ_PROP_LEVELSTYLE,                         // Стиль линии-уровня
   GRAPH_OBJ_PROP_LEVELWIDTH,                         // Толщина линии-уровня
   GRAPH_OBJ_PROP_ALIGN,                              // Горизонтальное выравнивание текста в объекте "Поле ввода" (OBJ_EDIT)
   GRAPH_OBJ_PROP_FONTSIZE,                           // Размер шрифта
   GRAPH_OBJ_PROP_RAY_LEFT,                           // Луч продолжается влево
   GRAPH_OBJ_PROP_RAY_RIGHT,                          // Луч продолжается вправо
   GRAPH_OBJ_PROP_RAY,                                // Вертикальная линия продолжается на все окна графика
   GRAPH_OBJ_PROP_ELLIPSE,                            // Отображение полного эллипса для объекта "Дуги Фибоначчи"
   GRAPH_OBJ_PROP_ARROWCODE,                          // Код стрелки для объекта "Стрелка"
   GRAPH_OBJ_PROP_ANCHOR,                             // Положение точки привязки графического объекта
   GRAPH_OBJ_PROP_XDISTANCE,                          // Дистанция в пикселях по оси X от угла привязки
   GRAPH_OBJ_PROP_YDISTANCE,                          // Дистанция в пикселях по оси Y от угла привязки
   GRAPH_OBJ_PROP_DIRECTION,                          // Тренд объекта Ганна
   GRAPH_OBJ_PROP_DEGREE,                             // Уровень волновой разметки Эллиотта
   GRAPH_OBJ_PROP_DRAWLINES,                          // Отображение линий для волновой разметки Эллиотта
   GRAPH_OBJ_PROP_STATE,                              // Состояние кнопки (Нажата/Отжата)
   GRAPH_OBJ_PROP_OBJ_CHART_ID,                       // Идентификатор объекта "График" (OBJ_CHART).
   GRAPH_OBJ_PROP_CHART_OBJ_PERIOD,                   // Период для объекта "График"
   GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE,               // Признак отображения шкалы времени для объекта "График"
   GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE,              // Признак отображения ценовой шкалы для объекта "График"
   GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE,              // Масштаб для объекта "График"
   GRAPH_OBJ_PROP_XSIZE,                              // Ширина объекта по оси X в пикселях.
   GRAPH_OBJ_PROP_YSIZE,                              // Высота объекта по оси Y в пикселях.
   GRAPH_OBJ_PROP_XOFFSET,                            // X-координата левого верхнего угла прямоугольной области видимости.
   GRAPH_OBJ_PROP_YOFFSET,                            // Y-координата левого верхнего угла прямоугольной области видимости.
   GRAPH_OBJ_PROP_BGCOLOR,                            // Цвет фона для OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
   GRAPH_OBJ_PROP_CORNER,                             // Угол графика для привязки графического объекта
   GRAPH_OBJ_PROP_BORDER_TYPE,                        // Тип рамки для объекта "Прямоугольная рамка"
   GRAPH_OBJ_PROP_BORDER_COLOR,                       // Цвет рамки для объекта OBJ_EDIT и OBJ_BUTTON
  };
#define GRAPH_OBJ_PROP_INTEGER_TOTAL (51)             // Общее количество целочисленных свойств
#define GRAPH_OBJ_PROP_INTEGER_SKIP  (0)              // Количество неиспользуемых в сортировке целочисленных свойств
//+------------------------------------------------------------------+
//| Вещественные свойства стандартного графического объекта          |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_OBJ_PROP_DOUBLE
  {
   GRAPH_OBJ_PROP_PRICE = GRAPH_OBJ_PROP_INTEGER_TOTAL,// Координата цены
   GRAPH_OBJ_PROP_LEVELVALUE,                         // Значение уровня
   GRAPH_OBJ_PROP_SCALE,                              // Масштаб
   GRAPH_OBJ_PROP_ANGLE,                              // Угол
   GRAPH_OBJ_PROP_DEVIATION,                          // Отклонение для канала стандартного отклонения
  };
#define GRAPH_OBJ_PROP_DOUBLE_TOTAL  (5)              // Общее количество вещественных свойств
#define GRAPH_OBJ_PROP_DOUBLE_SKIP   (0)              // Количество неиспользуемых в сортировке вещественных свойств
//+------------------------------------------------------------------+
//| Строковые свойства стандартного графического объекта             |
//+------------------------------------------------------------------+
enum ENUM_GRAPH_OBJ_PROP_STRING
  {
   GRAPH_OBJ_PROP_NAME = (GRAPH_OBJ_PROP_INTEGER_TOTAL+GRAPH_OBJ_PROP_DOUBLE_TOTAL), // Имя объекта
   GRAPH_OBJ_PROP_TEXT,                               // Описание объекта (текст, содержащийся в объекте)
   GRAPH_OBJ_PROP_TOOLTIP,                            // Текст всплывающей подсказки
   GRAPH_OBJ_PROP_LEVELTEXT,                          // Описание уровня
   GRAPH_OBJ_PROP_FONT,                               // Шрифт
   GRAPH_OBJ_PROP_BMPFILE,                            // Имя BMP-файла для объекта "Графическая метка"
   GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL,                   // Символ для объекта "График" 
  };
#define GRAPH_OBJ_PROP_STRING_TOTAL  (7)              // Общее количество строковых свойств
//+------------------------------------------------------------------+

Назначение таких перечислений нам уже давно известно, так как все объекты библиотеки создаются по одному принципу.

Соответственно, нам необходимо также добавить и перечисление возможных критериев сортировки графических объектов в списке-коллекции:

//+------------------------------------------------------------------+
//| Возможные критерии сортировки графических объектов               |
//+------------------------------------------------------------------+
#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_GRAPH_OBJ_ID = 0,                             // Сортировать по идентификатору объекта
   SORT_BY_GRAPH_OBJ_TYPE,                               // Сортировать по типу объекта
   SORT_BY_GRAPH_OBJ_ELEMENT_TYPE,                       // Сортировать по типу графического элемента
   SORT_BY_GRAPH_OBJ_BELONG,                             // Сортировать по принадлежности графического объекта
   SORT_BY_GRAPH_OBJ_CHART_ID,                           // Сортировать по идентификатору графика
   SORT_BY_GRAPH_OBJ_WND_NUM,                            // Сортировать по номеру подокна графика
   SORT_BY_GRAPH_OBJ_NUM,                                // Сортировать по номеру объекта в списке
   SORT_BY_GRAPH_OBJ_CREATETIME,                         // Сортировать по времени создания объекта
   SORT_BY_GRAPH_OBJ_TIMEFRAMES,                         // Сортировать по видимости объекта на таймфреймах
   SORT_BY_GRAPH_OBJ_BACK,                               // Сортировать по свойству "Объект на заднем плане"
   SORT_BY_GRAPH_OBJ_ZORDER,                             // Сортировать по приоритету графического объекта на получение события нажатия мышки на графике
   SORT_BY_GRAPH_OBJ_HIDDEN,                             // Сортировать по запрету на показ имени графического объекта в списке объектов терминала
   SORT_BY_GRAPH_OBJ_SELECTED,                           // Сортировать по свойству"Выделенность объекта"
   SORT_BY_GRAPH_OBJ_SELECTABLE,                         // Сортировать по свойству "Доступность объекта"
   SORT_BY_GRAPH_OBJ_TIME,                               // Сортировать по координате времени
   SORT_BY_GRAPH_OBJ_COLOR,                              // Сортировать по цвету
   SORT_BY_GRAPH_OBJ_STYLE,                              // Сортировать по стилю
   SORT_BY_GRAPH_OBJ_WIDTH,                              // Сортировать по толщине линии
   SORT_BY_GRAPH_OBJ_FILL,                               // Сортировать по свойству"Заливка объекта цветом"
   SORT_BY_GRAPH_OBJ_READONLY,                           // Сортировать по возможности редактирования текста в объекте Edit
   SORT_BY_GRAPH_OBJ_LEVELS,                             // Сортировать по количеству уровней
   SORT_BY_GRAPH_OBJ_LEVELCOLOR,                         // Сортировать по цвету линии-уровня
   SORT_BY_GRAPH_OBJ_LEVELSTYLE,                         // Сортировать по стилю линии-уровня
   SORT_BY_GRAPH_OBJ_LEVELWIDTH,                         // Сортировать по толщине линии-уровня
   SORT_BY_GRAPH_OBJ_ALIGN,                              // Сортировать по свойству "Горизонтальное выравнивание текста в объекте "Поле ввода""
   SORT_BY_GRAPH_OBJ_FONTSIZE,                           // Сортировать по размеру шрифта
   SORT_BY_GRAPH_OBJ_RAY_LEFT,                           // Сортировать по свойству "Луч продолжается влево"
   SORT_BY_GRAPH_OBJ_RAY_RIGHT,                          // Сортировать по свойству"Луч продолжается вправо"
   SORT_BY_GRAPH_OBJ_RAY,                                // Сортировать по свойству "Вертикальная линия продолжается на все окна графика"
   SORT_BY_GRAPH_OBJ_ELLIPSE,                            // Сортировать по свойству "Отображение полного эллипса для объекта "Дуги Фибоначчи"
   SORT_BY_GRAPH_OBJ_ARROWCODE,                          // Сортировать по коду стрелки для объекта "Стрелка"
   SORT_BY_GRAPH_OBJ_ANCHOR,                             // Сортировать по положению точки привязки графического объекта
   SORT_BY_GRAPH_OBJ_XDISTANCE,                          // Сортировать по дистанции в пикселях по оси X от угла привязки
   SORT_BY_GRAPH_OBJ_YDISTANCE,                          // Сортировать по дистанции в пикселях по оси Y от угла привязки
   SORT_BY_GRAPH_OBJ_DIRECTION,                          // Сортировать по свойству "Тренд объекта Ганна"
   SORT_BY_GRAPH_OBJ_DEGREE,                             // Сортировать по свойству "Уровень волновой разметки Эллиотта"
   SORT_BY_GRAPH_OBJ_DRAWLINES,                          // Сортировать по свойству "Отображение линий для волновой разметки Эллиотта"
   SORT_BY_GRAPH_OBJ_STATE,                              // Сортировать по состоянию кнопки (Нажата/Отжата)
   SORT_BY_GRAPH_OBJ_OBJ_CHART_ID,                       // Сортировать по идентификатору объекта "График".
   SORT_BY_GRAPH_OBJ_CHART_OBJ_PERIOD,                   // Сортировать по периоду для объекта "График"
   SORT_BY_GRAPH_OBJ_CHART_OBJ_DATE_SCALE,               // Сортировать по признаку отображения шкалы времени для объекта "График"
   SORT_BY_GRAPH_OBJ_CHART_OBJ_PRICE_SCALE,              // Сортировать по признаку отображения ценовой шкалы для объекта "График"
   SORT_BY_GRAPH_OBJ_CHART_OBJ_CHART_SCALE,              // Сортировать по масштабу для объекта "График"
   SORT_BY_GRAPH_OBJ_XSIZE,                              // Сортировать по ширине объекта по оси X в пикселях
   SORT_BY_GRAPH_OBJ_YSIZE,                              // Сортировать по высоте объекта по оси Y в пикселях
   SORT_BY_GRAPH_OBJ_XOFFSET,                            // Сортировать по X-координате левого верхнего угла прямоугольной области видимости
   SORT_BY_GRAPH_OBJ_YOFFSET,                            // Сортировать по Y-координате левого верхнего угла прямоугольной области видимости
   SORT_BY_GRAPH_OBJ_BGCOLOR,                            // Сортировать по цвету фона для OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
   SORT_BY_GRAPH_OBJ_CORNER,                             // Сортировать по углу графика для привязки графического объекта
   SORT_BY_GRAPH_OBJ_BORDER_TYPE,                        // Сортировать по типу рамки для объекта "Прямоугольная рамка"
   SORT_BY_GRAPH_OBJ_BORDER_COLOR,                       // Сортировать по цвету рамки для объекта OBJ_EDIT и OBJ_BUTTON
//--- Сортировка по вещественным свойствам
   SORT_BY_GRAPH_OBJ_PRICE = FIRST_GRAPH_OBJ_DBL_PROP,   // Сортировать по координате цены
   SORT_BY_GRAPH_OBJ_LEVELVALUE,                         // Сортировать по значению уровня
   SORT_BY_GRAPH_OBJ_SCALE,                              // Сортировать по масштабу (свойство объектов Ганна и объекта "Дуги Фибоначчи")
   SORT_BY_GRAPH_OBJ_ANGLE,                              // Сортировать по углу
   SORT_BY_GRAPH_OBJ_DEVIATION,                          // Сортировать по отклонению для канала стандартного отклонения
//--- Сортировка по строковым свойствам
   SORT_BY_GRAPH_OBJ_NAME = FIRST_GRAPH_OBJ_STR_PROP,    // Сортировать по имени объекта
   SORT_BY_GRAPH_OBJ_TEXT,                               // Сортировать по описанию объекта
   SORT_BY_GRAPH_OBJ_TOOLTIP,                            // Сортировать по тексту всплывающей подсказки
   SORT_BY_GRAPH_OBJ_LEVELTEXT,                          // Сортировать по описанию уровня
   SORT_BY_GRAPH_OBJ_FONT,                               // Сортировать по шрифту
   SORT_BY_GRAPH_OBJ_BMPFILE,                            // Сортировать по имени BMP-файла для объекта "Графическая метка"
   SORT_BY_GRAPH_OBJ_CHART_OBJ_SYMBOL,                   // Сортировать по символу для объекта "График" 
  };
//+------------------------------------------------------------------+


Теперь добавим тексты новых сообщений библиотеки и описаний всех свойств графических объектов.
Для этого в файле \MQL5\Include\DoEasy\Data.mqh впишем индексы новых сообщений библиотеки:

   MSG_LIB_TEXT_JANUARY,                              // Январь
   MSG_LIB_TEXT_FEBRUARY,                             // Февраль
   MSG_LIB_TEXT_MARCH,                                // Март
   MSG_LIB_TEXT_APRIL,                                // Апрель
   MSG_LIB_TEXT_MAY,                                  // Май
   MSG_LIB_TEXT_JUNE,                                 // Июнь
   MSG_LIB_TEXT_JULY,                                 // Июль
   MSG_LIB_TEXT_AUGUST,                               // Август
   MSG_LIB_TEXT_SEPTEMBER,                            // Сентябрь
   MSG_LIB_TEXT_OCTOBER,                              // Октябрь
   MSG_LIB_TEXT_NOVEMBER,                             // Ноябрь
   MSG_LIB_TEXT_DECEMBER,                             // Декабрь
   
   MSG_LIB_TEXT_ALIGN_LEFT,                           // Выравнивание по левой границе 
   MSG_LIB_TEXT_ALIGN_CENTER,                         // Выравнивание по центру
   MSG_LIB_TEXT_ALIGN_RIGHT,                          // Выравнивание по правой границе
   
   MSG_LIB_TEXT_GANN_UP_TREND,                        // Линия соответствует восходящему тренду
   MSG_LIB_TEXT_GANN_DOWN_TREND,                      // Линия соответствует нисходящему тренду
   
   MSG_LIB_TEXT_ELLIOTT_GRAND_SUPERCYCLE,             // Главный Суперцикл (Grand Supercycle)
   MSG_LIB_TEXT_ELLIOTT_SUPERCYCLE,                   // Суперцикл (Supercycle)
   MSG_LIB_TEXT_ELLIOTT_CYCLE,                        // Цикл (Cycle)
   MSG_LIB_TEXT_ELLIOTT_PRIMARY,                      // Первичный цикл (Primary)
   MSG_LIB_TEXT_ELLIOTT_INTERMEDIATE,                 // Промежуточное звено (Intermediate)
   MSG_LIB_TEXT_ELLIOTT_MINOR,                        // Второстепенный цикл (Minor)
   MSG_LIB_TEXT_ELLIOTT_MINUTE,                       // Минута (Minute)
   MSG_LIB_TEXT_ELLIOTT_MINUETTE,                     // Секунда (Minuette)
   MSG_LIB_TEXT_ELLIOTT_SUBMINUETTE,                  // Субсекунда (Subminuette)
   
   MSG_LIB_TEXT_BUTTON_STATE_PRESSED,                 // Нажата
   MSG_LIB_TEXT_BUTTON_STATE_DEPRESSED,               // Отжата
   
   MSG_LIB_TEXT_CORNER_LEFT_UPPER,                    // Центр координат в левом верхнем углу графика
   MSG_LIB_TEXT_CORNER_LEFT_LOWER,                    // Центр координат в левом нижнем углу графика
   MSG_LIB_TEXT_CORNER_RIGHT_LOWER,                   // Центр координат в правом нижнем углу графика
   MSG_LIB_TEXT_CORNER_RIGHT_UPPER,                   // Центр координат в правом верхнем углу графика
   
   MSG_LIB_TEXT_BORDER_FLAT,                          // Плоский вид
   MSG_LIB_TEXT_BORDER_RAISED,                        // Выпуклый вид
   MSG_LIB_TEXT_BORDER_SUNKEN,                        // Вогнутый вид
   
   MSG_LIB_TEXT_SUNDAY,                               // Воскресение
   MSG_LIB_TEXT_MONDAY,                               // Понедельник
   MSG_LIB_TEXT_TUESDAY,                              // Вторник
   MSG_LIB_TEXT_WEDNESDAY,                            // Среда
   MSG_LIB_TEXT_THURSDAY,                             // Четверг
   MSG_LIB_TEXT_FRIDAY,                               // Пятница
   MSG_LIB_TEXT_SATURDAY,                             // Суббота

...

//--- CGraphElementsCollection
   MSG_GRAPH_ELM_COLLECTION_ERR_OBJ_ALREADY_EXISTS,   // Ошибка. Уже существует объект управления чартами с идентификатором чарта 
   MSG_GRAPH_ELM_COLLECTION_ERR_FAILED_CREATE_CTRL_OBJ,// Не удалось создать объект управления чартами с идентификатором чарта 
   
//--- GStdGraphObj
   MSG_GRAPH_STD_OBJ_ERR_NOT_FIND_SUBWINDOW,          // Не удалось найти подокно графика
   
   MSG_GRAPH_ELEMENT_TYPE_STANDART,                   // Стандартный графический объект
   MSG_GRAPH_ELEMENT_TYPE_ELEMENT,                    // Элемент
   MSG_GRAPH_ELEMENT_TYPE_SHADOW_OBJ,                 // Объект тени
   MSG_GRAPH_ELEMENT_TYPE_FORM,                       // Форма
   MSG_GRAPH_ELEMENT_TYPE_WINDOW,                     // Окно
   
   MSG_GRAPH_OBJ_BELONG_PROGRAM,                      // Графический объект принадлежит программе
   MSG_GRAPH_OBJ_BELONG_NO_PROGRAM,                   // Графический объект не принадлежит программе
//---
   MSG_GRAPH_STD_OBJ_VLINE,                           // Вертикальная линия
   MSG_GRAPH_STD_OBJ_HLINE,                           // Горизонтальная линия
   MSG_GRAPH_STD_OBJ_TREND,                           // Трендовая линия
   MSG_GRAPH_STD_OBJ_TRENDBYANGLE,                    // Трендовая линия по углу
   MSG_GRAPH_STD_OBJ_CYCLES,                          // Циклические линии
   MSG_GRAPH_STD_OBJ_ARROWED_LINE,                    // Объект "Линия со стрелкой"
   MSG_GRAPH_STD_OBJ_CHANNEL,                         // Равноудаленный канал
   MSG_GRAPH_STD_OBJ_STDDEVCHANNEL,                   // Канал стандартного отклонения
   MSG_GRAPH_STD_OBJ_REGRESSION,                      // Канал на линейной регрессии
   MSG_GRAPH_STD_OBJ_PITCHFORK,                       // Вилы Эндрюса
   MSG_GRAPH_STD_OBJ_GANNLINE,                        // Линия Ганна
   MSG_GRAPH_STD_OBJ_GANNFAN,                         // Веер Ганна
   MSG_GRAPH_STD_OBJ_GANNGRID,                        // Сетка Ганна
   MSG_GRAPH_STD_OBJ_FIBO,                            // Уровни Фибоначчи
   MSG_GRAPH_STD_OBJ_FIBOTIMES,                       // Временные зоны Фибоначчи
   MSG_GRAPH_STD_OBJ_FIBOFAN,                         // Веер Фибоначчи
   MSG_GRAPH_STD_OBJ_FIBOARC,                         // Дуги Фибоначчи
   MSG_GRAPH_STD_OBJ_FIBOCHANNEL,                     // Канал Фибоначчи
   MSG_GRAPH_STD_OBJ_EXPANSION,                       // Расширение Фибоначчи
   MSG_GRAPH_STD_OBJ_ELLIOTWAVE5,                     // 5-волновка Эллиотта
   MSG_GRAPH_STD_OBJ_ELLIOTWAVE3,                     // 3-волновка Эллиотта
   MSG_GRAPH_STD_OBJ_RECTANGLE,                       // Прямоугольник
   MSG_GRAPH_STD_OBJ_TRIANGLE,                        // Треугольник
   MSG_GRAPH_STD_OBJ_ELLIPSE,                         // Эллипс
   MSG_GRAPH_STD_OBJ_ARROW_THUMB_UP,                  // Знак "Хорошо" (большой палец вверх)
   MSG_GRAPH_STD_OBJ_ARROW_THUMB_DOWN,                // Знак "Плохо" (большой палец вниз)
   MSG_GRAPH_STD_OBJ_ARROW_UP,                        // Знак "Стрелка вверх"
   MSG_GRAPH_STD_OBJ_ARROW_DOWN,                      // Знак "Стрелка вниз"
   MSG_GRAPH_STD_OBJ_ARROW_STOP,                      // Знак "Стоп"
   MSG_GRAPH_STD_OBJ_ARROW_CHECK,                     // Знак "Птичка" (галка)
   MSG_GRAPH_STD_OBJ_ARROW_LEFT_PRICE,                // Левая ценовая метка
   MSG_GRAPH_STD_OBJ_ARROW_RIGHT_PRICE,               // Правая ценовая метка
   MSG_GRAPH_STD_OBJ_ARROW_BUY,                       // Знак "Buy"
   MSG_GRAPH_STD_OBJ_ARROW_SELL,                      // Знак "Sell"
   MSG_GRAPH_STD_OBJ_ARROW,                           // Объект "Стрелка"
   MSG_GRAPH_STD_OBJ_TEXT,                            // Объект "Текст"
   MSG_GRAPH_STD_OBJ_LABEL,                           // Объект "Текстовая метка"
   MSG_GRAPH_STD_OBJ_BUTTON,                          // Объект "Кнопка"
   MSG_GRAPH_STD_OBJ_CHART,                           // Объект "График"
   MSG_GRAPH_STD_OBJ_BITMAP,                          // Объект "Рисунок"
   MSG_GRAPH_STD_OBJ_BITMAP_LABEL,                    // Объект "Графическая метка"
   MSG_GRAPH_STD_OBJ_EDIT,                            // Объект "Поле ввода"
   MSG_GRAPH_STD_OBJ_EVENT,                           // Объект "Событие", соответствующий событию в экономическом календаре
   MSG_GRAPH_STD_OBJ_RECTANGLE_LABEL,                 // Объект "Прямоугольная метка"для создания и оформления пользовательского графического интерфейса

   MSG_GRAPH_OBJ_PROP_ID,                             // Идентификатор объекта
   MSG_GRAPH_OBJ_PROP_TYPE,                           // Тип графичесеого объекта (ENUM_OBJECT)
   MSG_GRAPH_OBJ_PROP_ELEMENT_TYPE,                   // Тип графического элемента (ENUM_GRAPH_ELEMENT_TYPE)
   MSG_GRAPH_OBJ_PROP_BELONG,                         // Принадлежность графического объекта
   MSG_GRAPH_OBJ_PROP_CHART_ID,                       // Идентификатор графика
   MSG_GRAPH_OBJ_PROP_WND_NUM,                        // Номер подокна графика
   MSG_GRAPH_OBJ_PROP_CREATETIME,                     // Время создания
   MSG_GRAPH_OBJ_PROP_TIMEFRAMES,                     // Видимость объекта на таймфреймах
   MSG_GRAPH_OBJ_PROP_BACK,                           // Объект на заднем плане
   MSG_GRAPH_OBJ_PROP_ZORDER,                         // Приоритет графического объекта на получение события нажатия мышки на графике
   MSG_GRAPH_OBJ_PROP_HIDDEN,                         // Запрет на показ имени графического объекта в списке объектов терминала
   MSG_GRAPH_OBJ_PROP_SELECTED,                       // Выделенность объекта
   MSG_GRAPH_OBJ_PROP_SELECTABLE,                     // Доступность объекта
   MSG_GRAPH_OBJ_PROP_NUM,                            // Номер объекта в списке
   MSG_GRAPH_OBJ_PROP_TIME,                           // Координата времени
   MSG_GRAPH_OBJ_PROP_COLOR,                          // Цвет
   MSG_GRAPH_OBJ_PROP_STYLE,                          // Стиль
   MSG_GRAPH_OBJ_PROP_WIDTH,                          // Толщина линии
   MSG_GRAPH_OBJ_PROP_FILL,                           // Заливка объекта цветом
   MSG_GRAPH_OBJ_PROP_READONLY,                       // Возможность редактирования текста в объекте Edit
   MSG_GRAPH_OBJ_PROP_LEVELS,                         // Количество уровней
   MSG_GRAPH_OBJ_PROP_LEVELCOLOR,                     // Цвет линии-уровня
   MSG_GRAPH_OBJ_PROP_LEVELSTYLE,                     // Стиль линии-уровня
   MSG_GRAPH_OBJ_PROP_LEVELWIDTH,                     // Толщина линии-уровня
   MSG_GRAPH_OBJ_PROP_ALIGN,                          // Горизонтальное выравнивание текста в объекте "Поле ввода" (OBJ_EDIT)
   MSG_GRAPH_OBJ_PROP_FONTSIZE,                       // Размер шрифта
   MSG_GRAPH_OBJ_PROP_RAY_LEFT,                       // Луч продолжается влево
   MSG_GRAPH_OBJ_PROP_RAY_RIGHT,                      // Луч продолжается вправо
   MSG_GRAPH_OBJ_PROP_RAY,                            // Вертикальная линия продолжается на все окна графика
   MSG_GRAPH_OBJ_PROP_ELLIPSE,                        // Отображение полного эллипса для объекта "Дуги Фибоначчи"
   MSG_GRAPH_OBJ_PROP_ARROWCODE,                      // Код стрелки для объекта "Стрелка"
   MSG_GRAPH_OBJ_PROP_ANCHOR,                         // Положение точки привязки графического объекта
   MSG_GRAPH_OBJ_PROP_XDISTANCE,                      // Дистанция в пикселях по оси X от угла привязки
   MSG_GRAPH_OBJ_PROP_YDISTANCE,                      // Дистанция в пикселях по оси Y от угла привязки
   MSG_GRAPH_OBJ_PROP_DIRECTION,                      // Тренд объекта Ганна
   MSG_GRAPH_OBJ_PROP_DEGREE,                         // Уровень волновой разметки Эллиотта
   MSG_GRAPH_OBJ_PROP_DRAWLINES,                      // Отображение линий для волновой разметки Эллиотта
   MSG_GRAPH_OBJ_PROP_STATE,                          // Состояние кнопки (Нажата/Отжата)
   MSG_GRAPH_OBJ_PROP_CHART_OBJ_PERIOD,               // Период для объекта "График"
   MSG_GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE,           // Признак отображения шкалы времени для объекта "График"
   MSG_GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE,          // Признак отображения ценовой шкалы для объекта "График"
   MSG_GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE,          // Масштаб для объекта "График"
   MSG_GRAPH_OBJ_PROP_XSIZE,                          // Ширина объекта по оси X в пикселях.
   MSG_GRAPH_OBJ_PROP_YSIZE,                          // Высота объекта по оси Y в пикселях.
   MSG_GRAPH_OBJ_PROP_XOFFSET,                        // X-координата левого верхнего угла прямоугольной области видимости.
   MSG_GRAPH_OBJ_PROP_YOFFSET,                        // Y-координата левого верхнего угла прямоугольной области видимости.
   MSG_GRAPH_OBJ_PROP_BGCOLOR,                        // Цвет фона для OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
   MSG_GRAPH_OBJ_PROP_CORNER,                         // Угол графика для привязки графического объекта
   MSG_GRAPH_OBJ_PROP_BORDER_TYPE,                    // Тип рамки для объекта "Прямоугольная рамка"
   MSG_GRAPH_OBJ_PROP_BORDER_COLOR,                   // Цвет рамки для объекта OBJ_EDIT и OBJ_BUTTON
//---
   MSG_GRAPH_OBJ_PROP_PRICE,                          // Координата цены
   MSG_GRAPH_OBJ_PROP_LEVELVALUE,                     // Значение уровня
   MSG_GRAPH_OBJ_PROP_SCALE,                          // Масштаб (свойство объектов Ганна и объекта "Дуги Фибоначчи")
   MSG_GRAPH_OBJ_PROP_ANGLE,                          // Угол
   MSG_GRAPH_OBJ_PROP_DEVIATION,                      // Отклонение для канала стандартного отклонения
//---
   MSG_GRAPH_OBJ_PROP_NAME,                           // Имя объекта
   MSG_GRAPH_OBJ_PROP_TEXT,                           // Описание объекта (текст, содержащийся в объекте)
   MSG_GRAPH_OBJ_PROP_TOOLTIP,                        // Текст всплывающей подсказки
   MSG_GRAPH_OBJ_PROP_LEVELTEXT,                      // Описание уровня
   MSG_GRAPH_OBJ_PROP_FONT,                           // Шрифт
   MSG_GRAPH_OBJ_PROP_BMPFILE,                        // Имя BMP-файла для объекта "Графическая метка"
   MSG_GRAPH_OBJ_PROP_SYMBOL,                         // Символ для объекта "График" 
   
  };
//+------------------------------------------------------------------+

и текстовые сообщения, соответствующие вновь добавленным индексам:

   {"Январь","January"},
   {"Февраль","February"},
   {"Март","March"},
   {"Апрель","April"},
   {"Май","May"},
   {"Июнь","June"},
   {"Июль","July"},
   {"Август","August"},
   {"Сентябрь","September"},
   {"Октябрь","October"},
   {"Ноябрь","November"},
   {"Декабрь","December"},
   
   {"Выравнивание по левой границе","Left alignment"},
   {"Выравнивание по центру","Centered"},
   {"Выравнивание по правой границе","Right alignment",},
   
   {"Линия соответствует восходящему тренду","Line corresponding to the uptrend line"},
   {"Линия соответствует нисходящему тренду","Line corresponding to the downward trend"},
   
   {"Главный Суперцикл (Grand Supercycle)","Grand Supercycle"},
   {"Суперцикл (Supercycle)","Supercycle"},
   {"Цикл (Cycle)","Cycle"},
   {"Первичный цикл (Primary)","Primary"},
   {"Промежуточное звено (Intermediate)","Intermediate"},
   {"Второстепенный цикл (Minor)","Minor"},
   {"Минута (Minute)","Minute"},
   {"Секунда (Minuette)","Minuette"},
   {"Субсекунда (Subminuette)","Subminuette"},
   
   {"Нажата","Pressed"},
   {"Отжата","Depressed"},
   
   {"Центр координат в левом верхнем углу графика","Center of coordinates is in the upper left corner of the chart"},
   {"Центр координат в левом нижнем углу графика","Center of coordinates is in the lower left corner of the chart"},
   {"Центр координат в правом нижнем углу графика","Center of coordinates is in the lower right corner of the chart"},
   {"Центр координат в правом верхнем углу графика","Center of coordinates is in the upper right corner of the chart"},
   
   {"Плоский вид","Flat form"},
   {"Выпуклый вид","Prominent form"},
   {"Вогнутый вид","Concave form"},
   
   {"Воскресение","Sunday"},
   {"Понедельник","Monday"},
   {"Вторник","Tuesday"},
   {"Среда","Wednesday"},
   {"Четверг","Thursday"},
   {"Пятница","Friday"},
   {"Суббота","Saturday"},

...

//--- CGraphElementsCollection
   {"Ошибка. Уже существует объект управления чартами с идентификатором чарта ","Error. A chart control object already exists with chart id "},
   {"Не удалось создать объект управления чартами с идентификатором чарта ","Failed to create chart control object with chart id "},

//--- GStdGraphObj
   {"Не удалось найти подокно графика","Could not find chart subwindow"},
   
   {"Стандартный графический объект","Standard graphic object"},
   {"Элемент","Element"},
   {"Объект тени","Shadow object"},
   {"Форма","Form"},
   {"Окно","Window"},
   
   {"Графический объект принадлежит программе","The graphic object belongs to the program"},
   {"Графический объект не принадлежит программе","The graphic object does not belong to the program"},
   
   {"Вертикальная линия","Vertical Line"},
   {"Горизонтальная линия","Horizontal Line"},
   {"Трендовая линия","Trend Line"},
   {"Трендовая линия по углу","Trend Line By Angle"},
   {"Циклические линии","Cycle Lines"},
   {"Линия со стрелкой","Arrowed Line"},
   {"Равноудаленный канал","Equidistant Channel"},
   {"Канал стандартного отклонения","Standard Deviation Channel"},
   {"Канал на линейной регрессии","Linear Regression Channel"},
   {"Вилы Эндрюса","Andrews’ Pitchfork"},
   {"Линия Ганна","Gann Line"},
   {"Веер Ганна","Gann Fan"},
   {"Сетка Ганна","Gann Grid"},
   {"Уровни Фибоначчи","Fibonacci Retracement"},
   {"Временные зоны Фибоначчи","Fibonacci Time Zones"},
   {"Веер Фибоначчи","Fibonacci Fan"},
   {"Дуги Фибоначчи","Fibonacci Arcs"},
   {"Канал Фибоначчи","Fibonacci Channel"},
   {"Расширение Фибоначчи","Fibonacci Expansion"},
   {"5-волновка Эллиотта","Elliott Motive Wave"},
   {"3-волновка Эллиотта","Elliott Correction Wave"},
   {"Прямоугольник","Rectangle"},
   {"Треугольник","Triangle"},
   {"Эллипс","Ellipse"},
   {"Знак \"Хорошо\"","Thumbs Up"},
   {"Знак \"Плохо\"","Thumbs Down"},
   {"Знак \"Стрелка вверх\"","Arrow Up"},
   {"Знак \"Стрелка вниз\"","Arrow Down"},
   {"Знак \"Стоп\"","Stop Sign"},
   {"Знак \"Птичка\"","Check Sign"},
   {"Левая ценовая метка","Left Price Label"},
   {"Правая ценовая метка","Right Price Label"},
   {"Знак \"Buy\"","Buy Sign"},
   {"Знак \"Sell\"","Sell Sign"},
   {"Стрелка","Arrow"},
   {"Текст","Text"},
   {"Текстовая метка","Label"},
   {"Кнопка","Button"},
   {"График","Chart"},
   {"Рисунок","Bitmap"},
   {"Графическая метка","Bitmap Label"},
   {"Поле ввода","Edit"},
   {"Событие в экономическом календаре","The \"Event\" object corresponding to an event in the economic calendar"},
   {"Прямоугольная метка","The \"Rectangle label\" object for creating and designing the custom graphical interface"},
   
   {"Идентификатор объекта","Object ID"},
   {"Тип объекта","Object type"},
   {"Тип графического элемента","Graphic element type"},
   {"Принадлежность объекта","Object belongs to"},
   {"Идентификатор графика объекта","Object chart ID"},
   {"Номер подокна графика","Chart subwindow number"},
   {"Время создания","Time of creation"},
   {"Видимость объекта на таймфреймах","Visibility of an object at timeframes"},
   {"Объект на заднем плане","Object in the background"},
   {"Приоритет графического объекта на получение события нажатия мышки на графике","Priority of a graphical object for receiving events of clicking on a chart"},
   {"Запрет на показ имени графического объекта в списке объектов терминала","Prohibit showing of the name of a graphical object in the terminal objects list"},
   {"Выделенность объекта","Object is selected"},
   {"Доступность объекта","Object availability"},
   {"Номер объекта в списке","Object number in the list"},
   {"Координата времени","Time coordinate"},
   {"Цвет","Color"},
   {"Стиль","Style"},
   {"Толщина линии","Line thickness"},
   {"Заливка объекта цветом","Fill an object with color"},
   {"Возможность редактирования текста","Ability to edit text"},
   {"Количество уровней","Number of levels"},
   {"Цвет линии-уровня","Color of the line-level"},
   {"Стиль линии-уровня","Style of the line-level"},
   {"Толщина линии-уровня","Thickness of the line-level"},
   {"Горизонтальное выравнивание текста","Horizontal text alignment"},
   {"Размер шрифта","Font size"},
   {"Луч продолжается влево","Ray goes to the left"},
   {"Луч продолжается вправо","Ray goes to the right"},
   {"Вертикальная линия продолжается на все окна графика","A vertical line goes through all the windows of a chart"},
   {"Отображение полного эллипса","Showing the full ellipse"},
   {"Код стрелки","Arrow code"},
   {"Положение точки привязки","Location of the anchor point"},
   {"Дистанция в пикселях по оси X от угла привязки","The distance in pixels along the X axis from the binding corner"},
   {"Дистанция в пикселях по оси Y от угла привязки","The distance in pixels along the Y axis from the binding corner"},
   {"Тренд","Trend"},
   {"Уровень","Level"},
   {"Отображение линий","Displaying lines"},
   {"Состояние кнопки","Button state"},
   {"Период графика","Chart timeframe"},
   {"Отображение шкалы времени","Displaying the time scale"},
   {"Отображение ценовой шкалы","Displaying the price scale"},
   {"Масштаб графика","Chart scale"},
   {"Ширина по оси X в пикселях","Width along the X axis in pixels"},
   {"Высота по оси Y в пикселях","Height along the Y axis in pixels"},
   {"X-координата левого верхнего угла прямоугольной области видимости","The X coordinate of the upper left corner of the rectangular visible area"},
   {"Y-координата левого верхнего угла прямоугольной области видимости","The Y coordinate of the upper left corner of the rectangular visible area"},
   {"Цвет фона","Background color"},
   {"Угол графика для привязки","The corner of the chart to link a graphical object"},
   {"Тип рамки","Border type"},
   {"Цвет рамки","Border color"},
   {"Координата цены","Price coordinate"},
   {"Значение уровня","Level value"},
   {"Масштаб","Scale"},
   {"Угол","Angle"},
   {"Отклонение канала стандартного отклонения","Deviation for the Standard Deviation Channel"},
   {"Имя","Name"},
   {"Описание","Description"},
   {"Текст всплывающей подсказки","The text of a tooltip"},
   {"Описание уровня","Level description"},
   {"Шрифт","Font"},
   {"Имя BMP-файла","BMP-file name"},
   {"Символ графика","Chart Symbol"},

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


Некоторые свойства графических объектов имеют тип перечислений. Для возврата описания этих перечислений нам необходимо создать функции в файле сервисных функций библиотеки \MQL5\Include\DoEasy\Services\DELib.mqh:

Функция, возвращающая описание стиля линии:

//+------------------------------------------------------------------+
//| Возвращает описание стиля линии                                  |
//+------------------------------------------------------------------+
string LineStyleDescription(const ENUM_LINE_STYLE style)
  {
   return
     (
      style==STYLE_SOLID      ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_SOLID)      :
      style==STYLE_DASH       ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASH)       :
      style==STYLE_DOT        ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DOT)        :
      style==STYLE_DASHDOT    ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOT)    :
      style==STYLE_DASHDOTDOT ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOTDOT) :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Функция, возвращающая описание типа выравнивания:

//+------------------------------------------------------------------+
//| Возвращает описание типа выравнивания                            |
//+------------------------------------------------------------------+
string AlignModeDescription(ENUM_ALIGN_MODE align)
  {
   return
     (
      align==ALIGN_LEFT    ? CMessage::Text(MSG_LIB_TEXT_ALIGN_LEFT)    :
      align==ALIGN_CENTER  ? CMessage::Text(MSG_LIB_TEXT_ALIGN_CENTER)  :
      align==ALIGN_RIGHT   ? CMessage::Text(MSG_LIB_TEXT_ALIGN_RIGHT)   :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Функция, возвращающая описание направления тренда сетки Ганна:

//+------------------------------------------------------------------+
//| Возвращает описание направления тренда сетки Ганна               |
//+------------------------------------------------------------------+
string GannDirectDescription(const ENUM_GANN_DIRECTION direction)
  {
   return
     (
      direction==GANN_UP_TREND   ? CMessage::Text(MSG_LIB_TEXT_GANN_UP_TREND)    :
      direction==GANN_DOWN_TREND ? CMessage::Text(MSG_LIB_TEXT_GANN_DOWN_TREND)  :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Функция, возвращающая описание уровня волновой разметки Эллиотта:

//+------------------------------------------------------------------+
//| Возвращает описание уровня волновой разметки Эллиотта            |
//+------------------------------------------------------------------+
string ElliotWaveDegreeDescription(const ENUM_ELLIOT_WAVE_DEGREE degree)
  {
   return
     (
      degree==ELLIOTT_GRAND_SUPERCYCLE ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_GRAND_SUPERCYCLE)  :
      degree==ELLIOTT_SUPERCYCLE       ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_SUPERCYCLE)        :
      degree==ELLIOTT_CYCLE            ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_CYCLE)             :
      degree==ELLIOTT_PRIMARY          ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_PRIMARY)           :
      degree==ELLIOTT_INTERMEDIATE     ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_INTERMEDIATE)      :
      degree==ELLIOTT_MINOR            ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_MINOR)             :
      degree==ELLIOTT_MINUTE           ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_MINUTE)            :
      degree==ELLIOTT_MINUETTE         ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_MINUETTE)          :
      degree==ELLIOTT_SUBMINUETTE      ? CMessage::Text(MSG_LIB_TEXT_ELLIOTT_SUBMINUETTE)       :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Функция, возвращающая описание угла графика, относительно которого указываются координаты в пикселях:

//+------------------------------------------------------------------+
//| Возвращает описание угла графика, относительно                   |
//| которого указываются координаты в пикселях                       |
//+------------------------------------------------------------------+
string BaseCornerDescription(const ENUM_BASE_CORNER corner)
  {
   return
     (
      corner==CORNER_LEFT_UPPER  ? CMessage::Text(MSG_LIB_TEXT_CORNER_LEFT_UPPER)   :
      corner==CORNER_LEFT_LOWER  ? CMessage::Text(MSG_LIB_TEXT_CORNER_LEFT_LOWER)   :
      corner==CORNER_RIGHT_LOWER ? CMessage::Text(MSG_LIB_TEXT_CORNER_RIGHT_LOWER)  :
      corner==CORNER_RIGHT_UPPER ? CMessage::Text(MSG_LIB_TEXT_CORNER_RIGHT_UPPER)  :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Функция, возвращающая описание вида отображения рамки графического объекта:

//+------------------------------------------------------------------+
//| Возвращает описание вида отображения рамки графического объекта  |
//+------------------------------------------------------------------+
string BorderTypeDescription(const ENUM_BORDER_TYPE border_type)
  {
   return
     (
      border_type==BORDER_FLAT   ? CMessage::Text(MSG_LIB_TEXT_BORDER_FLAT)   :
      border_type==BORDER_RAISED ? CMessage::Text(MSG_LIB_TEXT_BORDER_RAISED) :
      border_type==BORDER_SUNKEN ? CMessage::Text(MSG_LIB_TEXT_BORDER_SUNKEN) :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Функция, возвращающая описание типа стандартного графического объекта:

//+------------------------------------------------------------------+
//| Возвращает описание типа стандартного графического объекта       |
//+------------------------------------------------------------------+
string StdGraphObjectTypeDescription(const ENUM_OBJECT type)
  {
   return
     (
      type==OBJ_VLINE               ? CMessage::Text(MSG_GRAPH_STD_OBJ_VLINE)             :
      type==OBJ_HLINE               ? CMessage::Text(MSG_GRAPH_STD_OBJ_HLINE)             :
      type==OBJ_TREND               ? CMessage::Text(MSG_GRAPH_STD_OBJ_TREND)             :
      type==OBJ_TRENDBYANGLE        ? CMessage::Text(MSG_GRAPH_STD_OBJ_TRENDBYANGLE)      :
      type==OBJ_CYCLES              ? CMessage::Text(MSG_GRAPH_STD_OBJ_CYCLES)            :
      type==OBJ_ARROWED_LINE        ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROWED_LINE)      :
      type==OBJ_CHANNEL             ? CMessage::Text(MSG_GRAPH_STD_OBJ_CHANNEL)           :
      type==OBJ_STDDEVCHANNEL       ? CMessage::Text(MSG_GRAPH_STD_OBJ_STDDEVCHANNEL)     :
      type==OBJ_REGRESSION          ? CMessage::Text(MSG_GRAPH_STD_OBJ_REGRESSION)        :
      type==OBJ_PITCHFORK           ? CMessage::Text(MSG_GRAPH_STD_OBJ_PITCHFORK)         :
      type==OBJ_GANNLINE            ? CMessage::Text(MSG_GRAPH_STD_OBJ_GANNLINE)          :
      type==OBJ_GANNFAN             ? CMessage::Text(MSG_GRAPH_STD_OBJ_GANNFAN)           :
      type==OBJ_GANNGRID            ? CMessage::Text(MSG_GRAPH_STD_OBJ_GANNGRID)          :
      type==OBJ_FIBO                ? CMessage::Text(MSG_GRAPH_STD_OBJ_FIBO)              :
      type==OBJ_FIBOTIMES           ? CMessage::Text(MSG_GRAPH_STD_OBJ_FIBOTIMES)         :
      type==OBJ_FIBOFAN             ? CMessage::Text(MSG_GRAPH_STD_OBJ_FIBOFAN)           :
      type==OBJ_FIBOARC             ? CMessage::Text(MSG_GRAPH_STD_OBJ_FIBOARC)           :
      type==OBJ_FIBOCHANNEL         ? CMessage::Text(MSG_GRAPH_STD_OBJ_FIBOCHANNEL)       :
      type==OBJ_EXPANSION           ? CMessage::Text(MSG_GRAPH_STD_OBJ_EXPANSION)         :
      type==OBJ_ELLIOTWAVE5         ? CMessage::Text(MSG_GRAPH_STD_OBJ_ELLIOTWAVE5)       :
      type==OBJ_ELLIOTWAVE3         ? CMessage::Text(MSG_GRAPH_STD_OBJ_ELLIOTWAVE3)       :
      type==OBJ_RECTANGLE           ? CMessage::Text(MSG_GRAPH_STD_OBJ_RECTANGLE)         :
      type==OBJ_TRIANGLE            ? CMessage::Text(MSG_GRAPH_STD_OBJ_TRIANGLE)          :
      type==OBJ_ELLIPSE             ? CMessage::Text(MSG_GRAPH_STD_OBJ_ELLIPSE)           :
      type==OBJ_ARROW_THUMB_UP      ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_THUMB_UP)    :
      type==OBJ_ARROW_THUMB_DOWN    ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_THUMB_DOWN)  :
      type==OBJ_ARROW_UP            ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_UP)          :
      type==OBJ_ARROW_DOWN          ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_DOWN)        :
      type==OBJ_ARROW_STOP          ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_STOP)        :
      type==OBJ_ARROW_CHECK         ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_CHECK)       :
      type==OBJ_ARROW_LEFT_PRICE    ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_LEFT_PRICE)  :
      type==OBJ_ARROW_RIGHT_PRICE   ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_RIGHT_PRICE) :
      type==OBJ_ARROW_BUY           ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_BUY)         :
      type==OBJ_ARROW_SELL          ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW_SELL)        :
      type==OBJ_ARROW               ? CMessage::Text(MSG_GRAPH_STD_OBJ_ARROW)             :
      type==OBJ_TEXT                ? CMessage::Text(MSG_GRAPH_STD_OBJ_TEXT)              :
      type==OBJ_LABEL               ? CMessage::Text(MSG_GRAPH_STD_OBJ_LABEL)             :
      type==OBJ_BUTTON              ? CMessage::Text(MSG_GRAPH_STD_OBJ_BUTTON)            :
      type==OBJ_CHART               ? CMessage::Text(MSG_GRAPH_STD_OBJ_CHART)             :
      type==OBJ_BITMAP              ? CMessage::Text(MSG_GRAPH_STD_OBJ_BITMAP)            :
      type==OBJ_BITMAP_LABEL        ? CMessage::Text(MSG_GRAPH_STD_OBJ_BITMAP_LABEL)      :
      type==OBJ_EDIT                ? CMessage::Text(MSG_GRAPH_STD_OBJ_EDIT)              :
      type==OBJ_EVENT               ? CMessage::Text(MSG_GRAPH_STD_OBJ_EVENT)             :
      type==OBJ_RECTANGLE_LABEL     ? CMessage::Text(MSG_GRAPH_STD_OBJ_RECTANGLE_LABEL)   :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Как видим, в каждую функцию передаётся переменная, указывающая проверяемый функцией тип. А далее сравниваем переданный в функцию тип и возвращаем его описание при помощи метода Text() класса CMessage.

В файле \MQL5\Include\DoEasy\Objects\Indicators\Buffer.mqh класса абстрактного индикаторного буфера перепишем метод, возвращающий описание стиля линии отрисовки индикаторного буфера. Ранее этот метод имел точно такую же логику, как у только что добавленной функции LineStyleDescription(), и был таким:

//+------------------------------------------------------------------+
//| Возвращает описание стиля линии отрисовки                        |
//+------------------------------------------------------------------+
string CBuffer::GetLineStyleDescription(void) const
  {
   return
     (
      this.LineStyle()==STYLE_SOLID       ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_SOLID)      :
      this.LineStyle()==STYLE_DASH        ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASH)       :
      this.LineStyle()==STYLE_DOT         ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DOT)        :
      this.LineStyle()==STYLE_DASHDOT     ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOT)    :
      this.LineStyle()==STYLE_DASHDOTDOT  ? CMessage::Text(MSG_LIB_TEXT_BUFFER_TEXT_STYLE_DASHDOTDOT) :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Теперь же, раз мы уже имеем общую для всех классов библиотеки сервисную функцию, мы в этом методе просто вернём результат вызова этой функции:

//+------------------------------------------------------------------+
//| Возвращает описание стиля линии отрисовки                        |
//+------------------------------------------------------------------+
string CBuffer::GetLineStyleDescription(void) const
  {
   return LineStyleDescription(this.LineStyle());
  }
//+------------------------------------------------------------------+


Так как мы добавили всем графическим объектам большое количество новых свойств, некоторые из которых будут присущи всем графическим объектам библиотеки, то класс базового графического объекта библиотеки, от которого наследуются все объекты графики в библиотеке, в файле \MQL5\Include\DoEasy\Objects\Graph\GBaseObj.mqh, нам необходимо переработать.  Добавим к нему все необходимые — общие для всех графических объектов переменные, и создадим методы для установки и возврата значений этих переменных.

В защищённой секции класса объявим все необходимые переменные:

//+------------------------------------------------------------------+
//|                                                     GBaseObj.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "..\..\Services\DELib.mqh"
#include <Graphics\Graphic.mqh>
//+------------------------------------------------------------------+
//| Класс базового объекта графических объектов библиотеки           |
//+------------------------------------------------------------------+
class CGBaseObj : public CObject
  {
private:

protected:
   ENUM_OBJECT       m_type_graph_obj;                   // Тип графического объекта
   ENUM_GRAPH_ELEMENT_TYPE m_type_element;               // Тип графического элемента
   ENUM_GRAPH_OBJ_BELONG m_belong;                       // Принадлежность программе
   string            m_name_prefix;                      // Префикс имени объекта
   string            m_name;                             // Имя объекта
   long              m_chart_id;                         // Идентификатор графика объекта
   long              m_object_id;                        // Идентификатор объекта
   long              m_zorder;                           // Приоритет графического объекта на получение события нажатия мышки
   int               m_subwindow;                        // Номер подокна
   int               m_shift_y;                          // Смещение координаты Y для подокна
   int               m_type;                             // Тип объекта
   int               m_timeframes_visible;               // Видимость объекта на таймфреймах (набор флагов)
   int               m_digits;                           // Количество знаков после запятой в котировке символа чарта
   bool              m_visible;                          // Видимость объекта
   bool              m_back;                             // Флаг "Объект на заднем плане"
   bool              m_selected;                         // Флаг "Выделенность объекта"
   bool              m_selectable;                       // Флаг "Доступность объекта"
   bool              m_hidden;                           // Флаг "Запрет на показ имени графического объекта в списке объектов терминала"
   datetime          m_create_time;                      // Время создания объекта
   
//--- Создаёт (1) структуру объекта, (2) объект из структуры
   virtual bool      ObjectToStruct(void)                      { return true; }
   virtual void      StructToObject(void){;}

public:

В публичной секции класса напишем методы для установки свойств объекта, которые есть у каждого объекта графики библиотеки:

public:
//--- Установка значений переменных класса
   void              SetObjectID(const long value)             { this.m_object_id=value;           }
   void              SetBelong(const ENUM_GRAPH_OBJ_BELONG belong){ this.m_belong=belong;          }
   void              SetTypeGraphObject(const ENUM_OBJECT obj) { this.m_type_graph_obj=obj;        }
   void              SetTypeElement(const ENUM_GRAPH_ELEMENT_TYPE type) { this.m_type_element=type;}
   void              SetName(const string name)                { this.m_name=name;                 }
   void              SetChartID(const long chart_id)           { this.m_chart_id=chart_id;         }
   void              SetDigits(const int value)                { this.m_digits=value;              }

Значения указанных свойств объектов, устанавливаемых этими методами, хранятся только в этих переменных, поэтому достаточно в переменную вписать переданное в метод значение.

А вот те свойства, которые помимо того, что хранятся в переменных класса, ещё и прописываются в сам графический объект, их необходимо устанавливать иначе — сначала изменить значение свойства непосредственно у графического объекта, и лишь при удачном выполнении запроса вписать такое же значение и в переменную класса:

//--- Устанавливает флаг "Объект на заднем плане"
   bool              SetBack(const bool flag)
                       {
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_BACK,flag))
                          {
                           this.m_back=flag;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }

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

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


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

Исходя из этого, мы всё же пока оставим так, как сделано и будем эксплуатировать допущение, что команда на изменение свойств объекта успешно отработала. Если же в процессе использования библиотеки выявятся случаи неустановки свойств графическому объекту при уже установленном свойстве переменной класса, то добавим проверку на то, что свойство реально изменено у графического объекта.

Рассмотрим все аналогичные методы установки свойств графическому объекту и переменным, добавленные в публичную секцию класса:

//--- Устанавливает флаг "Объект на заднем плане"
   bool              SetBack(const bool flag)
                       {
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_BACK,flag))
                          {
                           this.m_back=flag;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Устанавливает флаг "Выделенность объекта"
   bool              SetSelected(const bool flag)
                       {
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_SELECTED,flag))
                          {
                           this.m_selected=flag;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Устанавливает флаг "Выделенность объекта"
   bool              SetSelectable(const bool flag)
                       {
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_SELECTABLE,flag))
                          {
                           this.m_selectable=flag;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Устанавливает флаг "Запрет на показ имени графического объекта в списке объектов терминала"
   bool              SetHidden(const bool flag)
                       {
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_SELECTABLE,flag))
                          {
                           this.m_hidden=flag;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Устанавливает Приоритет графического объекта на получение события нажатия мышки на графике 
   bool              SetZorder(const long value)
                       {
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_ZORDER,value))
                          {
                           this.m_zorder=value;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Устанавливает видимость/невидимость объекта на всех таймфреймах
   bool              SetVisible(const bool flag)   
                       {
                        long value=(flag ? OBJ_ALL_PERIODS : OBJ_NO_PERIODS);
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_TIMEFRAMES,value))
                          {
                           this.m_visible=flag;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Устанавливает флаги видимости на таймфреймах, записанных как флаги
   bool              SetVisibleOnTimeframe(const int flags)
                       {
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_TIMEFRAMES,flags))
                          {
                           this.m_timeframes_visible=flags;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Добавляет флаг видимости на указанном таймфрейме
   bool              SetVisibleOnTimeframe(const ENUM_TIMEFRAMES timeframe)
                       {
                        int flags=this.m_timeframes_visible;
                        switch(timeframe)
                          {
                           case PERIOD_M1    : flags |= OBJ_PERIOD_M1;  break;
                           case PERIOD_M2    : flags |= OBJ_PERIOD_M2;  break;
                           case PERIOD_M3    : flags |= OBJ_PERIOD_M3;  break;
                           case PERIOD_M4    : flags |= OBJ_PERIOD_M4;  break;
                           case PERIOD_M5    : flags |= OBJ_PERIOD_M5;  break;
                           case PERIOD_M6    : flags |= OBJ_PERIOD_M6;  break;
                           case PERIOD_M10   : flags |= OBJ_PERIOD_M10; break;
                           case PERIOD_M12   : flags |= OBJ_PERIOD_M12; break;
                           case PERIOD_M15   : flags |= OBJ_PERIOD_M15; break;
                           case PERIOD_M20   : flags |= OBJ_PERIOD_M20; break;
                           case PERIOD_M30   : flags |= OBJ_PERIOD_M30; break;
                           case PERIOD_H1    : flags |= OBJ_PERIOD_H1;  break;
                           case PERIOD_H2    : flags |= OBJ_PERIOD_H2;  break;
                           case PERIOD_H3    : flags |= OBJ_PERIOD_H3;  break;
                           case PERIOD_H4    : flags |= OBJ_PERIOD_H4;  break;
                           case PERIOD_H6    : flags |= OBJ_PERIOD_H6;  break;
                           case PERIOD_H8    : flags |= OBJ_PERIOD_H8;  break;
                           case PERIOD_H12   : flags |= OBJ_PERIOD_H12; break;
                           case PERIOD_D1    : flags |= OBJ_PERIOD_D1;  break;
                           case PERIOD_W1    : flags |= OBJ_PERIOD_W1;  break;
                           case PERIOD_MN1   : flags |= OBJ_PERIOD_MN1; break;
                           default           : return true;
                          }
                        ::ResetLastError();
                        if(::ObjectSetInteger(this.m_chart_id,this.m_name,OBJPROP_TIMEFRAMES,flags))
                          {
                           this.m_timeframes_visible=flags;
                           return true;
                          }
                        else
                           CMessage::ToLog(DFUN,::GetLastError(),true);
                        return false;
                       }
//--- Устанавливает номер подокна
   bool              SetSubwindow(const long chart_id,const string name)
                       {
                        ::ResetLastError();
                        this.m_subwindow=::ObjectFind(chart_id,name);
                        if(this.m_subwindow<0)
                           CMessage::ToLog(DFUN,MSG_GRAPH_STD_OBJ_ERR_NOT_FIND_SUBWINDOW);
                        return(this.m_subwindow>WRONG_VALUE);
                       }
   bool              SetSubwindow(void)
                       {
                        return this.SetSubwindow(this.m_chart_id,this.m_name);
                       }

//--- Возврат значений переменных класса

Далее впишем методы, возвращающие значения переменных класса:

//--- Возврат значений переменных класса
   ENUM_GRAPH_ELEMENT_TYPE TypeGraphElement(void)        const { return this.m_type_element;       }
   ENUM_GRAPH_OBJ_BELONG   Belong(void)                  const { return this.m_belong;             }
   ENUM_OBJECT       TypeGraphObject(void)               const { return this.m_type_graph_obj;     }
   datetime          TimeCreate(void)                    const { return this.m_create_time;        }
   string            Name(void)                          const { return this.m_name;               }
   long              ChartID(void)                       const { return this.m_chart_id;           }
   long              ObjectID(void)                      const { return this.m_object_id;          }
   long              Zorder(void)                        const { return this.m_zorder;             }
   int               SubWindow(void)                     const { return this.m_subwindow;          }
   int               ShiftY(void)                        const { return this.m_shift_y;            }
   int               VisibleOnTimeframes(void)           const { return this.m_timeframes_visible; }
   int               Digits(void)                        const { return this.m_digits;             }
   bool              IsBack(void)                        const { return this.m_back;               }
   bool              IsSelected(void)                    const { return this.m_selected;           }
   bool              IsSelectable(void)                  const { return this.m_selectable;         }
   bool              IsHidden(void)                      const { return this.m_hidden;             }
   bool              IsVisible(void)                     const { return this.m_visible;            }
//--- Возвращает флаг видимости объекта на указанном таймфрейме
   bool              IsVisibleOnTimeframe(const ENUM_TIMEFRAMES timeframe) const
                       { return((this.m_timeframes_visible & timeframe)==timeframe);               }
//--- Возвращает тип графического объекта (ENUM_OBJECT), рассчитанного из значения типа объекта (ENUM_OBJECT_DE_TYPE), переданного в метод
   ENUM_OBJECT       GraphObjectType(const ENUM_OBJECT_DE_TYPE obj_type) const
                       { 
                        return ENUM_OBJECT(obj_type-OBJECT_DE_TYPE_GSTD_OBJ-1);
                       }
   
//--- Возвращает описание типа графического объекта

Все методы возвращают значения, записанные в соответствующих переменных класса.

Метод GraphObjectType() рассчитывает тип графического объекта из значения типа объекта таким образом, чтобы из типа объекта, представленного типом перечисления ENUM_OBJECT_DE_TYPE библиотеки получить тип стандартного перечисления ENUM_OBJECT.

Далее объявим методы для возврата описаний типов объекта и его принадлежности:

//--- Возвращает описание типа графического (1) объекта, (2) элемента, (3) принадлежности графического объекта
string               TypeGraphObjectDescription(void);
string               TypeElementDescription(void);
string               BelongDescription(void);

//--- Виртуальный метод, возвращающий тип объекта
   virtual int       Type(void)                          const { return this.m_type;               }

//--- Конструктор/деструктор
                     CGBaseObj();
                    ~CGBaseObj(){;}
  };
//+------------------------------------------------------------------+

В конструкторе класса установим всем переменным класса их значения по умолчанию:

//+------------------------------------------------------------------+
//| Конструктор                                                      |
//+------------------------------------------------------------------+
CGBaseObj::CGBaseObj() : m_shift_y(0),m_visible(false), m_name_prefix(::MQLInfoString(MQL_PROGRAM_NAME)+"_"),m_belong(GRAPH_OBJ_BELONG_PROGRAM)
  {
   this.m_type=OBJECT_DE_TYPE_GBASE;            // Тип объекта
   this.m_type_graph_obj=WRONG_VALUE;           // Тип графического объекта
   this.m_type_element=WRONG_VALUE;             // Тип графического элемента
   this.m_belong=WRONG_VALUE;                   // Принадлежность программе/терминалу
   this.m_name_prefix="";                       // Префикс имени объекта
   this.m_name="";                              // Имя объекта
   this.m_chart_id=0;                           // Идентификатор графика объекта
   this.m_object_id=0;                          // Идентификатор объекта
   this.m_zorder=0;                             // Приоритет графического объекта на получение события нажатия мышки
   this.m_subwindow=0;                          // Номер подокна
   this.m_shift_y=0;                            // Смещение координаты Y для подокна
   this.m_timeframes_visible=OBJ_ALL_PERIODS;   // Видимость объекта на таймфреймах (набор флагов)
   this.m_visible=true;                         // Видимость объекта
   this.m_back=false;                           // Флаг "Объект на заднем плане"
   this.m_selected=false;                       // Флаг "Выделенность объекта"
   this.m_selectable=false;                     // Флаг "Доступность объекта"
   this.m_hidden=true;                          // Флаг "Запрет на показ имени графического объекта в списке объектов терминала"
   this.m_create_time=0;                        // Время создания объекта
   
  }
//+------------------------------------------------------------------+

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

Реализация метода, возвращающего описание типа графического объекта:

//+------------------------------------------------------------------+
//| Возвращает описание типа графического объекта                    |
//+------------------------------------------------------------------+
string CGBaseObj::TypeGraphObjectDescription(void)
  {
   if(this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_STANDART)
      return StdGraphObjectTypeDescription(this.m_type_graph_obj);
   else
      return this.TypeElementDescription();
  }
//+------------------------------------------------------------------+

Здесь мы сначала смотрим к какому типу графического элемента принадлежит графический объект, и если это стандартный графический объект, то возвращаем его описание при помощи сервисной функции StdGraphObjectTypeDescription(), написанной нами выше.
В ином случае — возвращаем описание типа графического элемента методом TypeElementDescription(), который рассмотрим ниже:

//+------------------------------------------------------------------+
//| Возвращает описание типа графического элемента                   |
//+------------------------------------------------------------------+
string CGBaseObj::TypeElementDescription(void)
  {
   return
     (
      this.TypeGraphElement()==GRAPH_ELEMENT_TYPE_STANDART     ? CMessage::Text(MSG_GRAPH_ELEMENT_TYPE_STANDART)     :
      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"
     );
  }
//+------------------------------------------------------------------+

Метод, возвращающий описание принадлежности графического объекта:

//+------------------------------------------------------------------+
//| Возвращает описание принадлежности графического объекта          |
//+------------------------------------------------------------------+
string CGBaseObj::BelongDescription(void)
  {
   return
     (
      this.Belong()==GRAPH_OBJ_BELONG_PROGRAM      ? CMessage::Text(MSG_GRAPH_OBJ_BELONG_PROGRAM)     :
      this.Belong()==GRAPH_OBJ_BELONG_NO_PROGRAM   ? CMessage::Text(MSG_GRAPH_OBJ_BELONG_NO_PROGRAM)  :
      "Unknown"
     );
  }
//+------------------------------------------------------------------+

Логика двух последних методов аналогична логике сервисных функций, рассмотренных нами выше.


Класс объекта абстрактного графического объекта

Все подготовительные этапы мы прошли. Теперь создадим класс абстрактного графического объекта.

В каталоге библиотеки \MQL5\Include\DoEasy\Objects\Graph\ создадим новую папку Standart\, а в ней новый файл GStdGraphObj.mqh класса CGStdGraphObj.

Класс должен быть унаследован от класса базового графического объекта всех графических объектов библиотеки CGBaseObj, файл которого также должен быть подключен к новому файлу создаваемого класса:

//+------------------------------------------------------------------+
//|                                                 GStdGraphObj.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "..\GBaseObj.mqh"
//+------------------------------------------------------------------+
//| Класс абстрактного стандартного графического объекта             |
//+------------------------------------------------------------------+
class CGStdGraphObj : public CGBaseObj
  {
  }

В приватной секции класса, как уже известно по множеству предыдущих статей, разместим массивы для хранения свойств объекта и методы для возврата реального индекса свойства в соответствующем ему массиве:

//+------------------------------------------------------------------+
//| Класс абстрактного стандартного графического объекта             |
//+------------------------------------------------------------------+
class CGStdGraphObj : public CGBaseObj
  {
private:

   long              m_long_prop[GRAPH_OBJ_PROP_INTEGER_TOTAL];      // Целочисленные свойства
   double            m_double_prop[GRAPH_OBJ_PROP_DOUBLE_TOTAL];     // Вещественные свойства
   string            m_string_prop[GRAPH_OBJ_PROP_STRING_TOTAL];     // Строковые свойства

//--- Возвращает индекс массива, по которому фактически расположено (1) double-свойство и (2) string-свойство
   int               IndexProp(ENUM_GRAPH_OBJ_PROP_DOUBLE property)  const { return(int)property-GRAPH_OBJ_PROP_INTEGER_TOTAL;                              }
   int               IndexProp(ENUM_GRAPH_OBJ_PROP_STRING property)  const { return(int)property-GRAPH_OBJ_PROP_INTEGER_TOTAL-GRAPH_OBJ_PROP_DOUBLE_TOTAL;  }

public:

В публичной секции класса расположим стандартные для всех объектов библиотеки методы и два конструктора — конструктор по умолчанию и закрытый параметрический:

public:
//--- Устанавливает (1) целочисленное, (2) вещественное и (3) строковое свойство объекта
   void              SetProperty(ENUM_GRAPH_OBJ_PROP_INTEGER property,long value)   { this.m_long_prop[property]=value;                      }
   void              SetProperty(ENUM_GRAPH_OBJ_PROP_DOUBLE property,double value)  { this.m_double_prop[this.IndexProp(property)]=value;    }
   void              SetProperty(ENUM_GRAPH_OBJ_PROP_STRING property,string value)  { this.m_string_prop[this.IndexProp(property)]=value;    }
//--- Возвращает из массива свойств (1) целочисленное, (2) вещественное и (3) строковое свойство объекта
   long              GetProperty(ENUM_GRAPH_OBJ_PROP_INTEGER property)        const { return this.m_long_prop[property];                     }
   double            GetProperty(ENUM_GRAPH_OBJ_PROP_DOUBLE property)         const { return this.m_double_prop[this.IndexProp(property)];   }
   string            GetProperty(ENUM_GRAPH_OBJ_PROP_STRING property)         const { return this.m_string_prop[this.IndexProp(property)];   }
//--- Возвращает себя
   CGStdGraphObj    *GetObject(void)                                                { return &this;}

//--- Возвращает флаг поддержания объектом данного свойства
   virtual bool      SupportProperty(ENUM_GRAPH_OBJ_PROP_INTEGER property)          { return true; }
   virtual bool      SupportProperty(ENUM_GRAPH_OBJ_PROP_DOUBLE property)           { return true; }
   virtual bool      SupportProperty(ENUM_GRAPH_OBJ_PROP_STRING property)           { return true; }

//--- Возвращает описание (1) целочисленного, (2) вещественного и (3) строкового свойства
   string            GetPropertyDescription(ENUM_GRAPH_OBJ_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_GRAPH_OBJ_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_GRAPH_OBJ_PROP_STRING property);

//--- Возвращает описание положения точки привязки графического объекта
   virtual string    AnchorDescription(void)                                  const { return (string)this.GetProperty(GRAPH_OBJ_PROP_ANCHOR);}

//--- Выводит в журнал описание свойств объекта (full_prop=true - все свойства, false - только поддерживаемые - реализуется в наследниках класса)
   virtual void      Print(const bool full_prop=false,const bool dash=false);
//--- Выводит в журнал краткое описание объекта
   virtual void      PrintShort(const bool dash=false,const bool symbol=false);
//--- Возвращает краткое наименование объекта
   virtual string    Header(const bool symbol=false);
  
//--- Сравнивает объекты CGStdGraphObj между собой по указанному свойству (для сортировки списка по свойству графического объекта)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Сравнивает объекты CGStdGraphObj между собой по всем свойствам (для поиска равных графических объектов)
   bool              IsEqual(CGStdGraphObj* compared_req) const;
   
//--- Конструктор по умолчанию
                     CGStdGraphObj(){ this.m_type=OBJECT_DE_TYPE_GSTD_OBJ;  }
protected:
//--- Защищённый параметрический конструктор
                     CGStdGraphObj(const ENUM_OBJECT_DE_TYPE obj_type,const ENUM_GRAPH_OBJ_BELONG belong,const long chart_id,const string name);
                     
public:
//+-------------------------------------------------------------------+ 
//|Методы упрощённого доступа и установки свойств графического объекта|
//+-------------------------------------------------------------------+

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

Далее по коду класса впишем методы для упрощённого доступа установки и возврата свойств объекта:

public:
//+-------------------------------------------------------------------+ 
//|Методы упрощённого доступа и установки свойств графического объекта|
//+-------------------------------------------------------------------+
//--- Номер объекта в списке
   int               Number(void)                  const { return (int)this.GetProperty(GRAPH_OBJ_PROP_NUM);                              }
   void              SetNumber(const int number)         { this.SetProperty(GRAPH_OBJ_PROP_NUM,number);                                   }
//--- Идентификатор объекта
   long              ObjectID(void)                const { return this.GetProperty(GRAPH_OBJ_PROP_ID);                                    }
   void              SetObjectID(const long obj_id)
                       {
                        CGBaseObj::SetObjectID(obj_id);
                        this.SetProperty(GRAPH_OBJ_PROP_ID,obj_id);
                       }
//--- Тип графичесеого объекта
   ENUM_OBJECT       GraphObjectType(void)         const { return (ENUM_OBJECT)this.GetProperty(GRAPH_OBJ_PROP_TYPE);                     }
   void              SetGraphObjectType(const ENUM_OBJECT obj_type)
                       {
                        CGBaseObj::SetTypeGraphObject(obj_type);
                        this.SetProperty(GRAPH_OBJ_PROP_TYPE,obj_type);
                       }
//---Тип графического элемента
   ENUM_GRAPH_ELEMENT_TYPE GraphElementType(void)  const { return (ENUM_GRAPH_ELEMENT_TYPE)this.GetProperty(GRAPH_OBJ_PROP_ELEMENT_TYPE); }
   void              SetGraphElementType(const ENUM_GRAPH_ELEMENT_TYPE elm_type)
                       {
                        CGBaseObj::SetTypeElement(elm_type);
                        this.SetProperty(GRAPH_OBJ_PROP_ELEMENT_TYPE,elm_type);
                       }
//--- Принадлежность графического объекта
   ENUM_GRAPH_OBJ_BELONG Belong(void)              const { return (ENUM_GRAPH_OBJ_BELONG)this.GetProperty(GRAPH_OBJ_PROP_BELONG);         }
   void              SetBelong(const ENUM_GRAPH_OBJ_BELONG belong)
                       {
                        CGBaseObj::SetBelong(belong);
                        this.SetProperty(GRAPH_OBJ_PROP_BELONG,belong);
                       }
//--- Идентификатор графика
   long              ChartID(void)                 const { return this.GetProperty(GRAPH_OBJ_PROP_CHART_ID);                              }
   void              SetChartID(const long chart_id)
                       {
                        CGBaseObj::SetChartID(chart_id);
                        this.SetProperty(GRAPH_OBJ_PROP_CHART_ID,chart_id);
                       }
//--- Номер подокна графика
   int               SubWindow(void)               const { return (int)this.GetProperty(GRAPH_OBJ_PROP_WND_NUM);                          }
   void              SetSubWindow(void)
                       {
                        if(CGBaseObj::SetSubwindow(CGBaseObj::ChartID(),CGBaseObj::Name()))
                           this.SetProperty(GRAPH_OBJ_PROP_WND_NUM,CGBaseObj::SubWindow());
                       }
//--- Время создания объекта
   datetime          TimeCteate(void)              const { return (datetime)this.GetProperty(GRAPH_OBJ_PROP_CREATETIME);                  }
//--- Видимость объекта на всех таймфреймах
   bool              Visible(void)                 const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_TIMEFRAMES);                      }
   void              SetFlagVisible(const bool flag)
                       {
                        if(CGBaseObj::SetVisible(flag))
                           this.SetProperty(GRAPH_OBJ_PROP_TIMEFRAMES,flag);
                       }
//--- Объект на заднем плане
   bool              Back(void)                    const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_BACK);                            }
   void              SetFlagBack(const bool flag)
                       {
                        if(CGBaseObj::SetBack(flag))
                           this.SetProperty(GRAPH_OBJ_PROP_BACK,flag);
                       }
//--- Приоритет графического объекта на получение события нажатия мышки на графике
   long              Zorder(void)                  const { return this.GetProperty(GRAPH_OBJ_PROP_ZORDER);                                }
   void              SetZorder(const long value)
                       {
                        if(CGBaseObj::SetZorder(value))
                           this.SetProperty(GRAPH_OBJ_PROP_ZORDER,value);
                       }
//--- Запрет на показ имени графического объекта в списке объектов терминала
   bool              Hidden(void)                  const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_HIDDEN);                          }
   void              SetFlagHidden(const bool flag)
                       {
                        if(CGBaseObj::SetHidden(flag))
                           this.SetProperty(GRAPH_OBJ_PROP_HIDDEN,flag);
                       }
//--- Выделенность объекта
   bool              Selected(void)                const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTED);                        }
   void              SetFlagSelected(const bool flag)
                       {
                        if(CGBaseObj::SetSelected(flag))
                           this.SetProperty(GRAPH_OBJ_PROP_SELECTED,flag);
                       }
//--- Доступность объекта
   bool              Selectable(void)              const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTABLE);                      }
   void              SetFlagSelectable(const bool flag)
                       {
                        if(CGBaseObj::SetSelectable(flag))
                           this.SetProperty(GRAPH_OBJ_PROP_SELECTABLE,flag);
                       }
//--- Координата времени
   datetime          Time(void)                    const { return (datetime)this.GetProperty(GRAPH_OBJ_PROP_TIME);                        }
   void              SetTime(const datetime time)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_TIME,time))
                           this.SetProperty(GRAPH_OBJ_PROP_TIME,time);
                       }
//--- Цвет
   color             Color(void)                   const { return (color)this.GetProperty(GRAPH_OBJ_PROP_COLOR);                          }
   void              SetColor(const color colour)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_COLOR,colour))
                           this.SetProperty(GRAPH_OBJ_PROP_COLOR,colour);
                       }
//--- Стиль
   ENUM_LINE_STYLE   Style(void)                   const { return (ENUM_LINE_STYLE)this.GetProperty(GRAPH_OBJ_PROP_STYLE);                }
   void              SetStyle(const ENUM_LINE_STYLE style)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_STYLE,style))
                           this.SetProperty(GRAPH_OBJ_PROP_STYLE,style);
                       }
//--- Толщина линии
   int               Width(void)                   const { return (int)this.GetProperty(GRAPH_OBJ_PROP_WIDTH);                            }
   void              SetWidth(const int width)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_WIDTH,width))
                           this.SetProperty(GRAPH_OBJ_PROP_WIDTH,width);
                       }
//--- Заливка объекта цветом
   bool              Fill(void)                    const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_FILL);                            }
   void              SetFlagFill(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_FILL,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_FILL,flag);
                       }
//--- Возможность редактирования текста в объекте Edit
   bool              ReadOnly(void)                const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_READONLY);                        }
   void              SetFlagReadOnly(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_READONLY,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_READONLY,flag);
                       }
//--- Количество уровней
   int               Levels(void)                  const { return (int)this.GetProperty(GRAPH_OBJ_PROP_LEVELS);                           }
   void              SetLevels(const int levels)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELS,levels))
                           this.SetProperty(GRAPH_OBJ_PROP_LEVELS,levels);
                       }
//--- Цвет линии-уровня
   color             LevelColor(void)              const { return (color)this.GetProperty(GRAPH_OBJ_PROP_LEVELCOLOR);                     }
   void              SetLevelColor(const color colour)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELCOLOR,colour))
                           this.SetProperty(GRAPH_OBJ_PROP_LEVELCOLOR,colour);
                       }
//--- Стиль линии-уровня
   ENUM_LINE_STYLE   LevelStyle(void)              const { return (ENUM_LINE_STYLE)this.GetProperty(GRAPH_OBJ_PROP_LEVELSTYLE);           }
   void              SetLevelStyle(const ENUM_LINE_STYLE style)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELSTYLE,style))
                           this.SetProperty(GRAPH_OBJ_PROP_LEVELSTYLE,style);
                       }
///--- Толщина линии-уровня
   int               LevelWidth(void)              const { return (int)this.GetProperty(GRAPH_OBJ_PROP_LEVELWIDTH);                       }
   void              SetLevelWidth(const int width)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELWIDTH,width))
                           this.SetProperty(GRAPH_OBJ_PROP_LEVELWIDTH,width);
                       }
//--- Горизонтальное выравнивание текста в объекте "Поле ввода" (OBJ_EDIT)
   ENUM_ALIGN_MODE   Align(void)                   const { return (ENUM_ALIGN_MODE)this.GetProperty(GRAPH_OBJ_PROP_ALIGN);                }
   void              SetAlign(const ENUM_ALIGN_MODE align)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ALIGN,align))
                           this.SetProperty(GRAPH_OBJ_PROP_ALIGN,align);
                       }
//--- Размер шрифта
   int               FontSize(void)                const { return (int)this.GetProperty(GRAPH_OBJ_PROP_FONTSIZE);                         }
   void              SetFontSize(const int size)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_FONTSIZE,size))
                           this.SetProperty(GRAPH_OBJ_PROP_FONTSIZE,size);
                       }
//--- Луч продолжается влево
   bool              RayLeft(void)                 const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_RAY_LEFT);                        }
   void              SetFlagRayLeft(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_RAY_LEFT,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_RAY_LEFT,flag);
                       }
//--- Луч продолжается вправо
   bool              RayRight(void)                const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_RAY_RIGHT);                       }
   void              SetFlagRayRight(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_RAY_RIGHT,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_RAY_RIGHT,flag);
                       }
//--- Вертикальная линия продолжается на все окна графика
   bool              Ray(void)                     const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_RAY);                             }
   void              SetFlagRay(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_RAY,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_RAY,flag);
                       }
//--- Отображение полного эллипса для объекта "Дуги Фибоначчи"
   bool              Ellipse(void)                 const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_ELLIPSE);                         }
   void              SetFlagEllipse(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ELLIPSE,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_ELLIPSE,flag);
                       }
//--- Код стрелки для объекта "Стрелка"
   uchar             ArrowCode(void)               const { return (uchar)this.GetProperty(GRAPH_OBJ_PROP_ARROWCODE);                      }
   void              SetArrowCode(const uchar code)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ARROWCODE,code))
                           this.SetProperty(GRAPH_OBJ_PROP_ARROWCODE,code);
                       }
//--- Положение точки привязки графического объекта
   int               Anchor(void)                  const { return (int)this.GetProperty(GRAPH_OBJ_PROP_ANCHOR);                           }
   void              SetAnchor(const int anchor)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ANCHOR,anchor))
                           this.SetProperty(GRAPH_OBJ_PROP_ANCHOR,anchor);
                       }
//--- Дистанция в пикселях по оси X от угла привязки
   int               XDistance(void)               const { return (int)this.GetProperty(GRAPH_OBJ_PROP_XDISTANCE);                        }
   void              SetXDistance(const int distance)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_XDISTANCE,distance))
                           this.SetProperty(GRAPH_OBJ_PROP_XDISTANCE,distance);
                       }
//--- Дистанция в пикселях по оси Y от угла привязки
   int               YDistance(void)               const { return (int)this.GetProperty(GRAPH_OBJ_PROP_YDISTANCE);                        }
   void              SetYDistance(const int distance)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_YDISTANCE,distance))
                           this.SetProperty(GRAPH_OBJ_PROP_YDISTANCE,distance);
                       }
//--- Тренд объекта Ганна
   ENUM_GANN_DIRECTION Direction(void)             const { return (ENUM_GANN_DIRECTION)this.GetProperty(GRAPH_OBJ_PROP_DIRECTION);        }
   void              SetDirection(const ENUM_GANN_DIRECTION direction)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DIRECTION,direction))
                           this.SetProperty(GRAPH_OBJ_PROP_DIRECTION,direction);
                       }
//--- Уровень волновой разметки Эллиотта
   ENUM_ELLIOT_WAVE_DEGREE Degree(void)            const { return (ENUM_ELLIOT_WAVE_DEGREE)this.GetProperty(GRAPH_OBJ_PROP_DEGREE);       }
   void              SetDegree(const ENUM_ELLIOT_WAVE_DEGREE degree)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DEGREE,degree))
                           this.SetProperty(GRAPH_OBJ_PROP_DEGREE,degree);
                       }
//--- Отображение линий для волновой разметки Эллиотта
   bool              DrawLines(void)               const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_DRAWLINES);                       }
   void              SetFlagDrawLines(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DRAWLINES,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_DRAWLINES,flag);
                       }
//--- Состояние кнопки (Нажата/Отжата)
   bool              State(void)                   const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_STATE);                           }
   void              SetFlagState(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_STATE,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_STATE,flag);
                       }
//--- Идентификатор объекта "График" (OBJ_CHART)
   long              ChartObjChartID(void)         const { return this.GetProperty(GRAPH_OBJ_PROP_OBJ_CHART_ID);                          }
   void              SetChartObjChartID(const long chart_id)
                       {
                        this.SetProperty(GRAPH_OBJ_PROP_OBJ_CHART_ID,chart_id);
                       }
//--- Период для объекта "График"
   ENUM_TIMEFRAMES   ChartObjPeriod(void)          const { return (ENUM_TIMEFRAMES)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PERIOD);     }
   void              SetChartObjPeriod(const ENUM_TIMEFRAMES timeframe)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_PERIOD,timeframe))
                           this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PERIOD,timeframe);
                       }
//--- Признак отображения шкалы времени для объекта "График"
   bool              ChartObjDateScale(void)       const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE);            }
   void              SetFlagChartObjDateScale(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DATE_SCALE,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE,flag);
                       }
//--- Признак отображения ценовой шкалы для объекта "График"
   bool              ChartObjPriceScale(void)      const { return (bool)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE);           }
   void              SetFlagPriceScale(const bool flag)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_PRICE_SCALE,flag))
                           this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE,flag);
                       }
//--- Масштаб для объекта "График"
   int               ChartObjChartScale(void)      const { return (int)this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE);            }
   void              SetChartObjChartScale(const int scale)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_CHART_SCALE,scale))
                           this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE,scale);
                       }
//--- Ширина объекта по оси X в пикселях
   int               XSize(void)                   const { return (int)this.GetProperty(GRAPH_OBJ_PROP_XSIZE);                            }
   void              SetXSize(const int size)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_XSIZE,size))
                           this.SetProperty(GRAPH_OBJ_PROP_XSIZE,size);
                       }
//--- Высота объекта по оси Y в пикселях
   int               YSize(void)                   const { return (int)this.GetProperty(GRAPH_OBJ_PROP_YSIZE);                            }
   void              SetYSize(const int size)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_YSIZE,size))
                           this.SetProperty(GRAPH_OBJ_PROP_YSIZE,size);
                       }
//--- X-координата левого верхнего угла прямоугольной области видимости
   int               XOffset(void)                 const { return (int)this.GetProperty(GRAPH_OBJ_PROP_XOFFSET);                          }
   void              SetXOffset(const int offset)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_XOFFSET,offset))
                           this.SetProperty(GRAPH_OBJ_PROP_XOFFSET,offset);
                       }
//--- Y-координата левого верхнего угла прямоугольной области видимости
   int               YOffset(void)                 const { return (int)this.GetProperty(GRAPH_OBJ_PROP_YOFFSET);                          }
   void              SetYOffset(const int offset)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_YOFFSET,offset))
                           this.SetProperty(GRAPH_OBJ_PROP_YOFFSET,offset);
                       }
//--- Цвет фона для OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
   color             BGColor(void)                 const { return (color)this.GetProperty(GRAPH_OBJ_PROP_BGCOLOR);                        }
   void              SetBGColor(const color colour)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BGCOLOR,colour))
                           this.SetProperty(GRAPH_OBJ_PROP_BGCOLOR,colour);
                       }
//--- Угол графика для привязки графического объекта
   ENUM_BASE_CORNER  Corner(void)                  const { return (ENUM_BASE_CORNER)this.GetProperty(GRAPH_OBJ_PROP_CORNER);              }
   void              SetCorner(const ENUM_BASE_CORNER corner)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_CORNER,corner))
                           this.SetProperty(GRAPH_OBJ_PROP_CORNER,corner);
                       }
//--- Тип рамки для объекта "Прямоугольная рамка"
   ENUM_BORDER_TYPE  BorderType(void)              const { return (ENUM_BORDER_TYPE)this.GetProperty(GRAPH_OBJ_PROP_BORDER_TYPE);         }
   void              SetBorderType(const ENUM_BORDER_TYPE type)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BORDER_TYPE,type))
                           this.SetProperty(GRAPH_OBJ_PROP_BORDER_TYPE,type);
                       }
//--- Цвет рамки для объекта OBJ_EDIT и OBJ_BUTTON
   color             BorderColor(void)             const { return (color)this.GetProperty(GRAPH_OBJ_PROP_BORDER_COLOR);                   }
   void              SetBorderColor(const color colour)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BORDER_COLOR,colour))
                           this.SetProperty(GRAPH_OBJ_PROP_BORDER_COLOR,colour);
                       }

//--- Координата цены
   double            Price(void)                   const { return this.GetProperty(GRAPH_OBJ_PROP_PRICE);                                 }
   void              SetPrice(const double price)
                       {
                        if(::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_PRICE,price))
                           this.SetProperty(GRAPH_OBJ_PROP_PRICE,price);
                       }
//--- Значение уровня
   double            LevelValue(void)              const { return this.GetProperty(GRAPH_OBJ_PROP_LEVELVALUE);                            }
   void              SetLevelValue(const double value)
                       {
                        if(::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELVALUE,value))
                           this.SetProperty(GRAPH_OBJ_PROP_LEVELVALUE,value);
                       }
//--- Масштаб
   double            Scale(void)                   const { return this.GetProperty(GRAPH_OBJ_PROP_SCALE);                                 }
   void              SetScale(const double scale)
                       {
                        if(::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_SCALE,scale))
                           this.SetProperty(GRAPH_OBJ_PROP_SCALE,scale);
                       }
//--- Угол
   double            Angle(void)                   const { return this.GetProperty(GRAPH_OBJ_PROP_ANGLE);                                 }
   void              SetAngle(const double angle)
                       {
                        if(::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_ANGLE,angle))
                           this.SetProperty(GRAPH_OBJ_PROP_ANGLE,angle);
                       }
//--- Отклонение для канала стандартного отклонения
   double            Deviation(void)               const { return this.GetProperty(GRAPH_OBJ_PROP_DEVIATION);                             }
   void              SetDeviation(const double deviation)
                       {
                        if(::ObjectSetDouble(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_DEVIATION,deviation))
                           this.SetProperty(GRAPH_OBJ_PROP_DEVIATION,deviation);
                       }

//--- Имя объекта
   string            Name(void)                    const { return this.GetProperty(GRAPH_OBJ_PROP_NAME);                                  }
   void              SetName(const string name)
                       {
                        if(CGBaseObj::Name()==name)
                           return;
                        if(CGBaseObj::Name()=="")
                          {
                           CGBaseObj::SetName(name);
                           this.SetProperty(GRAPH_OBJ_PROP_NAME,name);
                           return;
                          }
                        else
                          {
                           if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_NAME,name))
                             {
                              CGBaseObj::SetName(name);
                              this.SetProperty(GRAPH_OBJ_PROP_NAME,name);
                             }
                          }
                       }
//--- Описание объекта (текст, содержащийся в объекте)
   string            Text(void)                    const { return this.GetProperty(GRAPH_OBJ_PROP_TEXT);                                  }
   void              SetText(const string text)
                       {
                        if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_TEXT,text))
                           this.SetProperty(GRAPH_OBJ_PROP_TEXT,text);
                       }
//--- Текст всплывающей подсказки
   string            Tooltip(void)                 const { return this.GetProperty(GRAPH_OBJ_PROP_TOOLTIP);                               }
   void              SetTooltip(const string tooltip)
                       {
                        if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_TOOLTIP,tooltip))
                           this.SetProperty(GRAPH_OBJ_PROP_TOOLTIP,tooltip);
                       }
//--- Описание уровня
   string            LevelText(void)               const { return this.GetProperty(GRAPH_OBJ_PROP_LEVELTEXT);                             }
   void              SetLevelText(const string text)
                       {
                        if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_LEVELTEXT,text))
                           this.SetProperty(GRAPH_OBJ_PROP_LEVELTEXT,text);
                       }
//--- Шрифт
   string            Font(void)                    const { return this.GetProperty(GRAPH_OBJ_PROP_FONT);                                  }
   void              SetFont(const string font)
                       {
                        if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_FONT,font))
                           this.SetProperty(GRAPH_OBJ_PROP_FONT,font);
                       }
//--- Имя BMP-файла для объекта "Графическая метка"
   string            BMPFile(void)                 const { return this.GetProperty(GRAPH_OBJ_PROP_BMPFILE);                               }
   void              SetBMPFile(const string bmp_file)
                       {
                        if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_BMPFILE,bmp_file))
                           this.SetProperty(GRAPH_OBJ_PROP_BMPFILE,bmp_file);
                       }
//--- Символ для объекта "График" 
   string            Symbol(void)                  const { return this.GetProperty(GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL);                      }
   void              SetChartObjSymbol(const string symbol)
                       {
                        if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_SYMBOL,symbol))
                           this.SetProperty(GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL,symbol);
                       }
   
  };
//+------------------------------------------------------------------+

Многие методы здесь написаны заранее, и они впоследствии будут перемещены в классы объектов-наследников, где есть соответствующие свойства у графических объектов, которые будут описывать эти классы. Это нам даст то, что у разных объектов будут разные, присущие только им, наборы методов для работы со свойствами.

Рассмотрим логику на примере нескольких методов.

Те свойства объекта, которые есть только у самого объекта, возвращаются и устанавливаются непосредственно из свойств объекта:

//--- Номер объекта в списке
   int               Number(void)                  const { return (int)this.GetProperty(GRAPH_OBJ_PROP_NUM);                              }
   void              SetNumber(const int number)         { this.SetProperty(GRAPH_OBJ_PROP_NUM,number);                                   }


Свойства объекта, присущие всем графическим объектам, переменные для хранения которых находятся в классе базового графического объекта всех графических объектов библиотеки, возвращаются из свойств данного объекта, а устанавливаются сначала в базовый объект, а затем и в свойства этого объекта:

//--- Идентификатор объекта
   long              ObjectID(void)                const { return this.GetProperty(GRAPH_OBJ_PROP_ID);                                    }
   void              SetObjectID(const long obj_id)
                       {
                        CGBaseObj::SetObjectID(obj_id);
                        this.SetProperty(GRAPH_OBJ_PROP_ID,obj_id);
                       }


Свойства объекта, которые есть у самого графического объекта, но их нет в базовом объекте, возвращаются непосредственно из свойств данного объекта,
а устанавливаются сначала в свойства самого графического объекта, а затем, при успешной постановке события изменения свойства в очередьпрописываются и в свойства данного объекта:

//--- Координата времени
   datetime          Time(void)                    const { return (datetime)this.GetProperty(GRAPH_OBJ_PROP_TIME);                        }
   void              SetTime(const datetime time)
                       {
                        if(::ObjectSetInteger(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_TIME,time))
                           this.SetProperty(GRAPH_OBJ_PROP_TIME,time);
                       }


Метод установки имени отличается от других подобных методов. Дело в том, что графические объекты в терминале выбираются по индексу в списке и по имени объекта (функцией ObjectName() мы получаем имя объекта по индексу в списке объектов, а функциями ObjectGetXXX() мы затем получаем остальные свойства уже по имени графического объекта), и имя объекта ему присваивается сразу же при его создании.

Соответственно, здесь нам нужно установить имя только лишь в переменные объектов. И это мы делаем в том случае, если имя в переменную ещё не записано. Если же имя уже записано в переменную, и имя для установки не равно уже имеющемуся имени (при равных именах мы уходим из метода), то это означает переименование объекта. Здесь пока такая ситуация не обрабатывается — будем делать в дальнейшем, а пока просто отправляем запрос на переименование графического объекта и перезаписываем его имя в переменной базового класса и в свойствах этого.
//--- Имя объекта
   string            Name(void)                    const { return this.GetProperty(GRAPH_OBJ_PROP_NAME);                                  }
   void              SetName(const string name)
                       {
                        if(CGBaseObj::Name()==name)
                           return;
                        if(CGBaseObj::Name()=="")
                          {
                           CGBaseObj::SetName(name);
                           this.SetProperty(GRAPH_OBJ_PROP_NAME,name);
                           return;
                          }
                        else
                          {
                           if(::ObjectSetString(CGBaseObj::ChartID(),CGBaseObj::Name(),OBJPROP_NAME,name))
                             {
                              CGBaseObj::SetName(name);
                              this.SetProperty(GRAPH_OBJ_PROP_NAME,name);
                             }
                          }
                       }


В защищённом параметрическом конструкторе запишем все переданные в конструктор значения — в базовый класс и в свойства данного объекта:

//+------------------------------------------------------------------+
//| Защищённый параметрический конструктор                           |
//+------------------------------------------------------------------+
CGStdGraphObj::CGStdGraphObj(const ENUM_OBJECT_DE_TYPE obj_type,const ENUM_GRAPH_OBJ_BELONG belong,const long chart_id,const string name)
  {
//--- Устанавливаем объекту (1) его тип, тип графического (2) объекта, (3) елемента, (4) принадлежность и (5) номер подокна, (6) Digits символа графика
   this.m_type=obj_type;
   CGBaseObj::SetChartID(chart_id);
   CGBaseObj::SetTypeGraphObject(CGBaseObj::GraphObjectType(obj_type));
   CGBaseObj::SetTypeElement(GRAPH_ELEMENT_TYPE_STANDART);
   CGBaseObj::SetBelong(belong);
   CGBaseObj::SetSubwindow(chart_id,name);
   CGBaseObj::SetDigits((int)::SymbolInfoInteger(::ChartSymbol(chart_id),SYMBOL_DIGITS));
   
//--- Сохранение целочисленных свойств
   //--- свойства, присущие всем графическим объектам, но не имеющиеся у графического объекта
   this.m_long_prop[GRAPH_OBJ_PROP_CHART_ID]    = CGBaseObj::ChartID();          // Идентификатор графика

   this.m_long_prop[GRAPH_OBJ_PROP_WND_NUM]     = CGBaseObj::SubWindow();        // Номер подокна графика
   this.m_long_prop[GRAPH_OBJ_PROP_TYPE]        = CGBaseObj::TypeGraphObject();  // Тип графического объекта (ENUM_OBJECT)
   this.m_long_prop[GRAPH_OBJ_PROP_ELEMENT_TYPE]= CGBaseObj::TypeGraphElement(); // Тип графического элемента (ENUM_GRAPH_ELEMENT_TYPE)
   this.m_long_prop[GRAPH_OBJ_PROP_BELONG]      = CGBaseObj::Belong();           // Принадлежность графического объекта
   this.m_long_prop[GRAPH_OBJ_PROP_ID]          = 0;                             // Идентификатор объекта
   this.m_long_prop[GRAPH_OBJ_PROP_NUM]         = 0;                             // Номер объекта в списке
   //--- Свойства, присущие всем графическим объектам, имеющиеся у графического объекта
   this.m_long_prop[GRAPH_OBJ_PROP_CREATETIME]  = ::ObjectGetInteger(chart_id,name,OBJPROP_CREATETIME);  // Время создания объекта
   this.m_long_prop[GRAPH_OBJ_PROP_TIMEFRAMES]  = ::ObjectGetInteger(chart_id,name,OBJPROP_TIMEFRAMES);  // Видимость объекта на таймфреймах
   this.m_long_prop[GRAPH_OBJ_PROP_BACK]        = ::ObjectGetInteger(chart_id,name,OBJPROP_BACK);        // Объект на заднем плане
   this.m_long_prop[GRAPH_OBJ_PROP_ZORDER]      = ::ObjectGetInteger(chart_id,name,OBJPROP_ZORDER);      // Приоритет графического объекта на получение события нажатия мышки на графике
   this.m_long_prop[GRAPH_OBJ_PROP_HIDDEN]      = ::ObjectGetInteger(chart_id,name,OBJPROP_HIDDEN);      // Запрет на показ имени графического объекта в списке объектов терминала
   this.m_long_prop[GRAPH_OBJ_PROP_SELECTED]    = ::ObjectGetInteger(chart_id,name,OBJPROP_SELECTED);    // Выделенность объекта
   this.m_long_prop[GRAPH_OBJ_PROP_SELECTABLE]  = ::ObjectGetInteger(chart_id,name,OBJPROP_SELECTABLE);  // Доступность объекта
   this.m_long_prop[GRAPH_OBJ_PROP_TIME]        = ::ObjectGetInteger(chart_id,name,OBJPROP_TIME);        // Координата времени первой точки
   this.m_long_prop[GRAPH_OBJ_PROP_COLOR]       = ::ObjectGetInteger(chart_id,name,OBJPROP_COLOR);       // Цвет
   this.m_long_prop[GRAPH_OBJ_PROP_STYLE]       = ::ObjectGetInteger(chart_id,name,OBJPROP_STYLE);       // Стиль
   this.m_long_prop[GRAPH_OBJ_PROP_WIDTH]       = ::ObjectGetInteger(chart_id,name,OBJPROP_WIDTH);       // Толщина линии
   //--- Свойства, принадлежащие разным графическим объектам
   this.m_long_prop[GRAPH_OBJ_PROP_FILL]                          = 0;  // Заливка объекта цветом
   this.m_long_prop[GRAPH_OBJ_PROP_READONLY]                      = 0;  // Возможность редактирования текста в объекте Edit
   this.m_long_prop[GRAPH_OBJ_PROP_LEVELS]                        = 0;  // Количество уровней
   this.m_long_prop[GRAPH_OBJ_PROP_LEVELCOLOR]                    = 0;  // Цвет линии-уровня
   this.m_long_prop[GRAPH_OBJ_PROP_LEVELSTYLE]                    = 0;  // Стиль линии-уровня
   this.m_long_prop[GRAPH_OBJ_PROP_LEVELWIDTH]                    = 0;  // Толщина линии-уровня
   this.m_long_prop[GRAPH_OBJ_PROP_ALIGN]                         = 0;  // Горизонтальное выравнивание текста в объекте "Поле ввода" (OBJ_EDIT)
   this.m_long_prop[GRAPH_OBJ_PROP_FONTSIZE]                      = 0;  // Размер шрифта
   this.m_long_prop[GRAPH_OBJ_PROP_RAY_LEFT]                      = 0;  // Луч продолжается влево
   this.m_long_prop[GRAPH_OBJ_PROP_RAY_RIGHT]                     = 0;  // Луч продолжается вправо
   this.m_long_prop[GRAPH_OBJ_PROP_RAY]                           = 0;  // Вертикальная линия продолжается на все окна графика
   this.m_long_prop[GRAPH_OBJ_PROP_ELLIPSE]                       = 0;  // Отображение полного эллипса для объекта "Дуги Фибоначчи"
   this.m_long_prop[GRAPH_OBJ_PROP_ARROWCODE]                     = 0;  // Код стрелки для объекта "Стрелка"
   this.m_long_prop[GRAPH_OBJ_PROP_ANCHOR]                        = 0;  // Положение точки привязки графического объекта
   this.m_long_prop[GRAPH_OBJ_PROP_XDISTANCE]                     = 0;  // Дистанция в пикселях по оси X от угла привязки
   this.m_long_prop[GRAPH_OBJ_PROP_YDISTANCE]                     = 0;  // Дистанция в пикселях по оси Y от угла привязки
   this.m_long_prop[GRAPH_OBJ_PROP_DIRECTION]                     = 0;  // Тренд объекта Ганна
   this.m_long_prop[GRAPH_OBJ_PROP_DEGREE]                        = 0;  // Уровень волновой разметки Эллиотта
   this.m_long_prop[GRAPH_OBJ_PROP_DRAWLINES]                     = 0;  // Отображение линий для волновой разметки Эллиотта
   this.m_long_prop[GRAPH_OBJ_PROP_STATE]                         = 0;  // Состояние кнопки (Нажата/Отжата)
   this.m_long_prop[GRAPH_OBJ_PROP_OBJ_CHART_ID]                  = 0;  // Идентификатор объекта "График" (OBJ_CHART).
   this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_PERIOD]              = 0;  // Период для объекта "График"
   this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_DATE_SCALE]          = 0;  // Признак отображения шкалы времени для объекта "График"
   this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_PRICE_SCALE]         = 0;  // Признак отображения ценовой шкалы для объекта "График"
   this.m_long_prop[GRAPH_OBJ_PROP_CHART_OBJ_CHART_SCALE]         = 0;  // Масштаб для объекта "График"
   this.m_long_prop[GRAPH_OBJ_PROP_XSIZE]                         = 0;  // Ширина объекта по оси X в пикселях.
   this.m_long_prop[GRAPH_OBJ_PROP_YSIZE]                         = 0;  // Высота объекта по оси Y в пикселях.
   this.m_long_prop[GRAPH_OBJ_PROP_XOFFSET]                       = 0;  // X-координата левого верхнего угла прямоугольной области видимости.
   this.m_long_prop[GRAPH_OBJ_PROP_YOFFSET]                       = 0;  // Y-координата левого верхнего угла прямоугольной области видимости.
   this.m_long_prop[GRAPH_OBJ_PROP_BGCOLOR]                       = 0;  // Цвет фона для OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
   this.m_long_prop[GRAPH_OBJ_PROP_CORNER]                        = 0;  // Угол графика для привязки графического объекта
   this.m_long_prop[GRAPH_OBJ_PROP_BORDER_TYPE]                   = 0;  // Тип рамки для объекта "Прямоугольная рамка"
   this.m_long_prop[GRAPH_OBJ_PROP_BORDER_COLOR]                  = 0;  // Цвет рамки для объекта OBJ_EDIT и OBJ_BUTTON
   
//--- Сохранение вещественных свойств
   this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_PRICE)]       = ::ObjectGetDouble(chart_id,name,OBJPROP_PRICE);  // Координата цены
   this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_LEVELVALUE)]  = 0;                                               // Значение уровня
   this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_SCALE)]       = 0;                                               // Масштаб (свойство объектов Ганна и объекта "Дуги Фибоначчи")
   this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_ANGLE)]       = 0;                                               // Угол
   this.m_double_prop[this.IndexProp(GRAPH_OBJ_PROP_DEVIATION)]   = 0;                                               // Отклонение для канала стандартного отклонения
   
//--- Сохранение строковых свойств
   this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_NAME)]        = name;                                            // Имя объекта
   this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_TEXT)]        = ::ObjectGetString(chart_id,name,OBJPROP_TEXT);   // Описание объекта (текст, содержащийся в объекте)
   this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_TOOLTIP)]     = ::ObjectGetString(chart_id,name,OBJPROP_TOOLTIP);// Текст всплывающей подсказки
   this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_LEVELTEXT)]   = "";                                              // Описание уровня
   this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_FONT)]        = "";                                              // Шрифт
   this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_BMPFILE)]     = "";                                              // Имя BMP-файла для объекта "Графическая метка"
   this.m_string_prop[this.IndexProp(GRAPH_OBJ_PROP_CHART_OBJ_SYMBOL)]= "";                                          // Символ для объекта "График" 
   
//--- Сохранение базовых свойств в родительском объекте
   this.m_create_time=(datetime)this.GetProperty(GRAPH_OBJ_PROP_CREATETIME);
   this.m_back=(bool)this.GetProperty(GRAPH_OBJ_PROP_BACK);
   this.m_selected=(bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTED);
   this.m_selectable=(bool)this.GetProperty(GRAPH_OBJ_PROP_SELECTABLE);
   this.m_hidden=(bool)this.GetProperty(GRAPH_OBJ_PROP_HIDDEN);
   this.m_name=this.GetProperty(GRAPH_OBJ_PROP_NAME);
   
  }
//+-------------------------------------------------------------------+

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

Стандартные для объектов библиотеки методы сравнения двух объектов:

//+-------------------------------------------------------------------+
//|Сравнивает объекты CGStdGraphObj между собой по указанному свойству|
//+-------------------------------------------------------------------+
int CGStdGraphObj::Compare(const CObject *node,const int mode=0) const
  {
   const CGStdGraphObj *obj_compared=node;
//--- сравнение целочисленных свойств двух ордеров
   if(mode<GRAPH_OBJ_PROP_INTEGER_TOTAL)
     {
      long value_compared=obj_compared.GetProperty((ENUM_GRAPH_OBJ_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_GRAPH_OBJ_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- сравнение вещественных свойств двух ордеров
   else if(mode<GRAPH_OBJ_PROP_DOUBLE_TOTAL+GRAPH_OBJ_PROP_INTEGER_TOTAL)
     {
      double value_compared=obj_compared.GetProperty((ENUM_GRAPH_OBJ_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_GRAPH_OBJ_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- сравнение строковых свойств двух ордеров
   else if(mode<GRAPH_OBJ_PROP_DOUBLE_TOTAL+GRAPH_OBJ_PROP_INTEGER_TOTAL+GRAPH_OBJ_PROP_STRING_TOTAL)
     {
      string value_compared=obj_compared.GetProperty((ENUM_GRAPH_OBJ_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_GRAPH_OBJ_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+
//| Сравнивает объекты CGStdGraphObj между собой по всем свойствам   |
//+------------------------------------------------------------------+
bool CGStdGraphObj::IsEqual(CGStdGraphObj *compared_obj) const
  {
   int beg=0, end=GRAPH_OBJ_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_GRAPH_OBJ_PROP_INTEGER prop=(ENUM_GRAPH_OBJ_PROP_INTEGER)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=GRAPH_OBJ_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_GRAPH_OBJ_PROP_DOUBLE prop=(ENUM_GRAPH_OBJ_PROP_DOUBLE)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=GRAPH_OBJ_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_GRAPH_OBJ_PROP_STRING prop=(ENUM_GRAPH_OBJ_PROP_STRING)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   return true;
  }
//+------------------------------------------------------------------+

Метод, выводящий в журнал свойства объекта:

//+------------------------------------------------------------------+
//| Выводит в журнал свойства объекта                                |
//+------------------------------------------------------------------+
void CGStdGraphObj::Print(const bool full_prop=false,const bool dash=false)
  {
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") =============");
   int beg=0, end=GRAPH_OBJ_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_GRAPH_OBJ_PROP_INTEGER prop=(ENUM_GRAPH_OBJ_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=GRAPH_OBJ_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_GRAPH_OBJ_PROP_DOUBLE prop=(ENUM_GRAPH_OBJ_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=GRAPH_OBJ_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_GRAPH_OBJ_PROP_STRING prop=(ENUM_GRAPH_OBJ_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.Header(),") =============\n");
  }
//+------------------------------------------------------------------+

Метод, возвращающий краткое наименование объекта:

//+------------------------------------------------------------------+
//| Возвращает краткое наименование объекта                          |
//+------------------------------------------------------------------+
string CGStdGraphObj::Header(const bool symbol=false)
  {
   return CGBaseObj::TypeGraphObjectDescription();
  }
//+------------------------------------------------------------------+

Метод, выводящий в журнал краткое описание объекта:

//+------------------------------------------------------------------+
//| Выводит в журнал краткое описание объекта                        |
//+------------------------------------------------------------------+
void CGStdGraphObj::PrintShort(const bool dash=false,const bool symbol=false)
  {
   ::Print
     (
      this.Header(symbol)," \"",CGBaseObj::Name(),"\": ID ",(string)this.GetProperty(GRAPH_OBJ_PROP_ID),
      " ",::TimeToString(CGBaseObj::TimeCreate(),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
     );
  }
//+------------------------------------------------------------------+

Методы, возвращающие описания целочисленного, вещественного и строкового свойств объекта:

//+------------------------------------------------------------------+
//| Возвращает описание целочисленного свойства объекта              |
//+------------------------------------------------------------------+
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)
         )  :
      property==GRAPH_OBJ_PROP_TYPE       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_TYPE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+StdGraphObjectTypeDescription((ENUM_OBJECT)this.GetProperty(property))
         )  :
      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_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)
         )  :
      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)
         )  :
      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),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) :
          ": "+(string)this.GetProperty(property)
         )  :
      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)
         )  :
      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) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==GRAPH_OBJ_PROP_TIME       ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_TIME)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES)
         )  :
      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),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))
         )  :
      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)
         )  :
      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) ? 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) ? 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)
         )  :
      property==GRAPH_OBJ_PROP_LEVELCOLOR ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELCOLOR)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::ColorToString((color)this.GetProperty(property),true)
         )  :
      property==GRAPH_OBJ_PROP_LEVELSTYLE ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELSTYLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+LineStyleDescription((ENUM_LINE_STYLE)this.GetProperty(property))
         )  :
      property==GRAPH_OBJ_PROP_LEVELWIDTH ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELWIDTH)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      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))
         )  :
      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)
         )  :
      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) ? 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) ? 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) ? 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) ? 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)
         )  :
      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)
         )  :
      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)
         )  :
      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))
         )  :
      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))
         )  :
      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) ? 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) ? CMessage::Text(MSG_LIB_TEXT_BUTTON_STATE_PRESSED) : CMessage::Text(MSG_LIB_TEXT_BUTTON_STATE_DEPRESSED))
         )  :
      property==GRAPH_OBJ_PROP_OBJ_CHART_ID  ?  CMessage::Text(MSG_CHART_OBJ_ID)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      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))
         )  :
      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) ? 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) ? 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)
         )  :
      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)
         )  :
      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)
         )  :
      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)
         )  :
      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)
         )  :
      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),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))
         )  :
      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))
         )  :
      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),true)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Возвращает описание вещественного свойства объекта               |
//+------------------------------------------------------------------+
string CGStdGraphObj::GetPropertyDescription(ENUM_GRAPH_OBJ_PROP_DOUBLE property)
  {
   int dg=(this.m_digits>0 ? this.m_digits : 1);
   return
     (
      property==GRAPH_OBJ_PROP_PRICE      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_PRICE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),dg)
         )  :
      property==GRAPH_OBJ_PROP_LEVELVALUE ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELVALUE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),dg)
         )  :
      property==GRAPH_OBJ_PROP_SCALE      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_SCALE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==GRAPH_OBJ_PROP_ANGLE      ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_ANGLE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==GRAPH_OBJ_PROP_DEVIATION  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_DEVIATION)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Возвращает описание строкового свойства объекта                  |
//+------------------------------------------------------------------+
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)
         )  :
      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)
         )  :
      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)
         )  :
      property==GRAPH_OBJ_PROP_LEVELTEXT  ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_LEVELTEXT)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetProperty(property)
         )  :
      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)
         )  :
      property==GRAPH_OBJ_PROP_BMPFILE    ?  CMessage::Text(MSG_GRAPH_OBJ_PROP_BMPFILE)+
         (!this.SupportProperty(property) ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+this.GetProperty(property)
         )  :
      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)
         )  :
      ""
     );
  }

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

Работа аналогичных представленным выше методов рассматривалась нами в самом начале описания создания библиотеки, затем неоднократно по ходу написания разных объектов мы уточняли логику работы таких методов. Поэтому читателям работа таких методов должна быть давно известна. В любом случае, все свои вопросы можно задать в обсуждении статьи.

Создание класса абстрактного графического объекта завершено. Теперь нам необходимо в классе-коллекции графических объектов определить факт появления на графике графического объекта и создать соответствующий абстрактный графический объект.

Сегодня мы не будем добавлять эти объекты в список-коллекцию. Для этого нам необходимо создавать не абстрактный объект, а его наследников, описывающих конкретные типы добавляемых на график графических объектов. Такие объекты мы будем делать в следующей статье. Сегодня же нам необходимо лишь проверить правильность работы созданного сейчас класса.

В файле \MQL5\Include\DoEasy\Collections\GraphElementsCollection.mqh в классе управления объектами чарта (в файле расположены два класса) нам нужно будет сделать некоторые изменения. Дело в том, что здесь не получится создать экономный расчёт для поиска последнего добавленного графического объекта на график, как мы это делали в других коллекциях, где начинали цикл не от начала, а от значения индекса последнего объекта из обрабатываемых классом-коллекцией. Не получится по той причине, что графические объекты добавляются в список терминала не по очерёдности их добавления на график, а по имени. Да, как это ни странно, но графические объекты в списке терминала сортированы по имени. И последний из добавленных объектов на график значков "Стрелка" встанет первым в списке объектов, так как его имя начинается на "Arrow", в то время как самый первый объект "прямоугольник" станет в списке из двух объектов вторым — так как его имя начинается на "Rectangle".

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

//+------------------------------------------------------------------+
//|                                      GraphElementsCollection.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "ListObj.mqh"
#include "..\Services\Select.mqh"
#include "..\Objects\Graph\Form.mqh"

//+------------------------------------------------------------------+
//| Класс управления объектами чарта                                 |
//+------------------------------------------------------------------+
class CChartObjectsControl : public CObject
  {
private:
   ENUM_TIMEFRAMES   m_chart_timeframe;         // Период графика
   long              m_chart_id;                // Идентификатор графика
   string            m_chart_symbol;            // Символ графика
   bool              m_is_graph_obj_event;      // Флаг события в списке графических объектов
   int               m_total_objects;           // Количество графических объектов
   int               m_last_objects;            // Количество графических объектов на прошлой проверке
   int               m_index_object;            // Индекс последнего добавленного графического объекта в коллекцию из списка объектов терминала
   int               m_delta_graph_obj;         // Разница в количестве графических объектов по сравнению с прошлой проверкой
public:
//--- Возврат значений переменных
   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;    }
//--- Проверяет объекты на чарте
   void              Refresh(void);
//--- Конструкторы
                     CChartObjectsControl(void)
                       { 
                        this.m_chart_id=::ChartID();
                        this.m_chart_timeframe=(ENUM_TIMEFRAMES)::ChartPeriod(this.m_chart_id);
                        this.m_chart_symbol=::ChartSymbol(this.m_chart_id);
                        this.m_is_graph_obj_event=false;
                        this.m_total_objects=0;
                        this.m_last_objects=0;
                        this.m_index_object=0;
                        this.m_delta_graph_obj=0;
                       }
                     CChartObjectsControl(const long chart_id)
                       {
                        this.m_chart_id=chart_id;
                        this.m_chart_timeframe=(ENUM_TIMEFRAMES)::ChartPeriod(this.m_chart_id);
                        this.m_chart_symbol=::ChartSymbol(this.m_chart_id);
                        this.m_is_graph_obj_event=false;
                        this.m_total_objects=0;
                        this.m_last_objects=0;
                        this.m_index_object=0;
                        this.m_delta_graph_obj=0;
                       }
                     
//--- Сравнивает объекты CChartObjectsControl между собой по идентификатору графика (для сортировки списка по свойству объекта)
   virtual int       Compare(const CObject *node,const int mode=0) const
                       {
                        const CChartObjectsControl *obj_compared=node;
                        return(this.ChartID()>obj_compared.ChartID() ? 1 : this.ChartID()<obj_compared.ChartID() ? -1 : 0);
                       }
  };
//+------------------------------------------------------------------+
//| CChartObjectsControl Проверяет объекты на чарте                  |
//+------------------------------------------------------------------+
void CChartObjectsControl::Refresh(void)
  {
//--- Графические объекты на чарте
   this.m_total_objects=::ObjectsTotal(this.ChartID());
   int i=this.m_index_object;
   int delta=this.m_total_objects-this.m_last_objects;
   
//--- Если количество объектов изменилось
   if(delta!=0)
     {

В методе, проверяющем объекты на чарте, впишем такой обработчик события увеличения количества графических объектов на чарте:

//+------------------------------------------------------------------+
//| CChartObjectsControl Проверяет объекты на чарте                  |
//+------------------------------------------------------------------+
void CChartObjectsControl::Refresh(void)
  {
//--- Графические объекты на чарте
   this.m_total_objects=::ObjectsTotal(this.ChartID());
   this.m_delta_graph_obj=this.m_total_objects-this.m_last_objects;
   
//--- Если количество объектов изменилось
   if(this.m_delta_graph_obj!=0)
     {
      //--- Создадим строку и выведем её в журнал с указание идентификатора графика, его символа и периода
      string txt=", "+(m_delta_graph_obj>0 ? "Added: " : "Deleted: ")+(string)fabs(m_delta_graph_obj)+" obj";
      Print(DFUN,"ChartID=",this.ChartID(),", ",this.Symbol(),", ",TimeframeDescription(this.Timeframe()),txt);
     }
   //--- Если добавлен объект на график
   if(this.m_delta_graph_obj>0)
     {
      int index=0;
      datetime time=0;
      string name="";
      //--- находим последний добавленный графический объект и записываем его индекс
      for(int j=0;j<this.m_total_objects;j++)
        {
         name=::ObjectName(this.ChartID(),j);
         datetime tm=(datetime)::ObjectGetInteger(this.ChartID(),name,OBJPROP_CREATETIME);
         if(tm>time)
           {
            time=tm;
            index=j;
           }
        }
      
      //--- Выбираем последний графический объект по его индексу
      name=::ObjectName(this.ChartID(),index);
      if(name!="")
        {
         //--- Создаём объект класса абстрактного графического объекта
         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=new CGStdGraphObj(obj_type,GRAPH_OBJ_BELONG_NO_PROGRAM,this.ChartID(),name);
         if(obj!=NULL)
           {
            //--- Устанавливаем объекту индекс объекта, выводим его краткое описание и удаляем созданный объект
            obj.SetObjectID(this.m_total_objects);
            obj.PrintShort();
            delete obj;
           }
        }
     }
//--- сохранение индекса последнего добавленного графического объекта и разницы по сравнению с прошлой проверкой
   this.m_last_objects=this.m_total_objects;
   this.m_is_graph_obj_event=(bool)this.m_delta_graph_obj;
  }
//+------------------------------------------------------------------+

Основная логика расписана в комментариях к коду и, надеюсь, вопросов не вызывает.

В заключение, и в порядке исправления давнего упущения, в классе главного объекта библиотеки CEngine в файле \MQL5\Include\DoEasy\Engine.mqh в деструктор класса впишем очистку всех комментариев, присутствующих на графике:

//+------------------------------------------------------------------+
//| CEngine деструктор                                               |
//+------------------------------------------------------------------+
CEngine::~CEngine()
  {
   ::EventKillTimer();
   ::Comment("");
  }
//+------------------------------------------------------------------+

Теперь нам необходимо протестировать созданный функционал.


Тестирование

Для тестирования возьмём советник из прошлой статьи и сохраним его в новой папке \MQL5\Experts\TestDoEasy\Part83\ под новым именем TestDoEasyPart83.mq5.

Как ни странно, но никаких изменений нам в логику советника вносить не придётся. Лишь изменим поведение в обработчике OnDeinit():

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   Comment("");
  }
//+------------------------------------------------------------------+

Вместо уничтожения миллисекундного таймера и очистки всех комментариев на графике впишем вызов одноимённого метода библиотеки:

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Деинициализация библиотеки
   engine.OnDeinit();
  }
//+------------------------------------------------------------------+

При попытке скомпилировать советник получим такую ошибку:

'CGStdGraphObj::CGStdGraphObj' - cannot access protected member function
   see declaration of 'CGStdGraphObj::CGStdGraphObj'
1 errors, 0 warnings

И это естественно — у нас же параметрический конструктор класса абстрактного графического объекта объявлен в приватной секции класса. Для исправления ошибки просто временно укажем спецификатор доступа public для конструктора:

//--- Конструктор по умолчанию
                     CGStdGraphObj(){ this.m_type=OBJECT_DE_TYPE_GSTD_OBJ;  }
protected:
public:
//--- Защищённый параметрический конструктор
                     CGStdGraphObj(const ENUM_OBJECT_DE_TYPE obj_type,const ENUM_GRAPH_OBJ_BELONG belong,const long chart_id,const string name);
                     

Ещё раз скомпилируем советник и запустим его.

На график будем добавлять разные графические объекты, а в журнал будут выводиться сообщения о добавлении нового объекта и его краткое описание:


Как видим, всё работает, как и предполагалось.


Что дальше

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

Ниже прикреплены все файлы текущей версии библиотеки и файл тестового советника для MQL5. Их можно скачать и протестировать всё самостоятельно.

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

К содержанию

*Статьи этой серии:

Графика в библиотеке DoEasy (Часть 73): Объект-форма графического элемента
Графика в библиотеке DoEasy (Часть 74): Базовый графический элемент на основе класса CCanvas
Графика в библиотеке DoEasy (Часть 75): Методы работы с примитивами и текстом в базовом графическом элементе
Графика в библиотеке DoEasy (Часть 76): Объект Форма и предопределённые цветовые темы
Графика в библиотеке DoEasy (Часть 77): Класс объекта Тень
Графика в библиотеке DoEasy (Часть 78): Принципы анимации в библиотеке. Нарезка изображений
Графика в библиотеке DoEasy (Часть 79): Класс объекта "Кадр анимации" и его объекты-наследники
Графика в библиотеке DoEasy (Часть 80): Класс объекта "Кадр геометрической анимации"
Графика в библиотеке DoEasy (Часть 81): Интегрируем графику в объекты библиотеки
Графика в библиотеке DoEasy (Часть 82): Рефакторинг объектов библиотеки и коллекция графических объектов

Прикрепленные файлы |
MQL5.zip (4120.71 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (5)
Daniil Kurmyshev
Daniil Kurmyshev | 24 сент. 2021 в 11:25
Добрый день, 

Прочитал несколько ваших статей, иногда попадаются в списке, в целом ок, но смущает меня пара моментов...

1. Слишком много дубликатов кода в вашей реализации... Конечно возможно потом будет рефакторинг, а возможно несколько)

2. Если вы работаете со стандартными объектами, почему не использовать готовые классы, которые поставляются с терминалами и их нагружать дополнительным функционалов, таким образом расширяя возможности, а так получается нет обратной совместимости и вы делаете двойную работу...
Artyom Trishkin
Artyom Trishkin | 24 сент. 2021 в 19:28
Daniil Kurmyshev #:
Добрый день, 

Прочитал несколько ваших статей, иногда попадаются в списке, в целом ок, но смущает меня пара моментов...

1. Слишком много дубликатов кода в вашей реализации... Конечно возможно потом будет рефакторинг, а возможно несколько)

2. Если вы работаете со стандартными объектами, почему не использовать готовые классы, которые поставляются с терминалами и их нагружать дополнительным функционалов, таким образом расширяя возможности, а так получается нет обратной совместимости и вы делаете двойную работу...
  1. Примеры можно дубликатов, чтобы ответить конкретнее?
  2. Структура и концепция построения объектов библиотеки не совсем стыкуется с концепцией стандартной библиотеки. Но если вы могли заметить, то библиотека построена на стандартном CObject и CArrayObj.

В любом случае я с удовольствием отвечу на вопросы, приму критику и предложения.

Спасибо за интерес.

Daniil Kurmyshev
Daniil Kurmyshev | 25 сент. 2021 в 03:19
Artyom Trishkin #:
  1. Примеры можно дубликатов, чтобы ответить конкретнее?
  2. Структура и концепция построения объектов библиотеки не совсем стыкуется с концепцией стандартной библиотеки. Но если вы могли заметить, то библиотека построена на стандартном CObject и CArrayObj.

В любом случае я с удовольствием отвечу на вопросы, приму критику и предложения.

Спасибо за интерес.

1. Если конкретно я имел ввиду про участок от куда начинается код "Далее по коду класса впишем методы для упрощённого доступа установки и возврата свойств объекта: ".

Как я понимаю это описание функций в базовом классе, т.е. они получаются исчерпывающими для всех объектов и имеют уровень доступа public, если будет создан наследник он увидит все эти функции, но не каждый объект имеет свойства для управления и вывода текста например и т.п... и чтобы использовать этот объект он всегда будет тянуть за собой базовый класс, а не собственный прямой от CObject, конечно возможно в этом есть смысл, что получить все фишки базового класса, вывод лога и т.п. но тогда при создании наследников необходимо все функции которые нельзя применить к классу наследнику виртуализировать и скрывать в уровне доступа private  

Возможно в этом и есть фишка вашей реализации, если это так тогда СУПЕР!)))

Кстати возможно уровень protected для некоторых функций будет уместнее, чем public, но тут вам виднее конечно смотря какой в это вкладывается смысл.

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

3. Заметил также, что вы используете объединение строк с помощью +, в некоторых версиях терминала при больших объединениях и при продолжительной работе терминала получались непредсказуемые ситуации в такой реализации))

Использую функции StringFormat и StringAdd, надежность работы повысилась, а также визуально код становится читабельней

4. Ещё хотел предупредить на счет ограничения длины создаваемых объектов при рендринге, имейте это ввиду, лучше генерировать хэш из имени и на его основе создавать объект, ограничение имеет стандартная функция, точно не помню, но возможно ResourceCreate...

Artyom Trishkin
Artyom Trishkin | 25 сент. 2021 в 18:58
Daniil Kurmyshev #:

1. Если конкретно я имел ввиду про участок от куда начинается код "Далее по коду класса впишем методы для упрощённого доступа установки и возврата свойств объекта: ".

Как я понимаю это описание функций в базовом классе, т.е. они получаются исчерпывающими для всех объектов и имеют уровень доступа public, если будет создан наследник он увидит все эти функции, но не каждый объект имеет свойства для управления и вывода текста например и т.п... и чтобы использовать этот объект он всегда будет тянуть за собой базовый класс, а не собственный прямой от CObject, конечно возможно в этом есть смысл, что получить все фишки базового класса, вывод лога и т.п. но тогда при создании наследников необходимо все функции которые нельзя применить к классу наследнику виртуализировать и скрывать в уровне доступа private  

Возможно в этом и есть фишка вашей реализации, если это так тогда СУПЕР!)))

Кстати возможно уровень protected для некоторых функций будет уместнее, чем public, но тут вам виднее конечно смотря какой в это вкладывается смысл.

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

3. Заметил также, что вы используете объединение строк с помощью +, в некоторых версиях терминала при больших объединениях и при продолжительной работе терминала получались непредсказуемые ситуации в такой реализации))

Использую функции StringFormat и StringAdd, надежность работы повысилась, а также визуально код становится читабельней

4. Ещё хотел предупредить на счет ограничения длины создаваемых объектов при рендринге, имейте это ввиду, лучше генерировать кэш из имени и на его основе создавать объект, ограничение имеет стандартная функция, точно не помню, но возможно ResourceCreate...

1. Публичность методов и их избыточность - издержки желания сделать множество различных способов доступа к одним и тем же свойствам. Но некоторые методы действительно будут либо виртуальными, либо прописаны только в наследниках. Но это опять-таки касается только объектов самой библиотеки. При наследовании от них, увы, все публичные методы унаследуются.

2. Подумаю. Но вообще-то верхним уронем доступа будет ещё одна точка входа в библиотеки, и это будут пользовательские функции, опять же, повторяющие уже реализованные возможности библиотеки, но будут более понятны рядовому пользователю - просто использовать функцию для получения результата, а не придумывать логику и обработчики - всё это будет делаться внутри библиотеки, а на выходе - usercase-функции для простого получения нужной информации.

3. Ничего не оптимизировал (кроме заранее обдумываемой логики) и не профилировал. Это на самый последний момент.

4. Проверял по-моему. Там длинное имя объекта возможно. Но, спасибо, буду учитывать и приглядываться.

Daniil Kurmyshev
Daniil Kurmyshev | 26 сент. 2021 в 06:23
Artyom Trishkin #:

1. Публичность методов и их избыточность - издержки желания сделать множество различных способов доступа к одним и тем же свойствам. Но некоторые методы действительно будут либо виртуальными, либо прописаны только в наследниках. Но это опять-таки касается только объектов самой библиотеки. При наследовании от них, увы, все публичные методы унаследуются.

2. Подумаю. Но вообще-то верхним уронем доступа будет ещё одна точка входа в библиотеки, и это будут пользовательские функции, опять же, повторяющие уже реализованные возможности библиотеки, но будут более понятны рядовому пользователю - просто использовать функцию для получения результата, а не придумывать логику и обработчики - всё это будет делаться внутри библиотеки, а на выходе - usercase-функции для простого получения нужной информации.

3. Ничего не оптимизировал (кроме заранее обдумываемой логики) и не профилировал. Это на самый последний момент.

4. Проверял по-моему. Там длинное имя объекта возможно. Но, спасибо, буду учитывать и приглядываться.

4. Возможно эту ошибку устранили, но не факт..функция как будто бы работает, но объект не создается, вот такое поведение при большой длине  

Стать хорошим программистом (Часть 2): избавляемся еще от пяти привычек на пути к лучшему программированию на MQL5 Стать хорошим программистом (Часть 2): избавляемся еще от пяти привычек на пути к лучшему программированию на MQL5
Статья обязательна к прочтению для всех, кто хочет улучшить свою карьеру программиста. Цель этой серии статей — помочь любому читателю, даже опытному, улучшить навыки программирования. Описанные в статье идеи работают как для начинающих MQL5-программистов, так и для профессионалов.
Почти конструктор для создания советника Почти конструктор для создания советника
Предлагаю свой набор торговых функций в виде готового советника. Представленный способ позволяет получать множество торговых стратегий простым добавлением индикаторов и изменением входных параметров.
Графика в библиотеке DoEasy (Часть 84): Классы-наследники абстрактного стандартного графического объекта Графика в библиотеке DoEasy (Часть 84): Классы-наследники абстрактного стандартного графического объекта
В статье рассмотрим создание классов-наследников объекта абстрактного стандартного графического объекта терминала. Объект этого класса описывает общие для всех графических объектов свойства. Т.е. это просто некий графический объект. Для уточнения его принадлежности к реальному графическому объекту нам необходимо унаследоваться от него, и в классе объекта-наследника прописать свойства, присущие этому конкретному графическому объекту.
Графика в библиотеке DoEasy (Часть 82): Рефакторинг объектов библиотеки и коллекция графических объектов Графика в библиотеке DoEasy (Часть 82): Рефакторинг объектов библиотеки и коллекция графических объектов
В статье доработаем все объекты библиотеки - присвоим каждому объекту его уникальный тип и продолжим разработку класса-коллекции графических объектов библиотеки.