//+------------------------------------------------------------------+ //| Base.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Включаемые библиотеки | //+------------------------------------------------------------------+ #include // Класс СБ CCanvas #include // Класс СБ CList //+------------------------------------------------------------------+ //| Макроподстановки | //+------------------------------------------------------------------+ #define clrNULL 0x00FFFFFF // Прозрачный цвет для CCanvas #define MARKER_START_DATA -1 // Маркер начала данных в файле //+------------------------------------------------------------------+ //| Перечисления | //+------------------------------------------------------------------+ enum ENUM_ELEMENT_TYPE // Перечисление типов графических элементов { ELEMENT_TYPE_BASE = 0x10000, // Базовый объект графических элементов ELEMENT_TYPE_COLOR, // Объект цвета ELEMENT_TYPE_COLORS_ELEMENT, // Объект цветов элемента графического объекта ELEMENT_TYPE_RECTANGLE_AREA, // Прямоугольная область элемента ELEMENT_TYPE_CANVAS_BASE, // Базовый объект холста графических элементов }; enum ENUM_COLOR_STATE // Перечисление цветов состояний элемента { COLOR_STATE_DEFAULT, // Цвет обычного состояния COLOR_STATE_FOCUSED, // Цвет при наведении курсора на элемент COLOR_STATE_PRESSED, // Цвет при нажатии на элемент COLOR_STATE_BLOCKED, // Цвет заблокированного элемента }; //+------------------------------------------------------------------+ //| Функции | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Возвращает тип элемента как строку | //+------------------------------------------------------------------+ string ElementDescription(const ENUM_ELEMENT_TYPE type) { string array[]; int total=StringSplit(EnumToString(type),StringGetCharacter("_",0),array); string result=""; for(int i=2;iobj.Name() ? 1 : this.Name()obj.ID() ? 1 : this.ID()>8)&0xFF; } double GetB(const color clr) { return(clr>>16)&0xFF; } public: //--- Возвращает новый цвет color NewColor(color base_color, int shift_red, int shift_green, int shift_blue); //--- Инициализация цветов различных состояний bool InitDefault(const color clr) { return this.m_default.SetColor(clr); } bool InitFocused(const color clr) { return this.m_focused.SetColor(clr); } bool InitPressed(const color clr) { return this.m_pressed.SetColor(clr); } bool InitBlocked(const color clr) { return this.m_blocked.SetColor(clr); } //--- Установка цветов для всех состояний void InitColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked); void InitColors(const color clr); //--- Возврат цветов различных состояний color GetCurrent(void) const { return this.m_current.Get(); } color GetDefault(void) const { return this.m_default.Get(); } color GetFocused(void) const { return this.m_focused.Get(); } color GetPressed(void) const { return this.m_pressed.Get(); } color GetBlocked(void) const { return this.m_blocked.Get(); } //--- Устанавливает один из списка цветов как текущий bool SetCurrentAs(const ENUM_COLOR_STATE color_state); //--- (1) Возвращает, (2) выводит в журнал описание объекта virtual string Description(void); void Print(void); //--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта virtual int Compare(const CObject *node,const int mode=0) const; virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_COLORS_ELEMENT); } //--- Конструкторы/деструктор CColorElement(void); CColorElement(const color clr); CColorElement(const color clr_default,const color clr_focused,const color clr_pressed,const color clr_blocked); ~CColorElement(void) {} }; //+------------------------------------------------------------------+ //| CColorControl::Конструктор с установкой прозрачных цветов объекта| //+------------------------------------------------------------------+ CColorElement::CColorElement(void) { this.InitColors(clrNULL,clrNULL,clrNULL,clrNULL); this.m_default.SetName("Default"); this.m_default.SetID(1); this.m_focused.SetName("Focused"); this.m_focused.SetID(2); this.m_pressed.SetName("Pressed"); this.m_pressed.SetID(3); this.m_blocked.SetName("Blocked"); this.m_blocked.SetID(4); this.SetCurrentAs(COLOR_STATE_DEFAULT); this.m_current.SetName("Current"); this.m_current.SetID(0); } //+------------------------------------------------------------------+ //| CColorControl::Конструктор с указанием цветов объекта | //+------------------------------------------------------------------+ CColorElement::CColorElement(const color clr_default,const color clr_focused,const color clr_pressed,const color clr_blocked) { this.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); this.m_default.SetName("Default"); this.m_default.SetID(1); this.m_focused.SetName("Focused"); this.m_focused.SetID(2); this.m_pressed.SetName("Pressed"); this.m_pressed.SetID(3); this.m_blocked.SetName("Blocked"); this.m_blocked.SetID(4); this.SetCurrentAs(COLOR_STATE_DEFAULT); this.m_current.SetName("Current"); this.m_current.SetID(0); } //+------------------------------------------------------------------+ //| CColorControl::Конструктор с указанием цвета объекта | //+------------------------------------------------------------------+ CColorElement::CColorElement(const color clr) { this.InitColors(clr); this.m_default.SetName("Default"); this.m_default.SetID(1); this.m_focused.SetName("Focused"); this.m_focused.SetID(2); this.m_pressed.SetName("Pressed"); this.m_pressed.SetID(3); this.m_blocked.SetName("Blocked"); this.m_blocked.SetID(4); this.SetCurrentAs(COLOR_STATE_DEFAULT); this.m_current.SetName("Current"); this.m_current.SetID(0); } //+------------------------------------------------------------------+ //| CColorControl::Устанавливает цвета для всех состояний | //+------------------------------------------------------------------+ void CColorElement::InitColors(const color clr_default,const color clr_focused,const color clr_pressed,const color clr_blocked) { this.InitDefault(clr_default); this.InitFocused(clr_focused); this.InitPressed(clr_pressed); this.InitBlocked(clr_blocked); } //+------------------------------------------------------------------+ //| CColorControl::Устанавливает цвета для всех состояний по текущему| //+------------------------------------------------------------------+ void CColorElement::InitColors(const color clr) { this.InitDefault(clr); this.InitFocused(this.NewColor(clr,-3,-3,-3)); this.InitPressed(this.NewColor(clr,-6,-6,-6)); this.InitBlocked(clrSilver); } //+-------------------------------------------------------------------+ //|CColorControl::Устанавливает один цвет из списка цветов как текущий| //+-------------------------------------------------------------------+ bool CColorElement::SetCurrentAs(const ENUM_COLOR_STATE color_state) { switch(color_state) { case COLOR_STATE_DEFAULT : return this.m_current.SetColor(this.m_default.Get()); case COLOR_STATE_FOCUSED : return this.m_current.SetColor(this.m_focused.Get()); case COLOR_STATE_PRESSED : return this.m_current.SetColor(this.m_pressed.Get()); case COLOR_STATE_BLOCKED : return this.m_current.SetColor(this.m_blocked.Get()); default : return false; } } //+------------------------------------------------------------------+ //| CColorControl::Преобразует RGB в color | //+------------------------------------------------------------------+ color CColorElement::RGBToColor(const double r,const double g,const double b) const { int int_r=(int)::round(r); int int_g=(int)::round(g); int int_b=(int)::round(b); int clr=0; clr=int_b; clr<<=8; clr|=int_g; clr<<=8; clr|=int_r; return (color)clr; } //+------------------------------------------------------------------+ //| CColorControl::Получение значений компонентов RGB | //+------------------------------------------------------------------+ void CColorElement::ColorToRGB(const color clr,double &r,double &g,double &b) { r=this.GetR(clr); g=this.GetG(clr); b=this.GetB(clr); } //+------------------------------------------------------------------+ //| CColorControl::Возвращает цвет с новой цветовой составляющей | //+------------------------------------------------------------------+ color CColorElement::NewColor(color base_color, int shift_red, int shift_green, int shift_blue) { double clrR=0, clrG=0, clrB=0; this.ColorToRGB(base_color,clrR,clrG,clrB); double clrRx=(clrR+shift_red < 0 ? 0 : clrR+shift_red > 255 ? 255 : clrR+shift_red); double clrGx=(clrG+shift_green< 0 ? 0 : clrG+shift_green> 255 ? 255 : clrG+shift_green); double clrBx=(clrB+shift_blue < 0 ? 0 : clrB+shift_blue > 255 ? 255 : clrB+shift_blue); return this.RGBToColor(clrRx,clrGx,clrBx); } //+------------------------------------------------------------------+ //| CColorElement::Возвращает описание объекта | //+------------------------------------------------------------------+ string CColorElement::Description(void) { string res=::StringFormat("%s Colors. %s",this.Name(),this.m_current.Description()); res+="\n 1: "+this.m_default.Description(); res+="\n 2: "+this.m_focused.Description(); res+="\n 3: "+this.m_pressed.Description(); res+="\n 4: "+this.m_blocked.Description(); return res; } //+------------------------------------------------------------------+ //| CColorElement::Выводит в журнал описание объекта | //+------------------------------------------------------------------+ void CColorElement::Print(void) { ::Print(this.Description()); } //+------------------------------------------------------------------+ //| CColorElement::Сохранение в файл | //+------------------------------------------------------------------+ bool CColorElement::Save(const int file_handle) { //--- Проверяем хэндл if(file_handle==INVALID_HANDLE) return false; //--- Сохраняем маркер начала данных - 0xFFFFFFFFFFFFFFFF if(::FileWriteLong(file_handle,-1)!=sizeof(long)) return false; //--- Сохраняем тип объекта if(::FileWriteInteger(file_handle,this.Type(),INT_VALUE)!=INT_VALUE) return false; //--- Сохраняем идентификатор if(::FileWriteInteger(file_handle,this.m_id,INT_VALUE)!=INT_VALUE) return false; //--- Сохраняем наименование цветов элемента if(::FileWriteArray(file_handle,this.m_name)!=sizeof(this.m_name)) return false; //--- Сохраняем текущий цвет if(!this.m_current.Save(file_handle)) return false; //--- Сохраняем цвет обычного состояния if(!this.m_default.Save(file_handle)) return false; //--- Сохраняем цвет при наведении курсора if(!this.m_focused.Save(file_handle)) return false; //--- Сохраняем цвет при нажатии if(!this.m_pressed.Save(file_handle)) return false; //--- Сохраняем цвет заблокированного элемента if(!this.m_blocked.Save(file_handle)) return false; //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CColorElement::Загрузка из файла | //+------------------------------------------------------------------+ bool CColorElement::Load(const int file_handle) { //--- Проверяем хэндл if(file_handle==INVALID_HANDLE) return false; //--- Загружаем и проверяем маркер начала данных - 0xFFFFFFFFFFFFFFFF if(::FileReadLong(file_handle)!=-1) return false; //--- Загружаем тип объекта if(::FileReadInteger(file_handle,INT_VALUE)!=this.Type()) return false; //--- Загружаем идентификатор this.m_id=::FileReadInteger(file_handle,INT_VALUE); //--- Загружаем наименование цветов элемента if(::FileReadArray(file_handle,this.m_name)!=sizeof(this.m_name)) return false; //--- Загружаем текущий цвет if(!this.m_current.Load(file_handle)) return false; //--- Загружаем цвет обычного состояния if(!this.m_default.Load(file_handle)) return false; //--- Загружаем цвет при наведении курсора if(!this.m_focused.Load(file_handle)) return false; //--- Загружаем цвет при нажатии if(!this.m_pressed.Load(file_handle)) return false; //--- Загружаем цвет заблокированного элемента if(!this.m_blocked.Load(file_handle)) return false; //--- Всё успешно return true; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Класс прямоугольной области | //+------------------------------------------------------------------+ class CBound : public CBaseObj { protected: CRect m_bound; // Структура прямоугольной области public: //--- Изменяет (1) ширину, (2) высоту, (3) размер ограничивающего прямоугольника void ResizeW(const int size) { this.m_bound.Width(size); } void ResizeH(const int size) { this.m_bound.Height(size); } void Resize(const int w,const int h) { this.m_bound.Width(w); this.m_bound.Height(h); } //--- Устанавливает координату (1) X, (2) Y, (3) обе координаты ограничивающего прямоугольника void SetX(const int x) { this.m_bound.left=x; } void SetY(const int y) { this.m_bound.top=y; } void SetXY(const int x,const int y) { this.m_bound.LeftTop(x,y); } //--- (1) Устанавливает, (2) смещает ограничивающий прямоугольник на указанные координаты/размер смещения void Move(const int x,const int y) { this.m_bound.Move(x,y); } void Shift(const int dx,const int dy) { this.m_bound.Shift(dx,dy); } //--- Возвращает координаты, размеры и границы объекта int X(void) const { return this.m_bound.left; } int Y(void) const { return this.m_bound.top; } int Width(void) const { return this.m_bound.Width(); } int Height(void) const { return this.m_bound.Height(); } int Right(void) const { return this.m_bound.right-1; } int Bottom(void) const { return this.m_bound.bottom-1; } //--- (1) Возвращает, (2) выводит в журнал описание объекта virtual string Description(void); void Print(void); //--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта virtual int Compare(const CObject *node,const int mode=0) const; virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_RECTANGLE_AREA); } //--- Конструкторы/деструктор CBound(void) { ::ZeroMemory(this.m_bound); } CBound(const int x,const int y,const int w,const int h) { this.SetXY(x,y); this.Resize(w,h); } ~CBound(void) { ::ZeroMemory(this.m_bound); } }; //+------------------------------------------------------------------+ //| CBound::Возвращает описание объекта | //+------------------------------------------------------------------+ string CBound::Description(void) { string nm=this.Name(); string name=(nm!="" ? ::StringFormat(" \"%s\"",nm) : nm); return ::StringFormat("%s%s: x %d, y %d, w %d, h %d", ElementDescription((ENUM_ELEMENT_TYPE)this.Type()),name, this.X(),this.Y(),this.Width(),this.Height()); } //+------------------------------------------------------------------+ //| CBound::Выводит в журнал описание объекта | //+------------------------------------------------------------------+ void CBound::Print(void) { ::Print(this.Description()); } //+------------------------------------------------------------------+ //| CBound::Сохранение в файл | //+------------------------------------------------------------------+ bool CBound::Save(const int file_handle) { //--- Проверяем хэндл if(file_handle==INVALID_HANDLE) return false; //--- Сохраняем маркер начала данных - 0xFFFFFFFFFFFFFFFF if(::FileWriteLong(file_handle,-1)!=sizeof(long)) return false; //--- Сохраняем тип объекта if(::FileWriteInteger(file_handle,this.Type(),INT_VALUE)!=INT_VALUE) return false; //--- Сохраняем идентификатор if(::FileWriteInteger(file_handle,this.m_id,INT_VALUE)!=INT_VALUE) return false; //--- Сохраняем наименование if(::FileWriteArray(file_handle,this.m_name)!=sizeof(this.m_name)) return false; //--- Сохраняем структуру области if(::FileWriteStruct(file_handle,this.m_bound)!=sizeof(this.m_bound)) return(false); //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CBound::Загрузка из файла | //+------------------------------------------------------------------+ bool CBound::Load(const int file_handle) { //--- Проверяем хэндл if(file_handle==INVALID_HANDLE) return false; //--- Загружаем и проверяем маркер начала данных - 0xFFFFFFFFFFFFFFFF if(::FileReadLong(file_handle)!=-1) return false; //--- Загружаем тип объекта if(::FileReadInteger(file_handle,INT_VALUE)!=this.Type()) return false; //--- Загружаем идентификатор this.m_id=::FileReadInteger(file_handle,INT_VALUE); //--- Загружаем наименование if(::FileReadArray(file_handle,this.m_name)!=sizeof(this.m_name)) return false; //--- Загружаем структуру области if(::FileReadStruct(file_handle,this.m_bound)!=sizeof(this.m_bound)) return(false); //--- Всё успешно return true; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Базовый класс холста графических элементов | //+------------------------------------------------------------------+ class CCanvasBase : public CBaseObj { protected: CCanvas m_background; // Канвас для рисования фона CCanvas m_foreground; // Канвас для рисования переднего плана CBound m_bound; // Границы объекта CCanvasBase *m_container; // Родительский объект-контейнер CColorElement m_color_background; // Объект управления цветом фона CColorElement m_color_foreground; // Объект управления цветом переднего плана CColorElement m_color_border; // Объект управления цветом рамки long m_chart_id; // Идентификатор графика int m_wnd; // Номер подокна графика int m_wnd_y; // Смещение координаты Y курсора в подокне int m_obj_x; // Координата X графического объекта int m_obj_y; // Координата Y графического объекта uchar m_alpha; // Прозрачность uint m_border_width; // Ширина рамки string m_program_name; // Имя программы bool m_hidden; // Флаг скрытого объекта bool m_blocked; // Флаг заблокированного элемента bool m_focused; // Флаг элемента в фокусе private: //--- Возврат смещения начальных координат рисования на холсте относительно канваса и координат объекта int CanvasOffsetX(void) const { return(this.ObjectX()-this.X()); } int CanvasOffsetY(void) const { return(this.ObjectY()-this.Y()); } //--- Возвращает скорректированную координату точки на холсте с учётом смещения холста относительно объекта int AdjX(const int x) const { return(x-this.CanvasOffsetX()); } int AdjY(const int y) const { return(y-this.CanvasOffsetY()); } protected: //--- Возвращает скорректированный идентификатор графика long CorrectChartID(const long chart_id) const { return(chart_id!=0 ? chart_id : ::ChartID()); } //--- Получение границ родительского объекта-контейнера int ContainerLimitLeft(void) const { return(this.m_container==NULL ? this.X() : this.m_container.LimitLeft()); } int ContainerLimitRight(void) const { return(this.m_container==NULL ? this.Right() : this.m_container.LimitRight()); } int ContainerLimitTop(void) const { return(this.m_container==NULL ? this.Y() : this.m_container.LimitTop()); } int ContainerLimitBottom(void) const { return(this.m_container==NULL ? this.Bottom() : this.m_container.LimitBottom()); } //--- Возврат координат, границ и размеров графического объекта int ObjectX(void) const { return this.m_obj_x; } int ObjectY(void) const { return this.m_obj_y; } int ObjectWidth(void) const { return this.m_background.Width(); } int ObjectHeight(void) const { return this.m_background.Height(); } int ObjectRight(void) const { return this.ObjectX()+this.ObjectWidth()-1; } int ObjectBottom(void) const { return this.ObjectY()+this.ObjectHeight()-1; } //--- Изменяет (1) ширину, (2) высоту, (3) размер ограничивающего прямоугольника void BoundResizeW(const int size) { this.m_bound.ResizeW(size); } void BoundResizeH(const int size) { this.m_bound.ResizeH(size); } void BoundResize(const int w,const int h) { this.m_bound.Resize(w,h); } //--- Устанавливает координату (1) X, (2) Y, (3) обе координаты ограничивающего прямоугольника void BoundSetX(const int x) { this.m_bound.SetX(x); } void BoundSetY(const int y) { this.m_bound.SetY(y); } void BoundSetXY(const int x,const int y) { this.m_bound.SetXY(x,y); } //--- (1) Устанавливает, (2) смещает ограничивающий прямоугольник на указанные координаты/размер смещения void BoundMove(const int x,const int y) { this.m_bound.Move(x,y); } void BoundShift(const int dx,const int dy) { this.m_bound.Shift(dx,dy); } //--- Изменяет (1) ширину, (2) высоту, (3) размер графического объекта bool ObjectResizeW(const int size); bool ObjectResizeH(const int size); bool ObjectResize(const int w,const int h); //--- Устанавливает координату (1) X, (2) Y, (3) обе координаты графического объекта bool ObjectSetX(const int x); bool ObjectSetY(const int y); bool ObjectSetXY(const int x,const int y) { return(this.ObjectSetX(x) && this.ObjectSetY(y)); } //--- (1) Устанавливает, (2) смещает графический объект на указанные координаты/размер смещения bool ObjectMove(const int x,const int y) { return this.ObjectSetXY(x,y); } bool ObjectShift(const int dx,const int dy) { return this.ObjectSetXY(this.ObjectX()+dx,this.ObjectY()+dy); } //--- Ограничивает графический объект по размерам контейнера virtual void ObjectTrim(void); public: //--- Возвращает указатель на канвас (1) фона, (2) переднего плана CCanvas *GetBackground(void) { return &this.m_background; } CCanvas *GetForeground(void) { return &this.m_foreground; } //--- Возвращает указатель на объект управления цветом (1) фона, (2) переднего плана, (3) рамки CColorElement *GetBackColorControl(void) { return &this.m_color_background; } CColorElement *GetForeColorControl(void) { return &this.m_color_foreground; } CColorElement *GetBorderColorControl(void) { return &this.m_color_border; } //--- Возврат цвета (1) фона, (2) переднего плана, (3) рамки color BackColor(void) const { return this.m_color_background.GetCurrent(); } color ForeColor(void) const { return this.m_color_foreground.GetCurrent(); } color BorderColor(void) const { return this.m_color_border.GetCurrent(); } //--- Установка цветов фона для всех состояний void InitBackColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_background.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitBackColors(const color clr) { this.m_color_background.InitColors(clr); } //--- Установка цветов переднего плана для всех состояний void InitForeColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_foreground.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitForeColors(const color clr) { this.m_color_foreground.InitColors(clr); } //--- Установка цветов рамки для всех состояний void InitBorderColors(const color clr_default, const color clr_focused, const color clr_pressed, const color clr_blocked) { this.m_color_border.InitColors(clr_default,clr_focused,clr_pressed,clr_blocked); } void InitBorderColors(const color clr) { this.m_color_border.InitColors(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки начальными значениями void InitBackColorDefault(const color clr) { this.m_color_background.InitDefault(clr); } void InitForeColorDefault(const color clr) { this.m_color_foreground.InitDefault(clr); } void InitBorderColorDefault(const color clr) { this.m_color_border.InitDefault(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки при наведении курсора начальными значениями void InitBackColorFocused(const color clr) { this.m_color_background.InitFocused(clr); } void InitForeColorFocused(const color clr) { this.m_color_foreground.InitFocused(clr); } void InitBorderColorFocused(const color clr) { this.m_color_border.InitFocused(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки при щелчке по объекту начальными значениями void InitBackColorPressed(const color clr) { this.m_color_background.InitPressed(clr); } void InitForeColorPressed(const color clr) { this.m_color_foreground.InitPressed(clr); } void InitBorderColorPressed(const color clr) { this.m_color_border.InitPressed(clr); } //--- Инициализация цвета (1) фона, (2) переднего плана, (3) рамки для заблокированного объекта начальными значениями void InitBackColorBlocked(const color clr) { this.m_color_background.InitBlocked(clr); } void InitForeColorBlocked(const color clr) { this.m_color_foreground.InitBlocked(clr); } void InitBorderColorBlocked(const color clr) { this.m_color_border.InitBlocked(clr); } //--- Установка текущего цвета фона в различные состояния bool BackColorToDefault(void) { return this.m_color_background.SetCurrentAs(COLOR_STATE_DEFAULT); } bool BackColorToFocused(void) { return this.m_color_background.SetCurrentAs(COLOR_STATE_FOCUSED); } bool BackColorToPressed(void) { return this.m_color_background.SetCurrentAs(COLOR_STATE_PRESSED); } bool BackColorToBlocked(void) { return this.m_color_background.SetCurrentAs(COLOR_STATE_BLOCKED); } //--- Установка текущего цвета переднего плана в различные состояния bool ForeColorToDefault(void) { return this.m_color_foreground.SetCurrentAs(COLOR_STATE_DEFAULT); } bool ForeColorToFocused(void) { return this.m_color_foreground.SetCurrentAs(COLOR_STATE_FOCUSED); } bool ForeColorToPressed(void) { return this.m_color_foreground.SetCurrentAs(COLOR_STATE_PRESSED); } bool ForeColorToBlocked(void) { return this.m_color_foreground.SetCurrentAs(COLOR_STATE_BLOCKED); } //--- Установка текущего цвета рамки в различные состояния bool BorderColorToDefault(void) { return this.m_color_border.SetCurrentAs(COLOR_STATE_DEFAULT); } bool BorderColorToFocused(void) { return this.m_color_border.SetCurrentAs(COLOR_STATE_FOCUSED); } bool BorderColorToPressed(void) { return this.m_color_border.SetCurrentAs(COLOR_STATE_PRESSED); } bool BorderColorToBlocked(void) { return this.m_color_border.SetCurrentAs(COLOR_STATE_BLOCKED); } //--- Установка текущих цветов элемента в различные состояния bool ColorsToDefault(void); bool ColorsToFocused(void); bool ColorsToPressed(void); bool ColorsToBlocked(void); //--- Устанавливает указатель на родительский объект-контейнер void SetContainerObj(CCanvasBase *obj); //--- Создаёт OBJ_BITMAP_LABEL bool Create(const long chart_id,const int wnd,const string name,const int x,const int y,const int w,const int h); //--- Возвращает (1) принадлежность объекта программе, флаг (2) скрытого, (3) заблокированного элемента, (4) имя графического объекта bool IsBelongsToThis(void) const { return(::ObjectGetString(this.m_chart_id,this.NameBG(),OBJPROP_TEXT)==this.m_program_name); } bool IsHidden(void) const { return this.m_hidden; } bool IsBlocked(void) const { return this.m_blocked; } bool IsFocused(void) const { return this.m_focused; } string NameBG(void) const { return this.m_background.ChartObjectName(); } string NameFG(void) const { return this.m_foreground.ChartObjectName(); } //--- (1) Возвращает, (2) устанавливает прозрачность uchar Alpha(void) const { return this.m_alpha; } void SetAlpha(const uchar value) { this.m_alpha=value; } //--- (1) Возвращает, (2) устанавливает ширину рамки uint BorderWidth(void) const { return this.m_border_width; } void SetBorderWidth(const uint width) { this.m_border_width=width; } //--- Возвращает координаты, размеры и границы объекта int X(void) const { return this.m_bound.X(); } int Y(void) const { return this.m_bound.Y(); } int Width(void) const { return this.m_bound.Width(); } int Height(void) const { return this.m_bound.Height(); } int Right(void) const { return this.m_bound.Right(); } int Bottom(void) const { return this.m_bound.Bottom(); } //--- Устанавливает объекту новую координату (1) X, (2) Y, (3) XY bool MoveX(const int x); bool MoveY(const int y); bool Move(const int x,const int y); //--- Смещает объект по оси (1) X, (2) Y, (3) XY на указанное смещение bool ShiftX(const int dx); bool ShiftY(const int dy); bool Shift(const int dx,const int dy); //--- Возврат границ объекта с учётом рамки int LimitLeft(void) const { return this.X()+(int)this.m_border_width; } int LimitRight(void) const { return this.Right()-(int)this.m_border_width; } int LimitTop(void) const { return this.Y()+(int)this.m_border_width; } int LimitBottom(void) const { return this.Bottom()-(int)this.m_border_width; } //--- (1) Скрывает (2) отображает объект на всех периодах графика, //--- (3) помещает объект на передний план, (4) блокирует, (5) разблокирует элемент, //--- (6) заливает объект указанным цветом с установленной прозрачностью virtual void Hide(const bool chart_redraw); virtual void Show(const bool chart_redraw); virtual void BringToTop(const bool chart_redraw); virtual void Block(const bool chart_redraw); virtual void Unblock(const bool chart_redraw); void Fill(const color clr,const bool chart_redraw); //--- (1) Заливает объект прозрачным цветом, (2) обновляет объект для отображения изменений, //--- (3) рисует внешний вид, (4) уничтожает объект virtual void Clear(const bool chart_redraw); virtual void Update(const bool chart_redraw); virtual void Draw(const bool chart_redraw); virtual void Destroy(void); //--- (1) Возвращает, (2) выводит в журнал описание объекта virtual string Description(void); void Print(void); //--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта virtual int Compare(const CObject *node,const int mode=0) const; virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); virtual int Type(void) const { return(ELEMENT_TYPE_CANVAS_BASE); } //--- Конструкторы/деструктор CCanvasBase(void) : m_program_name(::MQLInfoString(MQL_PROGRAM_NAME)), m_chart_id(::ChartID()), m_wnd(0), m_alpha(0), m_hidden(false), m_blocked(false), m_focused(false), m_border_width(0), m_wnd_y(0) { } CCanvasBase(const long chart_id,const int wnd,const string name,const int x,const int y,const int w,const int h); ~CCanvasBase(void); }; //+------------------------------------------------------------------+ //| CCanvasBase::Конструктор | //+------------------------------------------------------------------+ CCanvasBase::CCanvasBase(const long chart_id,const int wnd,const string name,const int x,const int y,const int w,const int h) : m_program_name(::MQLInfoString(MQL_PROGRAM_NAME)), m_wnd(wnd<0 ? 0 : wnd), m_alpha(0), m_hidden(false), m_blocked(false), m_focused(false), m_border_width(0) { //--- Получаем скорректированный идентификатор графика и дистанцию в пикселях по вертикальной оси Y //--- между верхней рамкой подокна индикатора и верхней рамкой главного окна графика this.m_chart_id=this.CorrectChartID(chart_id); this.m_wnd_y=(int)::ChartGetInteger(this.m_chart_id,CHART_WINDOW_YDISTANCE,this.m_wnd); //--- Если графический ресурс и графический объект созданы if(this.Create(this.m_chart_id,this.m_wnd,name,x,y,w,h)) { //--- Очищаем канвасы фона и переднего плана и устанавливаем начальные значения координат, //--- наименования графических объектов и свойства текста, рисуемого на переднем плане this.Clear(false); this.m_obj_x=x; this.m_obj_y=y; this.m_color_background.SetName("Background"); this.m_color_foreground.SetName("Foreground"); this.m_color_border.SetName("Border"); this.m_foreground.FontSet("Calibri",12); this.m_bound.SetName("Perimeter"); } } //+------------------------------------------------------------------+ //| CCanvasBase::Деструктор | //+------------------------------------------------------------------+ CCanvasBase::~CCanvasBase(void) { this.Destroy(); } //+------------------------------------------------------------------+ //| CCanvasBase::Создаёт графические объекты фона и переднего плана | //+------------------------------------------------------------------+ bool CCanvasBase::Create(const long chart_id,const int wnd,const string name,const int x,const int y,const int w,const int h) { //--- Получаем скорректированный идентификатор графика long id=this.CorrectChartID(chart_id); //--- Создаём имя графического объекта для фона и создаём канвас string obj_name=name+"_BG"; if(!this.m_background.CreateBitmapLabel(id,(wnd<0 ? 0 : wnd),obj_name,x,y,(w>0 ? w : 1),(h>0 ? h : 1),COLOR_FORMAT_ARGB_NORMALIZE)) { ::PrintFormat("%s: The CreateBitmapLabel() method of the CCanvas class returned an error creating a \"%s\" graphic object",__FUNCTION__,obj_name); return false; } //--- Создаём имя графического объекта для переднего плана и создаём канвас obj_name=name+"_FG"; if(!this.m_foreground.CreateBitmapLabel(id,(wnd<0 ? 0 : wnd),obj_name,x,y,(w>0 ? w : 1),(h>0 ? h : 1),COLOR_FORMAT_ARGB_NORMALIZE)) { ::PrintFormat("%s: The CreateBitmapLabel() method of the CCanvas class returned an error creating a \"%s\" graphic object",__FUNCTION__,obj_name); return false; } //--- При успешном создании в свойство графического объекта OBJPROP_TEXT вписываем наименование программы ::ObjectSetString(id,this.NameBG(),OBJPROP_TEXT,this.m_program_name); ::ObjectSetString(id,this.NameFG(),OBJPROP_TEXT,this.m_program_name); //--- Устанавливаем размеры прямоугольной области и возвращаем true this.m_bound.SetXY(x,y); this.m_bound.Resize(w,h); return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает указатель | //| на родительский объект-контейнер | //+------------------------------------------------------------------+ void CCanvasBase::SetContainerObj(CCanvasBase *obj) { //--- Устанавливаем переданный указатель объекту this.m_container=obj; //--- Если указатель пустой - уходим if(this.m_container==NULL) return; //--- Если передан невалидный указатель - обнуляем его в объекте и уходим if(::CheckPointer(this.m_container)==POINTER_INVALID) { this.m_container=NULL; return; } //--- Обрезаем объект по границам назначенного ему контейнера this.ObjectTrim(); } //+------------------------------------------------------------------+ //| CCanvasBase::Подрезает графический объект по контуру контейнера | //+------------------------------------------------------------------+ void CCanvasBase::ObjectTrim() { //--- Получаем границы контейнера int container_left = this.ContainerLimitLeft(); int container_right = this.ContainerLimitRight(); int container_top = this.ContainerLimitTop(); int container_bottom = this.ContainerLimitBottom(); //--- Получаем текущие границы объекта int object_left = this.X(); int object_right = this.Right(); int object_top = this.Y(); int object_bottom = this.Bottom(); //--- Проверяем, полностью ли объект выходит за пределы контейнера и скрываем его, если да if(object_right <= container_left || object_left >= container_right || object_bottom <= container_top || object_top >= container_bottom) { this.Hide(true); this.ObjectResize(this.Width(),this.Height()); return; } //--- Проверяем выход объекта по горизонтали и вертикали за пределы контейнера bool modified_horizontal=false; // Флаг изменений по горизонтали bool modified_vertical =false; // Флаг изменений по вертикали //--- Обрезка по горизонтали int new_left = object_left; int new_width = this.Width(); //--- Если объект выходит за левую границу контейнера if(object_left<=container_left) { int crop_left=container_left-object_left; new_left=container_left; new_width-=crop_left; modified_horizontal=true; } //--- Если объект выходит за правую границу контейнера if(object_right>=container_right) { int crop_right=object_right-container_right; new_width-=crop_right; modified_horizontal=true; } //--- Если были изменения по горизонтали if(modified_horizontal) { this.ObjectSetX(new_left); this.ObjectResizeW(new_width); } //--- Обрезка по вертикали int new_top=object_top; int new_height=this.Height(); //--- Если объект выходит за верхнюю границу контейнера if(object_top<=container_top) { int crop_top=container_top-object_top; new_top=container_top; new_height-=crop_top; modified_vertical=true; } //--- Если объект выходит за нижнюю границу контейнера if(object_bottom>=container_bottom) { int crop_bottom=object_bottom-container_bottom; new_height-=crop_bottom; modified_vertical=true; } //--- Если были изменения по вертикали if(modified_vertical) { this.ObjectSetY(new_top); this.ObjectResizeH(new_height); } //--- После рассчётов, объект может быть скрыт, но теперь находится в области контейнера - отображаем его this.Show(false); //--- Если объект был изменен, перерисовываем его if(modified_horizontal || modified_vertical) { this.Update(false); this.Draw(false); } } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает координату X графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectSetX(const int x) { //--- Если передана существующая координата - возвращаем true if(this.ObjectX()==x) return true; //--- Если не удалось установить новую координату в графические объекты фона и переднего плана - возвращаем false if(!::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_XDISTANCE,x) || !::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_XDISTANCE,x)) return false; //--- Записываем новую координату в переменную и возвращаем true this.m_obj_x=x; return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает координату Y графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectSetY(const int y) { //--- Если передана существующая координата - возвращаем true if(this.ObjectY()==y) return true; //--- Если не удалось установить новую координату в графические объекты фона и переднего плана - возвращаем false if(!::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_YDISTANCE,y) || !::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_YDISTANCE,y)) return false; //--- Записываем новую координату в переменную и возвращаем true this.m_obj_y=y; return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет ширину графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectResizeW(const int size) { //--- Если передана существующая ширина - возвращаем true if(this.ObjectWidth()==size) return true; //--- Если передан размер больше 0, возвращаем результат изменения ширины фона и переднего плана, иначе - false return(size>0 ? (this.m_background.Resize(size,this.ObjectHeight()) && this.m_foreground.Resize(size,this.ObjectHeight())) : false); } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет высоту графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectResizeH(const int size) { //--- Если передана существующая высота - возвращаем true if(this.ObjectHeight()==size) return true; //--- Если передан размер больше 0, возвращаем результат изменения высоты фона и переднего плана, иначе - false return(size>0 ? (this.m_background.Resize(this.ObjectWidth(),size) && this.m_foreground.Resize(this.ObjectWidth(),size)) : false); } //+------------------------------------------------------------------+ //| CCanvasBase::Изменяет размер графического объекта | //+------------------------------------------------------------------+ bool CCanvasBase::ObjectResize(const int w,const int h) { if(!this.ObjectResizeW(w)) return false; return this.ObjectResizeH(h); } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает объекту новые координаты X и Y | //+------------------------------------------------------------------+ bool CCanvasBase::Move(const int x,const int y) { if(!this.ObjectMove(x,y)) return false; this.BoundMove(x,y); this.ObjectTrim(); return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает объекту новую координату X | //+------------------------------------------------------------------+ bool CCanvasBase::MoveX(const int x) { return this.Move(x,this.ObjectY()); } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает объекту новую координату Y | //+------------------------------------------------------------------+ bool CCanvasBase::MoveY(const int y) { return this.Move(this.ObjectX(),y); } //+------------------------------------------------------------------+ //| CCanvasBase::Смещает объект по осям X и Y на указанное смещение | //+------------------------------------------------------------------+ bool CCanvasBase::Shift(const int dx,const int dy) { if(!this.ObjectShift(dx,dy)) return false; this.BoundShift(dx,dy); this.ObjectTrim(); return true; } //+------------------------------------------------------------------+ //| CCanvasBase::Смещает объект по оси X на указанное смещение | //+------------------------------------------------------------------+ bool CCanvasBase::ShiftX(const int dx) { return this.Shift(dx,0); } //+------------------------------------------------------------------+ //| CCanvasBase::Смещает объект по оси Y на указанное смещение | //+------------------------------------------------------------------+ bool CCanvasBase::ShiftY(const int dy) { return this.Shift(0,dy); } //+------------------------------------------------------------------+ //| CCanvasBase::Скрывает объект на всех периодах графика | //+------------------------------------------------------------------+ void CCanvasBase::Hide(const bool chart_redraw) { //--- Если объект уже скрыт - уходим if(this.m_hidden) return; //--- Если изменение видимости для фона и переднего плана успешно поставлено //--- в очередь команд графика - устанавливаем флаг скрытого объекта if(::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS) && ::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS) ) this.m_hidden=true; //--- Если указано - перерисовываем график if(chart_redraw) ::ChartRedraw(this.m_chart_id); } //+------------------------------------------------------------------+ //| CCanvasBase::Отображает объект на всех периодах графика | //+------------------------------------------------------------------+ void CCanvasBase::Show(const bool chart_redraw) { //--- Если объект уже видимый - уходим if(!this.m_hidden) return; //--- Если изменение видимости для фона и переднего плана успешно поставлено //--- в очередь команд графика - сбрасываем флаг скрытого объекта if(::ObjectSetInteger(this.m_chart_id,this.NameBG(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS) && ::ObjectSetInteger(this.m_chart_id,this.NameFG(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS) ) this.m_hidden=false; //--- Если указано - перерисовываем график if(chart_redraw) ::ChartRedraw(this.m_chart_id); } //+------------------------------------------------------------------+ //| CCanvasBase::Помещает объект на передний план | //+------------------------------------------------------------------+ void CCanvasBase::BringToTop(const bool chart_redraw) { this.Hide(false); this.Show(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в состояние по умолчанию | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToDefault(void) { bool res=true; res &=this.BackColorToDefault(); res &=this.ForeColorToDefault(); res &=this.BorderColorToDefault(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в состояние при наведении курсора | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToFocused(void) { bool res=true; res &=this.BackColorToFocused(); res &=this.ForeColorToFocused(); res &=this.BorderColorToFocused(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в состояние при нажатии курсора | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToPressed(void) { bool res=true; res &=this.BackColorToPressed(); res &=this.ForeColorToPressed(); res &=this.BorderColorToPressed(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Устанавливает текущие цвета | //| элемента в заблокированное состояние | //+------------------------------------------------------------------+ bool CCanvasBase::ColorsToBlocked(void) { bool res=true; res &=this.BackColorToBlocked(); res &=this.ForeColorToBlocked(); res &=this.BorderColorToBlocked(); return res; } //+------------------------------------------------------------------+ //| CCanvasBase::Блокирует элемент | //+------------------------------------------------------------------+ void CCanvasBase::Block(const bool chart_redraw) { //--- Если элемент уже заблокирован - уходим if(this.m_blocked) return; //--- Устанавливаем текущие цвета как цвета заблокированного элемента, //--- перерисовываем объект и устанавливаем флаг блокировки this.ColorsToBlocked(); this.Draw(chart_redraw); this.m_blocked=true; } //+------------------------------------------------------------------+ //| CCanvasBase::Разблокирует элемент | //+------------------------------------------------------------------+ void CCanvasBase::Unblock(const bool chart_redraw) { //--- Если элемент уже разблокирован - уходим if(!this.m_blocked) return; //--- Устанавливаем текущие цвета как цвета элемента в обычном состоянии, //--- перерисовываем объект и сбрасываем флаг блокировки this.ColorsToDefault(); this.Draw(chart_redraw); this.m_blocked=false; } //+------------------------------------------------------------------+ //| CCanvasBase::Заливает объект указанным цветом | //| с установленной в m_alpha прозрачностью | //+------------------------------------------------------------------+ void CCanvasBase::Fill(const color clr,const bool chart_redraw) { this.m_background.Erase(::ColorToARGB(clr,this.m_alpha)); this.m_background.Update(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Заливает объект прозрачным цветом | //+------------------------------------------------------------------+ void CCanvasBase::Clear(const bool chart_redraw) { this.m_background.Erase(clrNULL); this.m_foreground.Erase(clrNULL); this.Update(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Обновляет объект для отображения изменений | //+------------------------------------------------------------------+ void CCanvasBase::Update(const bool chart_redraw) { this.m_background.Update(false); this.m_foreground.Update(chart_redraw); } //+------------------------------------------------------------------+ //| CCanvasBase::Рисует внешний вид | //+------------------------------------------------------------------+ void CCanvasBase::Draw(const bool chart_redraw) { return; } //+------------------------------------------------------------------+ //| CCanvasBase::Уничтожает объект | //+------------------------------------------------------------------+ void CCanvasBase::Destroy(void) { this.m_background.Destroy(); this.m_foreground.Destroy(); } //+------------------------------------------------------------------+ //| CCanvasBase::Возвращает описание объекта | //+------------------------------------------------------------------+ string CCanvasBase::Description(void) { string nm=this.Name(); string name=(nm!="" ? ::StringFormat(" \"%s\"",nm) : nm); string area=::StringFormat("x %d, y %d, w %d, h %d",this.X(),this.Y(),this.Width(),this.Height()); return ::StringFormat("%s%s (%s, %s): ID %d, %s",ElementDescription((ENUM_ELEMENT_TYPE)this.Type()),name,this.NameBG(),this.NameFG(),this.ID(),area); } //+------------------------------------------------------------------+ //| CCanvasBase::Выводит в журнал описание объекта | //+------------------------------------------------------------------+ void CCanvasBase::Print(void) { ::Print(this.Description()); } //+------------------------------------------------------------------+ //| CCanvasBase::Сохранение в файл | //+------------------------------------------------------------------+ bool CCanvasBase::Save(const int file_handle) { //--- Метод временно отключен return false; //--- Проверяем хэндл if(file_handle==INVALID_HANDLE) return false; //--- Сохраняем маркер начала данных - 0xFFFFFFFFFFFFFFFF if(::FileWriteLong(file_handle,-1)!=sizeof(long)) return false; //--- Сохраняем тип объекта if(::FileWriteInteger(file_handle,this.Type(),INT_VALUE)!=INT_VALUE) return false; /* //--- Сохранение свойств */ //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| Загрузка из файла | //+------------------------------------------------------------------+ bool CCanvasBase::Load(const int file_handle) { //--- Метод временно отключен return false; //--- Проверяем хэндл if(file_handle==INVALID_HANDLE) return false; //--- Загружаем и проверяем маркер начала данных - 0xFFFFFFFFFFFFFFFF if(::FileReadLong(file_handle)!=-1) return false; //--- Загружаем тип объекта if(::FileReadInteger(file_handle,INT_VALUE)!=this.Type()) return false; /* //--- Загрузка свойств */ //--- Всё успешно return true; } //+------------------------------------------------------------------+