//+------------------------------------------------------------------+ //| Controls.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Включаемые библиотеки | //+------------------------------------------------------------------+ #include "Base.mqh" //+------------------------------------------------------------------+ //| Макроподстановки | //+------------------------------------------------------------------+ #define DEF_LABEL_W 40 // Ширина текстовой метки по умолчанию #define DEF_LABEL_H 16 // Высота текстовой метки по умолчанию #define DEF_BUTTON_W 50 // Ширина кнопки по умолчанию #define DEF_BUTTON_H 16 // Высота кнопки по умолчанию //+------------------------------------------------------------------+ //| Перечисления | //+------------------------------------------------------------------+ enum ENUM_ELEMENT_COMPARE_BY // Сравниваемые свойства { ELEMENT_SORT_BY_ID = 0, // Сравнение по идентификатору элемента ELEMENT_SORT_BY_NAME, // Сравнение по наименованию элемента ELEMENT_SORT_BY_TEXT, // Сравнение по тексту элемента ELEMENT_SORT_BY_COLOR, // Сравнение по цвету элемента ELEMENT_SORT_BY_ALPHA, // Сравнение по прозрачности элемента ELEMENT_SORT_BY_STATE, // Сравнение по состоянию элемента }; //+------------------------------------------------------------------+ //| Функции | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Классы | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Класс рисования изображений | //+------------------------------------------------------------------+ class CImagePainter : public CBaseObj { protected: CCanvas *m_canvas; // Указатель на канвас, где рисуем CBound m_bound; // Координаты и границы изображения uchar m_alpha; // Прозрачность //--- Проверяет валидность холста и корректность размеров bool CheckBound(void); public: //--- (1) Назначает канвас для рисования, (2) устанавливает, (3) возвращает прозрачность void CanvasAssign(CCanvas *canvas) { this.m_canvas=canvas; } void SetAlpha(const uchar value) { this.m_alpha=value; } uchar Alpha(void) const { return this.m_alpha; } //--- (1) Устанавливает координаты, (2) изменяет размеры области void SetXY(const int x,const int y) { this.m_bound.SetXY(x,y); } void SetSize(const int w,const int h) { this.m_bound.Resize(w,h); } //--- Устанавливает координаты и размеры области void SetBound(const int x,const int y,const int w,const int h) { this.SetXY(x,y); this.SetSize(w,h); } //--- Возвращает границы и размеры рисунка int X(void) const { return this.m_bound.X(); } int Y(void) const { return this.m_bound.Y(); } int Right(void) const { return this.m_bound.Right(); } int Bottom(void) const { return this.m_bound.Bottom(); } int Width(void) const { return this.m_bound.Width(); } int Height(void) const { return this.m_bound.Height(); } //--- Очищает область bool Clear(const int x,const int y,const int w,const int h,const bool update=true); //--- Рисует закрашенную стрелку (1) вверх, (2) вниз, (3) влево, (4) вправо bool ArrowUp(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); bool ArrowDown(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); bool ArrowLeft(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); bool ArrowRight(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); //--- Рисует (1) отмеченный, (2) неотмеченный CheckBox bool CheckedBox(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); bool UncheckedBox(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); //--- Рисует (1) отмеченный, (2) неотмеченный RadioButton bool CheckedRadioButton(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); bool UncheckedRadioButton(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true); //--- Виртуальные методы (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_IMAGE_PAINTER); } //--- Конструкторы/деструктор CImagePainter(void) : m_canvas(NULL) { this.SetBound(1,1,DEF_BUTTON_H-2,DEF_BUTTON_H-2); this.SetName("Image Painter"); } CImagePainter(CCanvas *canvas) : m_canvas(canvas) { this.SetBound(1,1,DEF_BUTTON_H-2,DEF_BUTTON_H-2); this.SetName("Image Painter"); } CImagePainter(CCanvas *canvas,const int id,const string name) : m_canvas(canvas) { this.m_id=id; this.SetName(name); this.SetBound(1,1,DEF_BUTTON_H-2,DEF_BUTTON_H-2); } CImagePainter(CCanvas *canvas,const int id,const int dx,const int dy,const int w,const int h,const string name) : m_canvas(canvas) { this.m_id=id; this.SetName(name); this.SetBound(dx,dy,w,h); } ~CImagePainter(void) {} }; //+------------------------------------------------------------------+ //| CImagePainter::Сравнение двух объектов | //+------------------------------------------------------------------+ int CImagePainter::Compare(const CObject *node,const int mode=0) const { const CImagePainter *obj=node; switch(mode) { case ELEMENT_SORT_BY_NAME : return(this.Name() >obj.Name() ? 1 : this.Name() obj.Alpha() ? 1 : this.Alpha()obj.ID() ? 1 : this.ID() obj.Name() ? 1 : this.Name() obj.Text() ? 1 : this.Text() obj.ForeColor() ? 1 : this.ForeColor()obj.AlphaFG() ? 1 : this.AlphaFG() obj.ID() ? 1 : this.ID() 0 && h>0) this.m_foreground.FillRectangle(this.AdjX(this.m_text_x),this.AdjY(this.m_text_y),this.AdjX(this.m_text_x+w),this.AdjY(this.m_text_y+h),clrNULL); //--- Иначе - очищаем полностью весь передний план else this.m_foreground.Erase(clrNULL); } //+------------------------------------------------------------------+ //| CLabel::Выводит текст | //+------------------------------------------------------------------+ void CLabel::DrawText(const int dx,const int dy,const string text,const bool chart_redraw) { //--- Очищаем прошлый текст и устанавливаем новый this.ClearText(); this.SetText(text); //--- Выводим установленный текст this.m_foreground.TextOut(this.AdjX(dx),this.AdjY(dy),this.Text(),::ColorToARGB(this.ForeColor(),this.AlphaFG())); //--- Если текст выходит за правую границу объекта if(this.Width()-dx0 && h>0) { //--- Стираем текст у правой границы объекта по размеру текста "троеточие" и заменяем троеточием окончание текста метки this.m_foreground.FillRectangle(this.AdjX(this.Width()-w),this.AdjY(this.m_text_y),this.AdjX(this.Width()),this.AdjY(this.m_text_y+h),clrNULL); this.m_foreground.TextOut(this.AdjX(this.Width()-w),this.AdjY(dy),"...",::ColorToARGB(this.ForeColor(),this.AlphaFG())); } } //--- Обновляем канвас переднего плана и запоминаем новые координаты текста this.m_foreground.Update(chart_redraw); this.m_text_x=dx; this.m_text_y=dy; //--- Запоминаем нарисованный текст как прошлый this.SetTextPrev(text); } //+------------------------------------------------------------------+ //| CLabel::Рисует внешний вид | //+------------------------------------------------------------------+ void CLabel::Draw(const bool chart_redraw) { this.DrawText(this.m_text_x,this.m_text_y,this.Text(),chart_redraw); } //+------------------------------------------------------------------+ //| CLabel::Сохранение в файл | //+------------------------------------------------------------------+ bool CLabel::Save(const int file_handle) { //--- Сохраняем данные родительского объекта if(!CCanvasBase::Save(file_handle)) return false; //--- Сохраняем текст if(::FileWriteArray(file_handle,this.m_text)!=sizeof(this.m_text)) return false; //--- Сохраняем предыдущий текст if(::FileWriteArray(file_handle,this.m_text_prev)!=sizeof(this.m_text_prev)) return false; //--- Сохраняем координату X текста if(::FileWriteInteger(file_handle,this.m_text_x,INT_VALUE)!=INT_VALUE) return false; //--- Сохраняем координату Y текста if(::FileWriteInteger(file_handle,this.m_text_y,INT_VALUE)!=INT_VALUE) return false; //--- Всё успешно return true; } //+------------------------------------------------------------------+ //| CLabel::Загрузка из файла | //+------------------------------------------------------------------+ bool CLabel::Load(const int file_handle) { //--- Загружаем данные родительского объекта if(!CCanvasBase::Load(file_handle)) return false; //--- Загружаем текст if(::FileReadArray(file_handle,this.m_text)!=sizeof(this.m_text)) return false; //--- Загружаем предыдущий текст if(::FileReadArray(file_handle,this.m_text_prev)!=sizeof(this.m_text_prev)) return false; //--- Загружаем координату X текста this.m_text_x=::FileReadInteger(file_handle,INT_VALUE); //--- Загружаем координату Y текста this.m_text_y=::FileReadInteger(file_handle,INT_VALUE); //--- Всё успешно return true; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Класс простой кнопки | //+------------------------------------------------------------------+ class CButton : public CLabel { public: //--- Рисует внешний вид virtual void Draw(const bool chart_redraw); //--- Виртуальные методы (1) сравнения, (2) сохранения в файл, (3) загрузки из файла, (4) тип объекта virtual int Compare(const CObject *node,const int mode=0) const; virtual bool Save(const int file_handle) { return CLabel::Save(file_handle); } virtual bool Load(const int file_handle) { return CLabel::Load(file_handle); } virtual int Type(void) const { return(ELEMENT_TYPE_BUTTON); } //--- Конструкторы/деструктор CButton(void); CButton(const string object_name, const string text, const int x, const int y, const int w, const int h); CButton(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h); CButton(const string object_name, const long chart_id, const int wnd, const string text, const int x, const int y, const int w, const int h); ~CButton (void) {} }; //+------------------------------------------------------------------+ //| CButton::Конструктор по умолчанию. Строит кнопку в главном окне | //| текущего графика в координатах 0,0 с размерами по умолчанию | //+------------------------------------------------------------------+ CButton::CButton(void) : CLabel("Button",::ChartID(),0,"Button",0,0,DEF_BUTTON_W,DEF_BUTTON_H) { this.SetState(ELEMENT_STATE_DEF); this.SetAlpha(255); } //+-------------------------------------------------------------------+ //| CButton::Конструктор параметрический. Строит кнопку в главном окне| //| текущего графика с указанными текстом, координами и размерами | //+-------------------------------------------------------------------+ CButton::CButton(const string object_name,const string text,const int x,const int y,const int w,const int h) : CLabel(object_name,::ChartID(),0,text,x,y,w,h) { this.SetState(ELEMENT_STATE_DEF); this.SetAlpha(255); } //+---------------------------------------------------------------------+ //| CButton::Конструктор параметрический. Строит кнопку в указанном окне| //| текущего графика с указанными текстом, координами и размерами | //+---------------------------------------------------------------------+ CButton::CButton(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) : CLabel(object_name,::ChartID(),wnd,text,x,y,w,h) { this.SetState(ELEMENT_STATE_DEF); this.SetAlpha(255); } //+---------------------------------------------------------------------+ //| CButton::Конструктор параметрический. Строит кнопку в указанном окне| //| указанного графика с указанными текстом, координами и размерами | //+---------------------------------------------------------------------+ CButton::CButton(const string object_name,const long chart_id,const int wnd,const string text,const int x,const int y,const int w,const int h) : CLabel(object_name,chart_id,wnd,text,x,y,w,h) { this.SetState(ELEMENT_STATE_DEF); this.SetAlpha(255); } //+------------------------------------------------------------------+ //| CButton::Сравнение двух объектов | //+------------------------------------------------------------------+ int CButton::Compare(const CObject *node,const int mode=0) const { const CButton *obj=node; switch(mode) { case ELEMENT_SORT_BY_NAME : return(this.Name() >obj.Name() ? 1 : this.Name() obj.Text() ? 1 : this.Text() obj.BackColor() ? 1 : this.BackColor()obj.AlphaBG() ? 1 : this.AlphaBG() obj.ID() ? 1 : this.ID() obj.Name() ? 1 : this.Name() obj.Text() ? 1 : this.Text() obj.BackColor() ? 1 : this.BackColor()obj.AlphaBG() ? 1 : this.AlphaBG() obj.State() ? 1 : this.State() obj.ID() ? 1 : this.ID()