Article-18658-MQL5-MVC-UI-C.../Controls/Controls.mqh
2026-03-30 08:53:02 +07:00

4210 Zeilen
246 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 50 // Ширина текстовой метки по умолчанию
#define DEF_LABEL_H 16 // Высота текстовой метки по умолчанию
#define DEF_BUTTON_W 60 // Ширина кнопки по умолчанию
#define DEF_BUTTON_H 16 // Высота кнопки по умолчанию
#define DEF_PANEL_W 80 // Ширина панели по умолчанию
#define DEF_PANEL_H 80 // Высота панели по умолчанию
#define DEF_SCROLLBAR_TH 13 // Толщина полосы прокрутки по умолчанию
#define DEF_THUMB_MIN_SIZE 8 // Минимальная толщина ползунка полосы прокрутки
#define DEF_AUTOREPEAT_DELAY 500 // Задержка перед запуском автоповтора
#define DEF_AUTOREPEAT_INTERVAL 100 // Частота автоповторов
//+------------------------------------------------------------------+
//| Перечисления |
//+------------------------------------------------------------------+
enum ENUM_ELEMENT_SORT_BY // Сравниваемые свойства
{
ELEMENT_SORT_BY_ID = BASE_SORT_BY_ID, // Сравнение по идентификатору элемента
ELEMENT_SORT_BY_NAME = BASE_SORT_BY_NAME, // Сравнение по наименованию элемента
ELEMENT_SORT_BY_X = BASE_SORT_BY_X, // Сравнение по координате X элемента
ELEMENT_SORT_BY_Y = BASE_SORT_BY_Y, // Сравнение по координате Y элемента
ELEMENT_SORT_BY_WIDTH= BASE_SORT_BY_WIDTH, // Сравнение по ширине элемента
ELEMENT_SORT_BY_HEIGHT= BASE_SORT_BY_HEIGHT, // Сравнение по высоте элемента
ELEMENT_SORT_BY_ZORDER= BASE_SORT_BY_ZORDER, // Сравнение по Z-order элемента
ELEMENT_SORT_BY_TEXT, // Сравнение по тексту элемента
ELEMENT_SORT_BY_COLOR_BG, // Сравнение по цвету фона элемента
ELEMENT_SORT_BY_ALPHA_BG, // Сравнение по прозрачности фона элемента
ELEMENT_SORT_BY_COLOR_FG, // Сравнение по цвету переднего плана элемента
ELEMENT_SORT_BY_ALPHA_FG, // Сравнение по прозрачности переднего плана элемента
ELEMENT_SORT_BY_STATE, // Сравнение по состоянию элемента
ELEMENT_SORT_BY_GROUP, // Сравнение по группе элемента
};
//+------------------------------------------------------------------+
//| Функции |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Классы |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс связанного списка объектов |
//+------------------------------------------------------------------+
class CListObj : public CList
{
protected:
ENUM_ELEMENT_TYPE m_element_type; // Тип создаваемого объекта в CreateElement()
public:
//--- Установка типа элемента
void SetElementType(const ENUM_ELEMENT_TYPE type) { this.m_element_type=type; }
//--- Виртуальный метод (1) загрузки списка из файла, (2) создания элемента списка
virtual bool Load(const int file_handle);
virtual CObject *CreateElement(void);
};
//+------------------------------------------------------------------+
//| Загрузка списка из файла |
//+------------------------------------------------------------------+
bool CListObj::Load(const int file_handle)
{
//--- Переменные
CObject *node;
bool result=true;
//--- Проверяем хэндл
if(file_handle==INVALID_HANDLE)
return(false);
//--- Загрузка и проверка маркера начала списка - 0xFFFFFFFFFFFFFFFF
if(::FileReadLong(file_handle)!=MARKER_START_DATA)
return(false);
//--- Загрузка и проверка типа списка
if(::FileReadInteger(file_handle,INT_VALUE)!=this.Type())
return(false);
//--- Чтение размера списка (количество объектов)
uint num=::FileReadInteger(file_handle,INT_VALUE);
//--- Последовательно заново создаём элементы списка с помощью вызова метода Load() объектов node
this.Clear();
for(uint i=0; i<num; i++)
{
//--- Читаем и проверяем маркер начала данных объекта - 0xFFFFFFFFFFFFFFFF
if(::FileReadLong(file_handle)!=MARKER_START_DATA)
return false;
//--- Читаем тип объекта
this.m_element_type=(ENUM_ELEMENT_TYPE)::FileReadInteger(file_handle,INT_VALUE);
node=this.CreateElement();
if(node==NULL)
return false;
this.Add(node);
//--- Сейчас файловый указатель смещён относительно начала маркера объекта на 12 байт (8 - маркер, 4 - тип)
//--- Поставим указатель на начало данных объекта и загрузим свойства объекта из файла методом Load() элемента node.
if(!::FileSeek(file_handle,-12,SEEK_CUR))
return false;
result &=node.Load(file_handle);
}
//--- Результат
return result;
}
//+------------------------------------------------------------------+
//| Метод создания элемента списка |
//+------------------------------------------------------------------+
CObject *CListObj::CreateElement(void)
{
//--- В зависимости от типа объекта в m_element_type, создаём новый объект
switch(this.m_element_type)
{
case ELEMENT_TYPE_BASE : return new CBaseObj(); // Базовый объект графических элементов
case ELEMENT_TYPE_COLOR : return new CColor(); // Объект цвета
case ELEMENT_TYPE_COLORS_ELEMENT : return new CColorElement(); // Объект цветов элемента графического объекта
case ELEMENT_TYPE_RECTANGLE_AREA : return new CBound(); // Прямоугольная область элемента
case ELEMENT_TYPE_IMAGE_PAINTER : return new CImagePainter(); // Объект для рисования изображений
case ELEMENT_TYPE_CANVAS_BASE : return new CCanvasBase(); // Базовый объект холста графических элементов
case ELEMENT_TYPE_ELEMENT_BASE : return new CElementBase(); // Базовый объект графических элементов
case ELEMENT_TYPE_LABEL : return new CLabel(); // Текстовая метка
case ELEMENT_TYPE_BUTTON : return new CButton(); // Простая кнопка
case ELEMENT_TYPE_BUTTON_TRIGGERED : return new CButtonTriggered(); // Двухпозиционная кнопка
case ELEMENT_TYPE_BUTTON_ARROW_UP : return new CButtonArrowUp(); // Кнопка со стрелкой вверх
case ELEMENT_TYPE_BUTTON_ARROW_DOWN : return new CButtonArrowDown(); // Кнопка со стрелкой вниз
case ELEMENT_TYPE_BUTTON_ARROW_LEFT : return new CButtonArrowLeft(); // Кнопка со стрелкой влево
case ELEMENT_TYPE_BUTTON_ARROW_RIGHT: return new CButtonArrowRight(); // Кнопка со стрелкой вправо
case ELEMENT_TYPE_CHECKBOX : return new CCheckBox(); // Элемент управления CheckBox
case ELEMENT_TYPE_RADIOBUTTON : return new CRadioButton(); // Элемент управления RadioButton
case ELEMENT_TYPE_PANEL : return new CPanel(); // Элемент управления Panel
case ELEMENT_TYPE_GROUPBOX : return new CGroupBox(); // Элемент управления GroupBox
case ELEMENT_TYPE_CONTAINER : return new CContainer(); // Элемент управления GroupBox
default : return NULL;
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс рисования изображений |
//+------------------------------------------------------------------+
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);
//--- Рисует рамку группы элементов
bool FrameGroupElements(const int x,const int y,const int w,const int h,const string text,
const color clr_text,const color clr_dark,const color clr_light,
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
{
if(node==NULL)
return -1;
const CImagePainter *obj=node;
switch(mode)
{
case ELEMENT_SORT_BY_NAME : return(this.Name() >obj.Name() ? 1 : this.Name() <obj.Name() ? -1 : 0);
case ELEMENT_SORT_BY_ALPHA_FG :
case ELEMENT_SORT_BY_ALPHA_BG : return(this.Alpha() >obj.Alpha() ? 1 : this.Alpha() <obj.Alpha() ? -1 : 0);
case ELEMENT_SORT_BY_X : return(this.X() >obj.X() ? 1 : this.X() <obj.X() ? -1 : 0);
case ELEMENT_SORT_BY_Y : return(this.Y() >obj.Y() ? 1 : this.Y() <obj.Y() ? -1 : 0);
case ELEMENT_SORT_BY_WIDTH : return(this.Width() >obj.Width() ? 1 : this.Width() <obj.Width() ? -1 : 0);
case ELEMENT_SORT_BY_HEIGHT : return(this.Height() >obj.Height() ? 1 : this.Height() <obj.Height() ? -1 : 0);
default : return(this.ID() >obj.ID() ? 1 : this.ID() <obj.ID() ? -1 : 0);
}
}
//+------------------------------------------------------------------+
//|CImagePainter::Проверяет валидность холста и корректность размеров|
//+------------------------------------------------------------------+
bool CImagePainter::CheckBound(void)
{
if(this.m_canvas==NULL)
{
::PrintFormat("%s: Error. First you need to assign the canvas using the CanvasAssign() method",__FUNCTION__);
return false;
}
if(this.Width()==0 || this.Height()==0)
{
::PrintFormat("%s: Error. First you need to set the area size using the SetSize() or SetBound() methods",__FUNCTION__);
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Очищает область |
//+------------------------------------------------------------------+
bool CImagePainter::Clear(const int x,const int y,const int w,const int h,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Очищаем прозрачным цветом всю область изображения
this.m_canvas.FillRectangle(x,y,x+w-1,y+h-1,clrNULL);
//--- Если указано - обновляем канвас
if(update)
this.m_canvas.Update(false);
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует закрашенную стрелку вверх |
//+------------------------------------------------------------------+
bool CImagePainter::ArrowUp(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Рассчитываем координаты углов стрелки внутри области изображения
int hw=(int)::floor(w/2); // Половина ширины
if(hw==0)
hw=1;
int x1 = x + 1; // X. Основание (левая точка)
int y1 = y + h - 4; // Y. Левая точка основания
int x2 = x1 + hw; // X. Вершина (центральная верхняя точка)
int y2 = y + 3; // Y. Вершина (верхняя точка)
int x3 = x1 + w - 1; // X. Основание (правая точка)
int y3 = y1; // Y. Основание (правая точка)
//--- Рисуем треугольник
this.m_canvas.FillTriangle(x1, y1, x2, y2, x3, y3, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует закрашенную стрелку вниз |
//+------------------------------------------------------------------+
bool CImagePainter::ArrowDown(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Рассчитываем координаты углов стрелки внутри области изображения
int hw=(int)::floor(w/2); // Половина ширины
if(hw==0)
hw=1;
int x1=x+1; // X. Основание (левая точка)
int y1=y+4; // Y. Левая точка основания
int x2=x1+hw; // X. Вершина (центральная нижняя точка)
int y2=y+h-3; // Y. Вершина (нижняя точка)
int x3=x1+w-1; // X. Основание (правая точка)
int y3=y1; // Y. Основание (правая точка)
//--- Рисуем треугольник
this.m_canvas.FillTriangle(x1, y1, x2, y2, x3, y3, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует закрашенную стрелку влево |
//+------------------------------------------------------------------+
bool CImagePainter::ArrowLeft(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Рассчитываем координаты углов стрелки внутри области изображения
int hh=(int)::floor(h/2); // Половина высоты
if(hh==0)
hh=1;
int x1=x+w-4; // X. Основание (правая сторона)
int y1=y+1; // Y. Верхний угол основания
int x2=x+3; // X. Вершина (левая центральная точка)
int y2=y1+hh; // Y. Центральная точка (вершина)
int x3=x1; // X. Нижний угол основания
int y3=y1+h-1; // Y. Нижний угол основания
//--- Рисуем треугольник
this.m_canvas.FillTriangle(x1, y1, x2, y2, x3, y3, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует закрашенную стрелку вправо |
//+------------------------------------------------------------------+
bool CImagePainter::ArrowRight(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Рассчитываем координаты углов стрелки внутри области изображения
int hh=(int)::floor(h/2); // Половина высоты
if(hh==0)
hh=1;
int x1=x+4; // X. Основание треугольника (левая сторона)
int y1=y+1; // Y. Верхний угол основания
int x2=x+w-3; // X. Вершина (правая центральная точка)
int y2=y1+hh; // Y. Центральная точка (вершина)
int x3=x1; // X. Нижний угол основания
int y3=y1+h-1; // Y. Нижний угол основания
//--- Рисуем треугольник
this.m_canvas.FillTriangle(x1, y1, x2, y2, x3, y3, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует отмеченный CheckBox |
//+------------------------------------------------------------------+
bool CImagePainter::CheckedBox(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Координаты прямоугольника
int x1=x+1; // Левый верхний угол, X
int y1=y+1; // Левый верхний угол, Y
int x2=x+w-2; // Правый нижний угол, X
int y2=y+h-2; // Правый нижний угол, Y
//--- Рисуем прямоугольник
this.m_canvas.Rectangle(x1, y1, x2, y2, ::ColorToARGB(clr, alpha));
//--- Координаты "галочки"
int arrx[3], arry[3];
arrx[0]=x1+(x2-x1)/4; // X. Левая точка
arrx[1]=x1+w/3; // X. Центральная точка
arrx[2]=x2-(x2-x1)/4; // X. Правая точка
arry[0]=y1+1+(y2-y1)/2; // Y. Левая точка
arry[1]=y2-(y2-y1)/3; // Y. Центральная точка
arry[2]=y1+(y2-y1)/3; // Y. Правая точка
//--- Рисуем "галочку" линией двойной толщины
this.m_canvas.Polyline(arrx, arry, ::ColorToARGB(clr, alpha));
arrx[0]++;
arrx[1]++;
arrx[2]++;
this.m_canvas.Polyline(arrx, arry, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует неотмеченный CheckBox |
//+------------------------------------------------------------------+
bool CImagePainter::UncheckedBox(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Координаты прямоугольника
int x1=x+1; // Левый верхний угол, X
int y1=y+1; // Левый верхний угол, Y
int x2=x+w-2; // Правый нижний угол, X
int y2=y+h-2; // Правый нижний угол, Y
//--- Рисуем прямоугольник
this.m_canvas.Rectangle(x1, y1, x2, y2, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует отмеченный RadioButton |
//+------------------------------------------------------------------+
bool CImagePainter::CheckedRadioButton(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Координаты и радиус окружности
int x1=x+1; // Левый верхний угол области окружности, X
int y1=y+1; // Левый верхний угол области окружности, Y
int x2=x+w-2; // Правый нижний угол области окружности, X
int y2=y+h-2; // Правый нижний угол области окружности, Y
//--- Координаты и радиус окружности
int d=::fmin(x2-x1,y2-y1); // Диаметр по меньшей стороне (ширина или высота)
int r=d/2; // Радиус
if(r<2)
r=2;
int cx=x1+r; // Координата X центра
int cy=y1+r; // Координата Y центра
//--- Рисуем окружность
this.m_canvas.CircleWu(cx, cy, r, ::ColorToARGB(clr, alpha));
//--- Радиус "метки"
r/=2;
if(r<1)
r=1;
//--- Рисуем метку
this.m_canvas.FillCircle(cx, cy, r, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Рисует неотмеченный RadioButton |
//+------------------------------------------------------------------+
bool CImagePainter::UncheckedRadioButton(const int x,const int y,const int w,const int h,const color clr,const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Координаты и радиус окружности
int x1=x+1; // Левый верхний угол области окружности, X
int y1=y+1; // Левый верхний угол области окружности, Y
int x2=x+w-2; // Правый нижний угол области окружности, X
int y2=y+h-2; // Правый нижний угол области окружности, Y
//--- Координаты и радиус окружности
int d=::fmin(x2-x1,y2-y1); // Диаметр по меньшей стороне (ширина или высота)
int r=d/2; // Радиус
int cx=x1+r; // Координата X центра
int cy=y1+r; // Координата Y центра
//--- Рисуем окружность
this.m_canvas.CircleWu(cx, cy, r, ::ColorToARGB(clr, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| Рисует рамку группы элементов |
//+------------------------------------------------------------------+
bool CImagePainter::FrameGroupElements(const int x,const int y,const int w,const int h,const string text,
const color clr_text,const color clr_dark,const color clr_light,
const uchar alpha,const bool update=true)
{
//--- Если область изображения не валидна - возвращаем false
if(!this.CheckBound())
return false;
//--- Корректировка координаты Y
int tw=0, th=0;
if(text!="" && text!=NULL)
this.m_canvas.TextSize(text,tw,th);
int shift_v=int(th!=0 ? ::ceil(th/2) : 0);
//--- Координаты и размеры рамки
int x1=x; // Левый верхний угол области рамки, X
int y1=y+shift_v; // Левый верхний угол области рамки, Y
int x2=x+w-1; // Правый нижний угол области рамки, X
int y2=y+h-1; // Правый нижний угол области рамки, Y
//--- Рисуем левую-верхнюю часть рамки
int arrx[3], arry[3];
arrx[0]=arrx[1]=x1;
arrx[2]=x2-1;
arry[0]=y2;
arry[1]=arry[2]=y1;
this.m_canvas.Polyline(arrx, arry, ::ColorToARGB(clr_dark, alpha));
arrx[0]++;
arrx[1]++;
arry[1]++;
arry[2]++;
this.m_canvas.Polyline(arrx, arry, ::ColorToARGB(clr_light, alpha));
//--- Рисуем правую-нижнюю часть рамки
arrx[0]=arrx[1]=x2-1;
arrx[2]=x1+1;
arry[0]=y1;
arry[1]=arry[2]=y2-1;
this.m_canvas.Polyline(arrx, arry, ::ColorToARGB(clr_dark, alpha));
arrx[0]++;
arrx[1]++;
arry[1]++;
arry[2]++;
this.m_canvas.Polyline(arrx, arry, ::ColorToARGB(clr_light, alpha));
if(tw>0)
this.m_canvas.FillRectangle(x+5,y,x+7+tw,y+th,clrNULL);
this.m_canvas.TextOut(x+6,y-1,text,::ColorToARGB(clr_text, alpha));
if(update)
this.m_canvas.Update(false);
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Сохранение в файл |
//+------------------------------------------------------------------+
bool CImagePainter::Save(const int file_handle)
{
//--- Сохраняем данные родительского объекта
if(!CBaseObj::Save(file_handle))
return false;
//--- Сохраняем прозрачность
if(::FileWriteInteger(file_handle,this.m_alpha,INT_VALUE)!=INT_VALUE)
return false;
//--- Сохраняем данные области
if(!this.m_bound.Save(file_handle))
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CImagePainter::Загрузка из файла |
//+------------------------------------------------------------------+
bool CImagePainter::Load(const int file_handle)
{
//--- Загружаем данные родительского объекта
if(!CBaseObj::Load(file_handle))
return false;
//--- Загружаем прозрачность
this.m_alpha=(uchar)::FileReadInteger(file_handle,INT_VALUE);
//--- Загружаем данные области
if(!this.m_bound.Load(file_handle))
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Базовый класс графического элемента |
//+------------------------------------------------------------------+
class CElementBase : public CCanvasBase
{
protected:
CImagePainter m_painter; // Класс рисования
int m_group; // Группа элементов
public:
//--- Возвращает указатель на класс рисования
CImagePainter *Painter(void) { return &this.m_painter; }
//--- (1) Устанавливает координаты, (2) изменяет размеры области изображения
void SetImageXY(const int x,const int y) { this.m_painter.SetXY(x,y); }
void SetImageSize(const int w,const int h) { this.m_painter.SetSize(w,h); }
//--- Устанавливает координаты и размеры области изображения
void SetImageBound(const int x,const int y,const int w,const int h)
{
this.SetImageXY(x,y);
this.SetImageSize(w,h);
}
//--- Возвращает координату (1) X, (2) Y, (3) ширину, (4) высоту, (5) правую, (6) нижнюю границу области изображения
int ImageX(void) const { return this.m_painter.X(); }
int ImageY(void) const { return this.m_painter.Y(); }
int ImageWidth(void) const { return this.m_painter.Width(); }
int ImageHeight(void) const { return this.m_painter.Height(); }
int ImageRight(void) const { return this.m_painter.Right(); }
int ImageBottom(void) const { return this.m_painter.Bottom(); }
//--- (1) Устанавливает, (2) возвращает группу элементов
virtual void SetGroup(const int group) { this.m_group=group; }
int Group(void) const { return this.m_group; }
//--- Возвращает описание объекта
virtual string Description(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_ELEMENT_BASE);}
//--- Конструкторы/деструктор
CElementBase(void) {}
CElementBase(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CElementBase(void) {}
};
//+----------------------------------------------------------------------+
//| CElementBase::Конструктор параметрический. Строит элемент в указанном|
//| окне указанного графика с указанными текстом, координами и размерами |
//+----------------------------------------------------------------------+
CElementBase::CElementBase(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CCanvasBase(object_name,chart_id,wnd,x,y,w,h),m_group(-1)
{
//--- Объекту рисования назначаем канвас переднего плана и
//--- обнуляем координаты и размеры, что делает его неактивным
this.m_painter.CanvasAssign(this.GetForeground());
this.m_painter.SetXY(0,0);
this.m_painter.SetSize(0,0);
}
//+------------------------------------------------------------------+
//| CElementBase::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CElementBase::Compare(const CObject *node,const int mode=0) const
{
if(node==NULL)
return -1;
const CElementBase *obj=node;
switch(mode)
{
case ELEMENT_SORT_BY_NAME : return(this.Name() >obj.Name() ? 1 : this.Name() <obj.Name() ? -1 : 0);
case ELEMENT_SORT_BY_X : return(this.X() >obj.X() ? 1 : this.X() <obj.X() ? -1 : 0);
case ELEMENT_SORT_BY_Y : return(this.Y() >obj.Y() ? 1 : this.Y() <obj.Y() ? -1 : 0);
case ELEMENT_SORT_BY_WIDTH : return(this.Width() >obj.Width() ? 1 : this.Width() <obj.Width() ? -1 : 0);
case ELEMENT_SORT_BY_HEIGHT : return(this.Height() >obj.Height() ? 1 : this.Height() <obj.Height() ? -1 : 0);
case ELEMENT_SORT_BY_COLOR_BG : return(this.BackColor() >obj.BackColor() ? 1 : this.BackColor() <obj.BackColor() ? -1 : 0);
case ELEMENT_SORT_BY_COLOR_FG : return(this.ForeColor() >obj.ForeColor() ? 1 : this.ForeColor() <obj.ForeColor() ? -1 : 0);
case ELEMENT_SORT_BY_ALPHA_BG : return(this.AlphaBG() >obj.AlphaBG() ? 1 : this.AlphaBG() <obj.AlphaBG() ? -1 : 0);
case ELEMENT_SORT_BY_ALPHA_FG : return(this.AlphaFG() >obj.AlphaFG() ? 1 : this.AlphaFG() <obj.AlphaFG() ? -1 : 0);
case ELEMENT_SORT_BY_STATE : return(this.State() >obj.State() ? 1 : this.State() <obj.State() ? -1 : 0);
case ELEMENT_SORT_BY_GROUP : return(this.Group() >obj.Group() ? 1 : this.Group() <obj.Group() ? -1 : 0);
case ELEMENT_SORT_BY_ZORDER : return(this.ObjectZOrder() >obj.ObjectZOrder() ? 1 : this.ObjectZOrder() <obj.ObjectZOrder() ? -1 : 0);
default : return(this.ID() >obj.ID() ? 1 : this.ID() <obj.ID() ? -1 : 0);
}
}
//+------------------------------------------------------------------+
//| CElementBase::Возвращает описание объекта |
//+------------------------------------------------------------------+
string CElementBase::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, Group %d, %s",ElementDescription((ENUM_ELEMENT_TYPE)this.Type()),name,this.NameBG(),this.NameFG(),this.ID(),this.Group(),area);
}
//+------------------------------------------------------------------+
//| CElementBase::Сохранение в файл |
//+------------------------------------------------------------------+
bool CElementBase::Save(const int file_handle)
{
//--- Сохраняем данные родительского объекта
if(!CCanvasBase::Save(file_handle))
return false;
//--- Сохраняем объект изображения
if(!this.m_painter.Save(file_handle))
return false;
//--- Сохраняем группу
if(::FileWriteInteger(file_handle,this.m_group,INT_VALUE)!=INT_VALUE)
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CElementBase::Загрузка из файла |
//+------------------------------------------------------------------+
bool CElementBase::Load(const int file_handle)
{
//--- Загружаем данные родительского объекта
if(!CCanvasBase::Load(file_handle))
return false;
//--- Загружаем объект изображения
if(!this.m_painter.Load(file_handle))
return false;
//--- Загружаем группу
this.m_group=::FileReadInteger(file_handle,INT_VALUE);
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс текстовой метки |
//+------------------------------------------------------------------+
class CLabel : public CElementBase
{
protected:
ushort m_text[]; // Текст
ushort m_text_prev[]; // Прошлый текст
int m_text_x; // Координата X текста (смещение относительно левой границы объекта)
int m_text_y; // Координата Y текста (смещение относительно верхней границы объекта)
//--- (1) Устанавливает, (2) возвращает прошлый текст
void SetTextPrev(const string text) { ::StringToShortArray(text,this.m_text_prev); }
string TextPrev(void) const { return ::ShortArrayToString(this.m_text_prev);}
//--- Стирает текст
void ClearText(void);
public:
//--- (1) Устанавливает, (2) возвращает текст
void SetText(const string text) { ::StringToShortArray(text,this.m_text); }
string Text(void) const { return ::ShortArrayToString(this.m_text); }
//--- Возвращает координату (1) X, (2) Y текста
int TextX(void) const { return this.m_text_x; }
int TextY(void) const { return this.m_text_y; }
//--- Устанавливает координату (1) X, (2) Y текста
void SetTextShiftH(const int x) { this.ClearText(); this.m_text_x=x; }
void SetTextShiftV(const int y) { this.ClearText(); this.m_text_y=y; }
//--- Выводит текст
void DrawText(const int dx, const int dy, const string text, const bool chart_redraw);
//--- Рисует внешний вид
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);
virtual bool Load(const int file_handle);
virtual int Type(void) const { return(ELEMENT_TYPE_LABEL); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void){}
//--- Конструкторы/деструктор
CLabel(void);
CLabel(const string object_name, const string text, const int x, const int y, const int w, const int h);
CLabel(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CLabel(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CLabel(void) {}
};
//+------------------------------------------------------------------+
//| CLabel::Конструктор по умолчанию. Строит метку в главном окне |
//| текущего графика в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CLabel::CLabel(void) : CElementBase("Label","Label",::ChartID(),0,0,0,DEF_LABEL_W,DEF_LABEL_H), m_text_x(0), m_text_y(0)
{
//--- Инициализация
this.Init("Label");
}
//+------------------------------------------------------------------+
//| CLabel::Конструктор параметрический. Строит метку в главном окне |
//| текущего графика с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CLabel::CLabel(const string object_name, const string text,const int x,const int y,const int w,const int h) :
CElementBase(object_name,text,::ChartID(),0,x,y,w,h), m_text_x(0), m_text_y(0)
{
//--- Инициализация
this.Init(text);
}
//+-------------------------------------------------------------------+
//| CLabel::Конструктор параметрический. Строит метку в указанном окне|
//| текущего графика с указанными текстом, координами и размерами |
//+-------------------------------------------------------------------+
CLabel::CLabel(const string object_name, const string text,const int wnd,const int x,const int y,const int w,const int h) :
CElementBase(object_name,text,::ChartID(),wnd,x,y,w,h), m_text_x(0), m_text_y(0)
{
//--- Инициализация
this.Init(text);
}
//+-------------------------------------------------------------------+
//| CLabel::Конструктор параметрический. Строит метку в указанном окне|
//| указанного графика с указанными текстом, координами и размерами |
//+-------------------------------------------------------------------+
CLabel::CLabel(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CElementBase(object_name,text,chart_id,wnd,x,y,w,h), m_text_x(0), m_text_y(0)
{
//--- Инициализация
this.Init(text);
}
//+------------------------------------------------------------------+
//| CLabel::Инициализация |
//+------------------------------------------------------------------+
void CLabel::Init(const string text)
{
//--- Устанавливаем текущий и предыдущий текст
this.SetText(text);
this.SetTextPrev("");
//--- Фон - прозрачный, передний план - нет
this.SetAlphaBG(0);
this.SetAlphaFG(255);
}
//+------------------------------------------------------------------+
//| CLabel::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CLabel::Compare(const CObject *node,const int mode=0) const
{
if(node==NULL)
return -1;
const CLabel *obj=node;
switch(mode)
{
case ELEMENT_SORT_BY_NAME : return(this.Name() >obj.Name() ? 1 : this.Name() <obj.Name() ? -1 : 0);
case ELEMENT_SORT_BY_TEXT : return(this.Text() >obj.Text() ? 1 : this.Text() <obj.Text() ? -1 : 0);
case ELEMENT_SORT_BY_X : return(this.X() >obj.X() ? 1 : this.X() <obj.X() ? -1 : 0);
case ELEMENT_SORT_BY_Y : return(this.Y() >obj.Y() ? 1 : this.Y() <obj.Y() ? -1 : 0);
case ELEMENT_SORT_BY_WIDTH : return(this.Width() >obj.Width() ? 1 : this.Width() <obj.Width() ? -1 : 0);
case ELEMENT_SORT_BY_HEIGHT : return(this.Height() >obj.Height() ? 1 : this.Height() <obj.Height() ? -1 : 0);
case ELEMENT_SORT_BY_COLOR_BG : return(this.BackColor() >obj.BackColor() ? 1 : this.BackColor() <obj.BackColor() ? -1 : 0);
case ELEMENT_SORT_BY_COLOR_FG : return(this.ForeColor() >obj.ForeColor() ? 1 : this.ForeColor() <obj.ForeColor() ? -1 : 0);
case ELEMENT_SORT_BY_ALPHA_BG : return(this.AlphaBG() >obj.AlphaBG() ? 1 : this.AlphaBG() <obj.AlphaBG() ? -1 : 0);
case ELEMENT_SORT_BY_ALPHA_FG : return(this.AlphaFG() >obj.AlphaFG() ? 1 : this.AlphaFG() <obj.AlphaFG() ? -1 : 0);
case ELEMENT_SORT_BY_STATE : return(this.State() >obj.State() ? 1 : this.State() <obj.State() ? -1 : 0);
case ELEMENT_SORT_BY_ZORDER : return(this.ObjectZOrder() >obj.ObjectZOrder() ? 1 : this.ObjectZOrder() <obj.ObjectZOrder() ? -1 : 0);
default : return(this.ID() >obj.ID() ? 1 : this.ID() <obj.ID() ? -1 : 0);
}
}
//+------------------------------------------------------------------+
//| CLabel::Стирает текст |
//+------------------------------------------------------------------+
void CLabel::ClearText(void)
{
int w=0, h=0;
string text=this.TextPrev();
//--- Получаем размеры прошлого текста
if(text!="")
this.m_foreground.TextSize(text,w,h);
//--- Если размеры получены - рисуем на месте текста прозрачный прямоугольник, стирая текст
if(w>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()-dx<this.m_foreground.TextWidth(text))
{
//--- Получаем размеры текста "троеточие"
int w=0,h=0;
this.m_foreground.TextSize("... ",w,h);
if(w>0 && 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(!CElementBase::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(!CElementBase::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); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void){}
//--- Обработчик события таймера
virtual void TimerEventHandler(void);
//--- Конструкторы/деструктор
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 string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CButton (void) {}
};
//+------------------------------------------------------------------+
//| CButton::Конструктор по умолчанию. Строит кнопку в главном окне |
//| текущего графика в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CButton::CButton(void) : CLabel("Button","Button",::ChartID(),0,0,0,DEF_BUTTON_W,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+-------------------------------------------------------------------+
//| 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,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+---------------------------------------------------------------------+
//| 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,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+---------------------------------------------------------------------+
//| CButton::Конструктор параметрический. Строит кнопку в указанном окне|
//| указанного графика с указанными текстом, координами и размерами |
//+---------------------------------------------------------------------+
CButton::CButton(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CLabel(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButton::Инициализация |
//+------------------------------------------------------------------+
void CButton::Init(const string text)
{
//--- Устанавливаем состояние по умолчанию
this.SetState(ELEMENT_STATE_DEF);
//--- Фон и передний план - непрозрачные
this.SetAlpha(255);
//--- Смещение текста от левого края кнопки по умолчанию
this.m_text_x=2;
//--- Автоповтор нажатий отключен
this.m_autorepeat_flag=false;
}
//+------------------------------------------------------------------+
//| CButton::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CButton::Compare(const CObject *node,const int mode=0) const
{
return CLabel::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CButton::Рисует внешний вид |
//+------------------------------------------------------------------+
void CButton::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| Обработчик события таймера |
//+------------------------------------------------------------------+
void CButton::TimerEventHandler(void)
{
if(this.m_autorepeat_flag)
this.m_autorepeat.Process();
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс двухпозиционной кнопки |
//+------------------------------------------------------------------+
class CButtonTriggered : public CButton
{
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 CButton::Save(file_handle); }
virtual bool Load(const int file_handle) { return CButton::Load(file_handle); }
virtual int Type(void) const { return(ELEMENT_TYPE_BUTTON_TRIGGERED); }
//--- Обработчик событий нажатий кнопок мышки (Press)
virtual void OnPressEvent(const int id, const long lparam, const double dparam, const string sparam);
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void);
//--- Конструкторы/деструктор
CButtonTriggered(void);
CButtonTriggered(const string object_name, const string text, const int x, const int y, const int w, const int h);
CButtonTriggered(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CButtonTriggered(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CButtonTriggered (void) {}
};
//+------------------------------------------------------------------+
//| CButtonTriggered::Конструктор по умолчанию. |
//| Строит кнопку в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CButtonTriggered::CButtonTriggered(void) : CButton("Button","Button",::ChartID(),0,0,0,DEF_BUTTON_W,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Конструктор параметрический. |
//| Строит кнопку в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonTriggered::CButtonTriggered(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Конструктор параметрический. |
//| Строит кнопку в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonTriggered::CButtonTriggered(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Конструктор параметрический. |
//| Строит кнопку в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonTriggered::CButtonTriggered(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Инициализация |
//+------------------------------------------------------------------+
void CButtonTriggered::Init(const string text)
{
//--- Инициализируем цвета по умолчанию
this.InitColors();
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Инициализация цветов объекта по умолчанию |
//+------------------------------------------------------------------+
void CButtonTriggered::InitColors(void)
{
//--- Инициализируем цвета заднего плана для обычного и активированного состояний и делаем его текущим цветом фона
this.InitBackColors(clrWhiteSmoke);
this.InitBackColorsAct(clrLightBlue);
this.BackColorToDefault();
//--- Инициализируем цвета переднего плана для обычного и активированного состояний и делаем его текущим цветом текста
this.InitForeColors(clrBlack);
this.InitForeColorsAct(clrBlack);
this.ForeColorToDefault();
//--- Инициализируем цвета рамки для обычного и активированного состояний и делаем его текущим цветом рамки
this.InitBorderColors(clrDarkGray);
this.InitBorderColorsAct(clrGreen);
this.BorderColorToDefault();
//--- Инициализируем цвет рамки и цвет переднего плана для заблокированного элемента
this.InitBorderColorBlocked(clrLightGray);
this.InitForeColorBlocked(clrSilver);
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CButtonTriggered::Compare(const CObject *node,const int mode=0) const
{
return CButton::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Рисует внешний вид |
//+------------------------------------------------------------------+
void CButtonTriggered::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CButtonTriggered::Обработчик событий нажатий кнопок мышки (Press)|
//+------------------------------------------------------------------+
void CButtonTriggered::OnPressEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Устанавливаем состояние кнопки, обратное уже установленному
ENUM_ELEMENT_STATE state=(this.State()==ELEMENT_STATE_DEF ? ELEMENT_STATE_ACT : ELEMENT_STATE_DEF);
this.SetState(state);
//--- Вызываем обработчик родительского объекта с указанием идентификатора в lparam и состояния в dparam
CCanvasBase::OnPressEvent(id,this.m_id,this.m_state,sparam);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс кнопки со стрелкой вверх |
//+------------------------------------------------------------------+
class CButtonArrowUp : public CButton
{
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 CButton::Save(file_handle); }
virtual bool Load(const int file_handle) { return CButton::Load(file_handle); }
virtual int Type(void) const { return(ELEMENT_TYPE_BUTTON_ARROW_UP);}
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void){}
//--- Конструкторы/деструктор
CButtonArrowUp(void);
CButtonArrowUp(const string object_name, const string text, const int x, const int y, const int w, const int h);
CButtonArrowUp(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CButtonArrowUp(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CButtonArrowUp (void) {}
};
//+------------------------------------------------------------------+
//| CButtonArrowUp::Конструктор по умолчанию. |
//| Строит кнопку в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CButtonArrowUp::CButtonArrowUp(void) : CButton("Arrow Up Button","",::ChartID(),0,0,0,DEF_BUTTON_W,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowUp::Конструктор параметрический. |
//| Строит кнопку в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowUp::CButtonArrowUp(const string object_name, const string text,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowUp::Конструктор параметрический. |
//| Строит кнопку в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowUp::CButtonArrowUp(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowUp::Конструктор параметрический. |
//| Строит кнопку в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowUp::CButtonArrowUp(const string object_name, const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowUp::Инициализация |
//+------------------------------------------------------------------+
void CButtonArrowUp::Init(const string text)
{
//--- Инициализируем цвета по умолчанию
this.InitColors();
//--- Устанавливаем смещение и размеры области изображенеия
this.SetImageBound(1,1,this.Height()-2,this.Height()-2);
//--- Инициализируем счётчики автоповтора
this.m_autorepeat_flag=true;
//--- Инициализируем свойства объекта управления автоповтором событий
this.m_autorepeat.SetChartID(this.m_chart_id);
this.m_autorepeat.SetID(0);
this.m_autorepeat.SetName("ButtUpAutorepeatControl");
this.m_autorepeat.SetDelay(DEF_AUTOREPEAT_DELAY);
this.m_autorepeat.SetInterval(DEF_AUTOREPEAT_INTERVAL);
this.m_autorepeat.SetEvent(CHARTEVENT_OBJECT_CLICK,0,0,this.NameFG());
}
//+------------------------------------------------------------------+
//| CButtonArrowUp::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CButtonArrowUp::Compare(const CObject *node,const int mode=0) const
{
return CButton::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CButtonArrowUp::Рисует внешний вид |
//+------------------------------------------------------------------+
void CButtonArrowUp::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Очищаем область рисунка
this.m_painter.Clear(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),false);
//--- Задаём цвет стрелки для обычного и заблокированного состояний кнопки и рисуем стрелку вверх
color clr=(!this.IsBlocked() ? this.GetForeColorControl().NewColor(this.ForeColor(),90,90,90) : this.ForeColor());
this.m_painter.ArrowUp(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),clr,this.AlphaFG(),true);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс кнопки со стрелкой вниз |
//+------------------------------------------------------------------+
class CButtonArrowDown : public CButton
{
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 CButton::Save(file_handle); }
virtual bool Load(const int file_handle) { return CButton::Load(file_handle); }
virtual int Type(void) const { return(ELEMENT_TYPE_BUTTON_ARROW_DOWN); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void){}
//--- Конструкторы/деструктор
CButtonArrowDown(void);
CButtonArrowDown(const string object_name, const string text, const int x, const int y, const int w, const int h);
CButtonArrowDown(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CButtonArrowDown(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CButtonArrowDown (void) {}
};
//+------------------------------------------------------------------+
//| CButtonArrowDown::Конструктор по умолчанию. |
//| Строит кнопку в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CButtonArrowDown::CButtonArrowDown(void) : CButton("Arrow Up Button","",::ChartID(),0,0,0,DEF_BUTTON_W,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowDown::Конструктор параметрический. |
//| Строит кнопку в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowDown::CButtonArrowDown(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowDown::Конструктор параметрический. |
//| Строит кнопку в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowDown::CButtonArrowDown(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowDown::Конструктор параметрический. |
//| Строит кнопку в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowDown::CButtonArrowDown(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowDown::Инициализация |
//+------------------------------------------------------------------+
void CButtonArrowDown::Init(const string text)
{
//--- Инициализируем цвета по умолчанию
this.InitColors();
//--- Устанавливаем смещение и размеры области изображенеия
this.SetImageBound(1,1,this.Height()-2,this.Height()-2);
//--- Инициализируем счётчики автоповтора
this.m_autorepeat_flag=true;
//--- Инициализируем свойства объекта управления автоповтором событий
this.m_autorepeat.SetChartID(this.m_chart_id);
this.m_autorepeat.SetID(0);
this.m_autorepeat.SetName("ButtDownAutorepeatControl");
this.m_autorepeat.SetDelay(DEF_AUTOREPEAT_DELAY);
this.m_autorepeat.SetInterval(DEF_AUTOREPEAT_INTERVAL);
this.m_autorepeat.SetEvent(CHARTEVENT_OBJECT_CLICK,0,0,this.NameFG());
}
//+------------------------------------------------------------------+
//| CButtonArrowDown::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CButtonArrowDown::Compare(const CObject *node,const int mode=0) const
{
return CButton::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CButtonArrowDown::Рисует внешний вид |
//+------------------------------------------------------------------+
void CButtonArrowDown::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Очищаем область рисунка
this.m_painter.Clear(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),false);
//--- Задаём цвет стрелки для обычного и заблокированного состояний кнопки и рисуем стрелку вниз
color clr=(!this.IsBlocked() ? this.GetForeColorControl().NewColor(this.ForeColor(),90,90,90) : this.ForeColor());
this.m_painter.ArrowDown(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),clr,this.AlphaFG(),true);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс кнопки со стрелкой влево |
//+------------------------------------------------------------------+
class CButtonArrowLeft : public CButton
{
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 CButton::Save(file_handle); }
virtual bool Load(const int file_handle) { return CButton::Load(file_handle); }
virtual int Type(void) const { return(ELEMENT_TYPE_BUTTON_ARROW_DOWN); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void){}
//--- Конструкторы/деструктор
CButtonArrowLeft(void);
CButtonArrowLeft(const string object_name, const string text, const int x, const int y, const int w, const int h);
CButtonArrowLeft(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CButtonArrowLeft(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CButtonArrowLeft (void) {}
};
//+------------------------------------------------------------------+
//| CButtonArrowLeft::Конструктор по умолчанию. |
//| Строит кнопку в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CButtonArrowLeft::CButtonArrowLeft(void) : CButton("Arrow Up Button","",::ChartID(),0,0,0,DEF_BUTTON_W,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowLeft::Конструктор параметрический. |
//| Строит кнопку в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowLeft::CButtonArrowLeft(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowLeft::Конструктор параметрический. |
//| Строит кнопку в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowLeft::CButtonArrowLeft(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowLeft::Конструктор параметрический. |
//| Строит кнопку в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowLeft::CButtonArrowLeft(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowLeft::Инициализация |
//+------------------------------------------------------------------+
void CButtonArrowLeft::Init(const string text)
{
//--- Инициализируем цвета по умолчанию
this.InitColors();
//--- Устанавливаем смещение и размеры области изображенеия
this.SetImageBound(1,1,this.Height()-2,this.Height()-2);
//--- Инициализируем счётчики автоповтора
this.m_autorepeat_flag=true;
//--- Инициализируем свойства объекта управления автоповтором событий
this.m_autorepeat.SetChartID(this.m_chart_id);
this.m_autorepeat.SetID(0);
this.m_autorepeat.SetName("ButtLeftAutorepeatControl");
this.m_autorepeat.SetDelay(DEF_AUTOREPEAT_DELAY);
this.m_autorepeat.SetInterval(DEF_AUTOREPEAT_INTERVAL);
this.m_autorepeat.SetEvent(CHARTEVENT_OBJECT_CLICK,0,0,this.NameFG());
}
//+------------------------------------------------------------------+
//| CButtonArrowLeft::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CButtonArrowLeft::Compare(const CObject *node,const int mode=0) const
{
return CButton::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CButtonArrowLeft::Рисует внешний вид |
//+------------------------------------------------------------------+
void CButtonArrowLeft::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Очищаем область рисунка
this.m_painter.Clear(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),false);
//--- Задаём цвет стрелки для обычного и заблокированного состояний кнопки и рисуем стрелку влево
color clr=(!this.IsBlocked() ? this.GetForeColorControl().NewColor(this.ForeColor(),90,90,90) : this.ForeColor());
this.m_painter.ArrowLeft(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),clr,this.AlphaFG(),true);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс кнопки со стрелкой вправо |
//+------------------------------------------------------------------+
class CButtonArrowRight : public CButton
{
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 CButton::Save(file_handle); }
virtual bool Load(const int file_handle) { return CButton::Load(file_handle); }
virtual int Type(void) const { return(ELEMENT_TYPE_BUTTON_ARROW_DOWN); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void){}
//--- Конструкторы/деструктор
CButtonArrowRight(void);
CButtonArrowRight(const string object_name, const string text, const int x, const int y, const int w, const int h);
CButtonArrowRight(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CButtonArrowRight(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CButtonArrowRight (void) {}
};
//+------------------------------------------------------------------+
//| CButtonArrowRight::Конструктор по умолчанию. |
//| Строит кнопку в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CButtonArrowRight::CButtonArrowRight(void) : CButton("Arrow Up Button","",::ChartID(),0,0,0,DEF_BUTTON_W,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowRight::Конструктор параметрический. |
//| Строит кнопку в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowRight::CButtonArrowRight(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowRight::Конструктор параметрический. |
//| Строит кнопку в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowRight::CButtonArrowRight(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowRight::Конструктор параметрический. |
//| Строит кнопку в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CButtonArrowRight::CButtonArrowRight(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CButtonArrowRight::Инициализация |
//+------------------------------------------------------------------+
void CButtonArrowRight::Init(const string text)
{
//--- Инициализируем цвета по умолчанию
this.InitColors();
//--- Устанавливаем смещение и размеры области изображенеия
this.SetImageBound(1,1,this.Height()-2,this.Height()-2);
//--- Инициализируем счётчики автоповтора
this.m_autorepeat_flag=true;
//--- Инициализируем свойства объекта управления автоповтором событий
this.m_autorepeat.SetChartID(this.m_chart_id);
this.m_autorepeat.SetID(0);
this.m_autorepeat.SetName("ButtRightAutorepeatControl");
this.m_autorepeat.SetDelay(DEF_AUTOREPEAT_DELAY);
this.m_autorepeat.SetInterval(DEF_AUTOREPEAT_INTERVAL);
this.m_autorepeat.SetEvent(CHARTEVENT_OBJECT_CLICK,0,0,this.NameFG());
}
//+------------------------------------------------------------------+
//| CButtonArrowRight::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CButtonArrowRight::Compare(const CObject *node,const int mode=0) const
{
return CButton::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CButtonArrowRight::Рисует внешний вид |
//+------------------------------------------------------------------+
void CButtonArrowRight::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Очищаем область рисунка
this.m_painter.Clear(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),false);
//--- Задаём цвет стрелки для обычного и заблокированного состояний кнопки и рисуем стрелку вправо
color clr=(!this.IsBlocked() ? this.GetForeColorControl().NewColor(this.ForeColor(),90,90,90) : this.ForeColor());
this.m_painter.ArrowRight(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),clr,this.AlphaFG(),true);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс элемента управления Checkbox |
//+------------------------------------------------------------------+
class CCheckBox : public CButtonTriggered
{
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 CButton::Save(file_handle); }
virtual bool Load(const int file_handle) { return CButton::Load(file_handle); }
virtual int Type(void) const { return(ELEMENT_TYPE_CHECKBOX); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void);
//--- Конструкторы/деструктор
CCheckBox(void);
CCheckBox(const string object_name, const string text, const int x, const int y, const int w, const int h);
CCheckBox(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CCheckBox(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CCheckBox (void) {}
};
//+------------------------------------------------------------------+
//| CCheckBox::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CCheckBox::CCheckBox(void) : CButtonTriggered("CheckBox","CheckBox",::ChartID(),0,0,0,DEF_BUTTON_W,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CCheckBox::Конструктор параметрический. |
//| Строит элемент в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CCheckBox::CCheckBox(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CButtonTriggered(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CCheckBox::Конструктор параметрический. |
//| Строит элемент в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CCheckBox::CCheckBox(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CButtonTriggered(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CCheckBox::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CCheckBox::CCheckBox(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButtonTriggered(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CCheckBox::Инициализация |
//+------------------------------------------------------------------+
void CCheckBox::Init(const string text)
{
//--- Устанавливаем цвета по умолчанию, прозрачность для фона и переднего плана,
//--- и координаты и границы области рисунка значка кнопки
this.InitColors();
this.SetAlphaBG(0);
this.SetAlphaFG(255);
this.SetImageBound(1,1,this.Height()-2,this.Height()-2);
}
//+------------------------------------------------------------------+
//| CCheckBox::Инициализация цветов объекта по умолчанию |
//+------------------------------------------------------------------+
void CCheckBox::InitColors(void)
{
//--- Инициализируем цвета заднего плана для обычного и активированного состояний и делаем его текущим цветом фона
this.InitBackColors(clrNULL);
this.InitBackColorsAct(clrNULL);
this.BackColorToDefault();
//--- Инициализируем цвета переднего плана для обычного и активированного состояний и делаем его текущим цветом текста
this.InitForeColors(clrBlack);
this.InitForeColorsAct(clrBlack);
this.InitForeColorFocused(clrNavy);
this.InitForeColorActFocused(clrNavy);
this.ForeColorToDefault();
//--- Инициализируем цвета рамки для обычного и активированного состояний и делаем его текущим цветом рамки
this.InitBorderColors(clrNULL);
this.InitBorderColorsAct(clrNULL);
this.BorderColorToDefault();
//--- Инициализируем цвет рамки и цвет переднего плана для заблокированного элемента
this.InitBorderColorBlocked(clrNULL);
this.InitForeColorBlocked(clrSilver);
}
//+------------------------------------------------------------------+
//| CCheckBox::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CCheckBox::Compare(const CObject *node,const int mode=0) const
{
return CButtonTriggered::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CCheckBox::Рисует внешний вид |
//+------------------------------------------------------------------+
void CCheckBox::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Очищаем область рисунка
this.m_painter.Clear(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),false);
//--- Рисуем отмеченный значок для активного состояния кнопки,
if(this.m_state)
this.m_painter.CheckedBox(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),this.ForeColor(),this.AlphaFG(),true);
//--- и неотмеченный - для неактивного
else
this.m_painter.UncheckedBox(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),this.ForeColor(),this.AlphaFG(),true);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс элемента управления Radio Button |
//+------------------------------------------------------------------+
class CRadioButton : public CCheckBox
{
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 CButton::Save(file_handle); }
virtual bool Load(const int file_handle) { return CButton::Load(file_handle); }
virtual int Type(void) const { return(ELEMENT_TYPE_RADIOBUTTON); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
virtual void InitColors(void){}
//--- Обработчик событий нажатий кнопок мышки (Press)
virtual void OnPressEvent(const int id, const long lparam, const double dparam, const string sparam);
//--- Конструкторы/деструктор
CRadioButton(void);
CRadioButton(const string object_name, const string text, const int x, const int y, const int w, const int h);
CRadioButton(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CRadioButton(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CRadioButton (void) {}
};
//+------------------------------------------------------------------+
//| CRadioButton::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CRadioButton::CRadioButton(void) : CCheckBox("RadioButton","",::ChartID(),0,0,0,DEF_BUTTON_H,DEF_BUTTON_H)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CRadioButton::Конструктор параметрический. |
//| Строит элемент в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CRadioButton::CRadioButton(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CCheckBox(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CRadioButton::Конструктор параметрический. |
//| Строит элемент в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CRadioButton::CRadioButton(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CCheckBox(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CRadioButton::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CRadioButton::CRadioButton(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CCheckBox(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CRadioButton::Инициализация |
//+------------------------------------------------------------------+
void CRadioButton::Init(const string text)
{
return;
}
//+------------------------------------------------------------------+
//| CRadioButton::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CRadioButton::Compare(const CObject *node,const int mode=0) const
{
return CCheckBox::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CRadioButton::Рисует внешний вид |
//+------------------------------------------------------------------+
void CRadioButton::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Выводим текст кнопки
CLabel::Draw(false);
//--- Очищаем область рисунка
this.m_painter.Clear(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),false);
//--- Рисуем отмеченный значок для активного состояния кнопки,
if(this.m_state)
this.m_painter.CheckedRadioButton(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),this.ForeColor(),this.AlphaFG(),true);
//--- и неотмеченный - для неактивного
else
this.m_painter.UncheckedRadioButton(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),this.ForeColor(),this.AlphaFG(),true);
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CRadioButton::Обработчик событий нажатий кнопок мышки (Press) |
//+------------------------------------------------------------------+
void CRadioButton::OnPressEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Если кнопка уже отмечена - уходим
if(this.m_state)
return;
//--- Устанавливаем состояние кнопки, обратное уже установленному
ENUM_ELEMENT_STATE state=(this.State()==ELEMENT_STATE_DEF ? ELEMENT_STATE_ACT : ELEMENT_STATE_DEF);
this.SetState(state);
//--- Вызываем обработчик родительского объекта с указанием идентификатора в lparam и состояния в dparam
CCanvasBase::OnPressEvent(id,this.m_id,this.m_state,sparam);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс панели |
//+------------------------------------------------------------------+
class CPanel : public CLabel
{
private:
CElementBase m_temp_elm; // Временный объект для поиска элементов
CBound m_temp_bound; // Временный объект для поиска областей
protected:
CListObj m_list_elm; // Список прикреплённых элементов
CListObj m_list_bounds; // Список областей
//--- Добавляет новый элемент в список
bool AddNewElement(CElementBase *element);
public:
//--- Возвращает указатель на список (1) прикреплённых элементов, (2) областей
CListObj *GetListAttachedElements(void) { return &this.m_list_elm; }
CListObj *GetListBounds(void) { return &this.m_list_bounds; }
//--- Возвращает элемент по (1) индексу в списке, (2) идентификатору, (3) назначенному имени объекта
CElementBase *GetAttachedElementAt(const uint index) { return this.m_list_elm.GetNodeAtIndex(index); }
CElementBase *GetAttachedElementByID(const int id);
CElementBase *GetAttachedElementByName(const string name);
//--- Возвращает область по (1) индексу в списке, (2) идентификатору, (3) назначенному имени области
CBound *GetBoundAt(const uint index) { return this.m_list_bounds.GetNodeAtIndex(index); }
CBound *GetBoundByID(const int id);
CBound *GetBoundByName(const string name);
//--- Создаёт и добавляет (1) новый, (2) ранее созданный элемент в список
virtual CElementBase *InsertNewElement(const ENUM_ELEMENT_TYPE type,const string text,const string user_name,const int dx,const int dy,const int w,const int h);
virtual CElementBase *InsertElement(CElementBase *element,const int dx,const int dy);
//--- Создаёт и добавляет в список новую область
CBound *InsertNewBound(const string name,const int dx,const int dy,const int w,const int h);
//--- Рисует внешний вид
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);
virtual bool Load(const int file_handle);
virtual int Type(void) const { return(ELEMENT_TYPE_PANEL); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(void);
virtual void InitColors(void);
//--- Устанавливает объекту новые координаты XY
virtual bool Move(const int x,const int y);
//--- Смещает объект по осям XY на указанное смещение
virtual bool Shift(const int dx,const int dy);
//--- (1) Скрывает (2) отображает объект на всех периодах графика,
//--- (3) помещает объект на передний план, (4) блокирует, (5) разблокирует элемент,
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);
//--- Выводит в журнал описание объекта
virtual void Print(void);
//--- Распечатывает список (1) присоединённых объектов, (2) областей
void PrintAttached(const uint tab=3);
void PrintBounds(void);
//--- Обработчик событий
virtual void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam);
//--- Обработчик события таймера
virtual void TimerEventHandler(void);
//--- Конструкторы/деструктор
CPanel(void);
CPanel(const string object_name, const string text, const int x, const int y, const int w, const int h);
CPanel(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CPanel(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CPanel (void) { this.m_list_elm.Clear(); this.m_list_bounds.Clear(); }
};
//+------------------------------------------------------------------+
//| CPanel::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CPanel::CPanel(void) : CLabel("Panel","",::ChartID(),0,0,0,DEF_PANEL_W,DEF_PANEL_H)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CPanel::Конструктор параметрический. |
//| Строит элемент в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CPanel::CPanel(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CLabel(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CPanel::Конструктор параметрический. |
//| Строит элемент в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CPanel::CPanel(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,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CPanel::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CPanel::CPanel(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CLabel(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CPanel::Инициализация |
//+------------------------------------------------------------------+
void CPanel::Init(void)
{
//--- Инициализация цветов по умолчанию
this.InitColors();
//--- Фон - прозрачный, передний план - нет
this.SetAlphaBG(0);
this.SetAlphaFG(255);
//--- Устанавливаем смещение и размеры области изображенеия
this.SetImageBound(0,0,this.Width(),this.Height());
//--- Ширина рамки
this.SetBorderWidth(2);
}
//+------------------------------------------------------------------+
//| CPanel::Инициализация цветов объекта по умолчанию |
//+------------------------------------------------------------------+
void CPanel::InitColors(void)
{
//--- Инициализируем цвета заднего плана для обычного и активированного состояний и делаем его текущим цветом фона
this.InitBackColors(clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke);
this.InitBackColorsAct(clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke);
this.BackColorToDefault();
//--- Инициализируем цвета переднего плана для обычного и активированного состояний и делаем его текущим цветом текста
this.InitForeColors(clrBlack,clrBlack,clrBlack,clrSilver);
this.InitForeColorsAct(clrBlack,clrBlack,clrBlack,clrSilver);
this.ForeColorToDefault();
//--- Инициализируем цвета рамки для обычного и активированного состояний и делаем его текущим цветом рамки
this.InitBorderColors(clrNULL,clrNULL,clrNULL,clrNULL);
this.InitBorderColorsAct(clrNULL,clrNULL,clrNULL,clrNULL);
this.BorderColorToDefault();
//--- Инициализируем цвет рамки и цвет переднего плана для заблокированного элемента
this.InitBorderColorBlocked(clrNULL);
this.InitForeColorBlocked(clrSilver);
}
//+------------------------------------------------------------------+
//| CPanel::Сравнение двух объектов |
//+------------------------------------------------------------------+
int CPanel::Compare(const CObject *node,const int mode=0) const
{
return CLabel::Compare(node,mode);
}
//+------------------------------------------------------------------+
//| CPanel::Рисует внешний вид |
//+------------------------------------------------------------------+
void CPanel::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона
this.Fill(this.BackColor(),false);
//--- Очищаем область рисунка
this.m_painter.Clear(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),this.m_painter.Width(),this.m_painter.Height(),false);
//--- Задаём цвет для тёмной и светлой линий и рисуем рамку панели
color clr_dark =(this.BackColor()==clrNULL ? this.BackColor() : this.GetBackColorControl().NewColor(this.BackColor(),-20,-20,-20));
color clr_light=(this.BackColor()==clrNULL ? this.BackColor() : this.GetBackColorControl().NewColor(this.BackColor(), 6, 6, 6));
this.m_painter.FrameGroupElements(this.AdjX(this.m_painter.X()),this.AdjY(this.m_painter.Y()),
this.m_painter.Width(),this.m_painter.Height(),this.Text(),
this.ForeColor(),clr_dark,clr_light,this.AlphaFG(),true);
//--- Обновляем канвас фона без перерисовки графика
this.m_background.Update(false);
//--- Рисуем элементы списка
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.Draw(false);
}
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CPanel::Добавляет новый элемент в список |
//+------------------------------------------------------------------+
bool CPanel::AddNewElement(CElementBase *element)
{
//--- Если передан пустой указатель - сообщаем об этом и возвращаем false
if(element==NULL)
{
::PrintFormat("%s: Error. Empty element passed",__FUNCTION__);
return false;
}
//--- Устанавливаем списку флаг сортировки по идентификатору
this.m_list_elm.Sort(ELEMENT_SORT_BY_ID);
//--- Если такого элемента нет в списке - возвращаем результат его добавления в список
if(this.m_list_elm.Search(element)==NULL)
return(this.m_list_elm.Add(element)>-1);
//--- Элемент с таким идентификатором уже есть в списке - возвращаем false
return false;
}
//+------------------------------------------------------------------+
//| CPanel::Создаёт и добавляет новый элемент в список |
//+------------------------------------------------------------------+
CElementBase *CPanel::InsertNewElement(const ENUM_ELEMENT_TYPE type,const string text,const string user_name,const int dx,const int dy,const int w,const int h)
{
//--- Создаём имя графического объекта
int elm_total=this.m_list_elm.Total();
string obj_name=this.NameFG()+"_"+ElementShortName(type)+(string)elm_total;
//--- Рассчитываем координаты
int x=this.X()+dx;
int y=this.Y()+dy;
//--- В зависимости от типа объекта, создаём новый объект
CElementBase *element=NULL;
switch(type)
{
case ELEMENT_TYPE_LABEL : element = new CLabel(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Текстовая метка
case ELEMENT_TYPE_BUTTON : element = new CButton(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Простая кнопка
case ELEMENT_TYPE_BUTTON_TRIGGERED : element = new CButtonTriggered(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Двухпозиционная кнопка
case ELEMENT_TYPE_BUTTON_ARROW_UP : element = new CButtonArrowUp(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Кнопка со стрелкой вверх
case ELEMENT_TYPE_BUTTON_ARROW_DOWN : element = new CButtonArrowDown(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Кнопка со стрелкой вниз
case ELEMENT_TYPE_BUTTON_ARROW_LEFT : element = new CButtonArrowLeft(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Кнопка со стрелкой влево
case ELEMENT_TYPE_BUTTON_ARROW_RIGHT: element = new CButtonArrowRight(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Кнопка со стрелкой вправо
case ELEMENT_TYPE_CHECKBOX : element = new CCheckBox(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Элемент управления CheckBox
case ELEMENT_TYPE_RADIOBUTTON : element = new CRadioButton(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Элемент управления RadioButton
case ELEMENT_TYPE_PANEL : element = new CPanel(obj_name,"",this.m_chart_id,this.m_wnd,x,y,w,h); break; // Элемент управления Panel
case ELEMENT_TYPE_GROUPBOX : element = new CGroupBox(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Элемент управления GroupBox
case ELEMENT_TYPE_SCROLLBAR_THUMB_H : element = new CScrollBarThumbH(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Полоса прокрутки горизонтального ScrollBar
case ELEMENT_TYPE_SCROLLBAR_THUMB_V : element = new CScrollBarThumbV(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Полоса прокрутки вертикального ScrollBar
case ELEMENT_TYPE_SCROLLBAR_H : element = new CScrollBarH(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Элемент управления горизонтальный ScrollBar
case ELEMENT_TYPE_SCROLLBAR_V : element = new CScrollBarV(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Элемент управления вертикальный ScrollBar
case ELEMENT_TYPE_CONTAINER : element = new CContainer(obj_name,text,this.m_chart_id,this.m_wnd,x,y,w,h); break; // Элемент управления Container
default : element = NULL;
}
//--- Если новый элемент не создан - сообщаем об этом и возвращаем NULL
if(element==NULL)
{
::PrintFormat("%s: Error. Failed to create graphic element %s",__FUNCTION__,ElementDescription(type));
return NULL;
}
//--- Устанавливаем идентификатор, имя, контейнер и z-order элемента
element.SetID(elm_total);
element.SetName(user_name);
element.SetContainerObj(&this);
element.ObjectSetZOrder(this.ObjectZOrder()+1);
//--- Если созданный элемент не добавлен в список - сообщаем об этом, удаляем созданный элемент и возвращаем NULL
if(!this.AddNewElement(element))
{
::PrintFormat("%s: Error. Failed to add %s element with ID %d to list",__FUNCTION__,ElementDescription(type),element.ID());
delete element;
return NULL;
}
//--- Получаем родительский элемент, к которому привязаны дочерние
CElementBase *elm=this.GetContainer();
//--- Если родительский элемент имеет тип "Контейнер", значит, у него есть полосы прокрутки
if(elm!=NULL && elm.Type()==ELEMENT_TYPE_CONTAINER)
{
//--- Преобразуем CElementBase в CContainer
CContainer *container_obj=elm;
//--- Если горизонтальная полоса прокрутки видима,
if(container_obj.ScrollBarHorIsVisible())
{
//--- получаем указатель на горизонтальный скроллбар и переносим его на передний план
CScrollBarH *sbh=container_obj.GetScrollBarH();
if(sbh!=NULL)
sbh.BringToTop(false);
}
//--- Если вертикальная полоса прокрутки видима,
if(container_obj.ScrollBarVerIsVisible())
{
//--- получаем указатель на вертикальный скроллбар и переносим его на передний план
CScrollBarV *sbv=container_obj.GetScrollBarV();
if(sbv!=NULL)
sbv.BringToTop(false);
}
}
//--- Возвращаем указатель на созданный и присоединённый элемент
return element;
}
//+------------------------------------------------------------------+
//| CPanel::Добавляет указанный элемент в список |
//+------------------------------------------------------------------+
CElementBase *CPanel::InsertElement(CElementBase *element,const int dx,const int dy)
{
//--- Если передан пустой или невалидный указатель на элемент - возвращаем NULL
if(::CheckPointer(element)==POINTER_INVALID)
{
::PrintFormat("%s: Error. Empty element passed",__FUNCTION__);
return NULL;
}
//--- Если передан базовый элемент - возвращаем NULL
if(element.Type()==ELEMENT_TYPE_BASE)
{
::PrintFormat("%s: Error. The base element cannot be used",__FUNCTION__);
return NULL;
}
//--- Запоминаем идентификатор элемента и устанавливаем новый
int id=element.ID();
element.SetID(this.m_list_elm.Total());
//--- Добавляем элемент в список; при неудаче - сообщаем об этом, устанавливаем начальный идентификатор и возвращаем NULL
if(!this.AddNewElement(element))
{
::PrintFormat("%s: Error. Failed to add element %s to list",__FUNCTION__,ElementDescription((ENUM_ELEMENT_TYPE)element.Type()));
element.SetID(id);
return NULL;
}
//--- Устанавливаем новые координаты, контейнер и z-order элемента
int x=this.X()+dx;
int y=this.Y()+dy;
element.Move(x,y);
element.SetContainerObj(&this);
element.ObjectSetZOrder(this.ObjectZOrder()+1);
//--- Возвращаем указатель на присоединённый элемент
return element;
}
//+------------------------------------------------------------------+
//| CPanel::Возвращает элемент по идентификатору |
//+------------------------------------------------------------------+
CElementBase *CPanel::GetAttachedElementByID(const int id)
{
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL && elm.ID()==id)
return elm;
}
return NULL;
}
//+------------------------------------------------------------------+
//| CPanel::Возвращает элемент по назначенному имени объекта |
//+------------------------------------------------------------------+
CElementBase *CPanel::GetAttachedElementByName(const string name)
{
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL && elm.Name()==name)
return elm;
}
return NULL;
}
//+------------------------------------------------------------------+
//| Создаёт и добавляет в список новую область |
//+------------------------------------------------------------------+
CBound *CPanel::InsertNewBound(const string name,const int dx,const int dy,const int w,const int h)
{
//--- Проверяем есть ли в списке область с указанным именем и, если да - сообщаем об этом и возвращаем NULL
this.m_temp_bound.SetName(name);
if(this.m_list_bounds.Search(&this.m_temp_bound)!=NULL)
{
::PrintFormat("%s: Error. An area named \"%s\" is already in the list",__FUNCTION__,name);
return NULL;
}
//--- Создаём новый объект-область; при неудаче - сообщаем об этом и возвращаем NULL
CBound *bound=new CBound(dx,dy,w,h);
if(bound==NULL)
{
::PrintFormat("%s: Error. Failed to create CBound object",__FUNCTION__);
return NULL;
}
//--- Если новый объект не удалось добавить в список - сообщаем об этом, удаляем объект и возвращаем NULL
if(this.m_list_bounds.Add(bound)==-1)
{
::PrintFormat("%s: Error. Failed to add CBound object to list",__FUNCTION__);
delete bound;
return NULL;
}
//--- Устанавливаем имя области и идентификатор, и возвращаем указатель на объект
bound.SetName(name);
bound.SetID(this.m_list_bounds.Total());
return bound;
}
//+------------------------------------------------------------------+
//| Выводит в журнал описание объекта |
//+------------------------------------------------------------------+
void CPanel::Print(void)
{
CBaseObj::Print();
this.PrintAttached();
}
//+------------------------------------------------------------------+
//| CPanel::Распечатывает список присоединённых объектов |
//+------------------------------------------------------------------+
void CPanel::PrintAttached(const uint tab=3)
{
//--- В цикле по всем привязанным элементам
int total=this.m_list_elm.Total();
for(int i=0;i<total;i++)
{
//--- получаем очередной элемент
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm==NULL)
continue;
//--- Получаем тип элемента и, если это полоса прокрутки - пропускаем его
ENUM_ELEMENT_TYPE type=(ENUM_ELEMENT_TYPE)elm.Type();
if(type==ELEMENT_TYPE_SCROLLBAR_H || type==ELEMENT_TYPE_SCROLLBAR_V)
continue;
//--- Распечатываем в журнале описание элемента
::PrintFormat("%*s[%d]: %s",tab,"",i,elm.Description());
//--- Если элемент является контейнером - распечатываем в журнал его список привязанных элементов
if(type==ELEMENT_TYPE_PANEL || type==ELEMENT_TYPE_GROUPBOX || type==ELEMENT_TYPE_CONTAINER)
{
CPanel *obj=elm;
obj.PrintAttached(tab*2);
}
}
}
//+------------------------------------------------------------------+
//| CPanel::Распечатывает список областей |
//+------------------------------------------------------------------+
void CPanel::PrintBounds(void)
{
//--- В цикле по списку областей элемента
int total=this.m_list_bounds.Total();
for(int i=0;i<total;i++)
{
//--- получаем очередную область и распечатываем её описание в журнал
CBound *obj=this.GetBoundAt(i);
if(obj==NULL)
continue;
::PrintFormat(" [%d]: %s",i,obj.Description());
}
}
//+------------------------------------------------------------------+
//| CPanel::Устанавливает объекту новые координаты X и Y |
//+------------------------------------------------------------------+
bool CPanel::Move(const int x,const int y)
{
//--- Вычисляем дистанцию, на которую сместится элемент
int delta_x=x-this.X();
int delta_y=y-this.Y();
//--- Перемещаем элемент на указанные координаты
bool res=this.ObjectMove(x,y);
if(!res)
return false;
this.BoundMove(x,y);
this.ObjectTrim();
//--- Перемещаем все привязанные элементы на рассчитанную дистанцию
int total=this.m_list_elm.Total();
for(int i=0;i<total;i++)
{
//--- Перемещаем привязанный элемент с учётом смещения родительского элемента
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
res &=elm.Move(elm.X()+delta_x, elm.Y()+delta_y);
}
//--- Возвращаем результат перемещения всех привязанных элементов
return res;
}
//+------------------------------------------------------------------+
//| CPanel::Смещает объект по осям X и Y на указанное смещение |
//+------------------------------------------------------------------+
bool CPanel::Shift(const int dx,const int dy)
{
//--- Смещаем элемент на указанную дистанцию
bool res=this.ObjectShift(dx,dy);
if(!res)
return false;
this.BoundShift(dx,dy);
this.ObjectTrim();
//--- Смещаем все привязанные элементы
int total=this.m_list_elm.Total();
for(int i=0;i<total;i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
res &=elm.Shift(dx,dy);
}
//--- Возвращаем результат смещения всех привязанных элементов
return res;
}
//+------------------------------------------------------------------+
//| CPanel::Скрывает объект на всех периодах графика |
//+------------------------------------------------------------------+
void CPanel::Hide(const bool chart_redraw)
{
//--- Если объект уже скрыт - уходим
if(this.m_hidden)
return;
//--- Скрываем панель
CCanvasBase::Hide(false);
//--- Скрываем прикреплённые объекты
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.Hide(false);
}
//--- Если указано - перерисовываем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CPanel::Отображает объект на всех периодах графика |
//+------------------------------------------------------------------+
void CPanel::Show(const bool chart_redraw)
{
//--- Если объект уже видимый - уходим
if(!this.m_hidden)
return;
//--- Отображаем панель
CCanvasBase::Show(false);
//--- Отображаем прикреплённые объекты
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.Show(false);
}
//--- Если указано - перерисовываем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CPanel::Помещает объект на передний план |
//+------------------------------------------------------------------+
void CPanel::BringToTop(const bool chart_redraw)
{
//--- Помещаем панель на передний план
CCanvasBase::BringToTop(false);
//--- Помещаем на передний план прикреплённые объекты
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.BringToTop(false);
}
//--- Если указано - перерисовываем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CPanel::Блокирует элемент |
//+------------------------------------------------------------------+
void CPanel::Block(const bool chart_redraw)
{
//--- Если элемент уже заблокирован - уходим
if(this.m_blocked)
return;
//--- Блокируем панель
CCanvasBase::Block(false);
//--- Блокируем прикреплённые объекты
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.Block(false);
}
//--- Если указано - перерисовываем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CPanel::Разблокирует элемент |
//+------------------------------------------------------------------+
void CPanel::Unblock(const bool chart_redraw)
{
//--- Если элемент уже разблокирован - уходим
if(!this.m_blocked)
return;
//--- Разблокируем панель
CCanvasBase::Unblock(false);
//--- Разблокируем прикреплённые объекты
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.Unblock(false);
}
//--- Если указано - перерисовываем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CPanel::Сохранение в файл |
//+------------------------------------------------------------------+
bool CPanel::Save(const int file_handle)
{
//--- Сохраняем данные родительского объекта
if(!CElementBase::Save(file_handle))
return false;
//--- Сохраняем список прикреплённых элементов
if(!this.m_list_elm.Save(file_handle))
return false;
//--- Сохраняем список областей
if(!this.m_list_bounds.Save(file_handle))
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CPanel::Загрузка из файла |
//+------------------------------------------------------------------+
bool CPanel::Load(const int file_handle)
{
//--- Загружаем данные родительского объекта
if(!CElementBase::Load(file_handle))
return false;
//--- Загружаем список прикреплённых элементов
if(!this.m_list_elm.Load(file_handle))
return false;
//--- Загружаем список областей
if(!this.m_list_bounds.Load(file_handle))
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CPanel::Обработчик событий |
//+------------------------------------------------------------------+
void CPanel::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- Вызываем обработчик событий родительского класса
CCanvasBase::OnChartEvent(id,lparam,dparam,sparam);
//--- В цикле по всем привязанным элементам
int total=this.m_list_elm.Total();
for(int i=0;i<total;i++)
{
//--- получаем очередной элемент и вызываем его обработчик событий
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.OnChartEvent(id,lparam,dparam,sparam);
}
}
//+------------------------------------------------------------------+
//| CPanel::Обработчик события таймера |
//+------------------------------------------------------------------+
void CPanel::TimerEventHandler(void)
{
//--- В цикле по всем привязанным элементам
for(int i=0;i<this.m_list_elm.Total();i++)
{
//--- получаем очередной элемент и вызываем его обработчик событий таймера
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.TimerEventHandler();
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс группы объектов |
//+------------------------------------------------------------------+
class CGroupBox : public CPanel
{
public:
//--- Тип объекта
virtual int Type(void) const { return(ELEMENT_TYPE_GROUPBOX); }
//--- Инициализация объекта класса
void Init(void);
//--- Устанавливает группу элементов
virtual void SetGroup(const int group);
//--- Создаёт и добавляет (1) новый, (2) ранее созданный элемент в список
virtual CElementBase *InsertNewElement(const ENUM_ELEMENT_TYPE type,const string text,const string user_name,const int dx,const int dy,const int w,const int h);
virtual CElementBase *InsertElement(CElementBase *element,const int dx,const int dy);
//--- Конструкторы/деструктор
CGroupBox(void);
CGroupBox(const string object_name, const string text, const int x, const int y, const int w, const int h);
CGroupBox(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CGroupBox(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CGroupBox(void) {}
};
//+------------------------------------------------------------------+
//| CGroupBox::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CGroupBox::CGroupBox(void) : CPanel("GroupBox","",::ChartID(),0,0,0,DEF_PANEL_W,DEF_PANEL_H)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CGroupBox::Конструктор параметрический. |
//| Строит элемент в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CGroupBox::CGroupBox(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,::ChartID(),0,x,y,w,h)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CGroupBox::Конструктор параметрический. |
//| Строит элемент в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CGroupBox::CGroupBox(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,::ChartID(),wnd,x,y,w,h)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CGroupBox::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CGroupBox::CGroupBox(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CGroupBox::Инициализация |
//+------------------------------------------------------------------+
void CGroupBox::Init(void)
{
//--- Инициализация при помощи родительского класса
CPanel::Init();
}
//+------------------------------------------------------------------+
//| CGroupBox::Устанавливает группу элементов |
//+------------------------------------------------------------------+
void CGroupBox::SetGroup(const int group)
{
//--- Устанавливаем группу этому элементу методом родительского класса
CElementBase::SetGroup(group);
//--- В цикле по списку привязанных элементов
for(int i=0;i<this.m_list_elm.Total();i++)
{
//--- получаем очередной элемент и назначаем ему группу
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.SetGroup(group);
}
}
//+------------------------------------------------------------------+
//| CGroupBox::Создаёт и добавляет новый элемент в список |
//+------------------------------------------------------------------+
CElementBase *CGroupBox::InsertNewElement(const ENUM_ELEMENT_TYPE type,const string text,const string user_name,const int dx,const int dy,const int w,const int h)
{
//--- Создаём и добавляем в список элементов новый элемент
CElementBase *element=CPanel::InsertNewElement(type,text,user_name,dx,dy,w,h);
if(element==NULL)
return NULL;
//--- Устанавливаем созданному элементу группу, равную группе этого объекта
element.SetGroup(this.Group());
return element;
}
//+------------------------------------------------------------------+
//| CGroupBox::Добавляет указанный элемент в список |
//+------------------------------------------------------------------+
CElementBase *CGroupBox::InsertElement(CElementBase *element,const int dx,const int dy)
{
//--- Добавляем в список элементов новый элемент
if(CPanel::InsertElement(element,dx,dy)==NULL)
return NULL;
//--- Устанавливаем добавленному элементу группу, равную группе этого объекта
element.SetGroup(this.Group());
return element;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс ползунка горизонтальной полосы прокрутки |
//+------------------------------------------------------------------+
class CScrollBarThumbH : public CButton
{
protected:
bool m_chart_redraw; // Флаг обновления графика
public:
//--- (1) Устанавливает, (2) возвращает флаг обновления графика
void SetChartRedrawFlag(const bool flag) { this.m_chart_redraw=flag; }
bool ChartRedrawFlag(void) const { return this.m_chart_redraw; }
//--- Виртуальные методы (1) сохранения в файл, (2) загрузки из файла, (3) тип объекта
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
virtual int Type(void) const { return(ELEMENT_TYPE_SCROLLBAR_THUMB_H); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
//--- Обработчики событий (1) перемещения курсора, (2) прокрутки колёсика
virtual void OnMoveEvent(const int id, const long lparam, const double dparam, const string sparam);
virtual void OnWheelEvent(const int id, const long lparam, const double dparam, const string sparam);
//--- Конструкторы/деструктор
CScrollBarThumbH(void);
CScrollBarThumbH(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CScrollBarThumbH (void) {}
};
//+------------------------------------------------------------------+
//| CScrollBarThumbH::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CScrollBarThumbH::CScrollBarThumbH(void) : CButton("SBThumb","",::ChartID(),0,0,0,DEF_PANEL_W,DEF_SCROLLBAR_TH)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CScrollBarThumbH::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CScrollBarThumbH::CScrollBarThumbH(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CScrollBarThumbH::Инициализация |
//+------------------------------------------------------------------+
void CScrollBarThumbH::Init(const string text)
{
//--- Инициализация родительского класса
CButton::Init("");
//--- Устанавливаем флаги перемещаемости и обновления графика
this.SetMovable(true);
this.SetChartRedrawFlag(false);
}
//+------------------------------------------------------------------+
//| CScrollBarThumbH::Обработчик перемещения курсора |
//+------------------------------------------------------------------+
void CScrollBarThumbH::OnMoveEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Обработчик перемещения курсора базового объекта
CCanvasBase::OnMoveEvent(id,lparam,dparam,sparam);
//--- Получаем указатель на базовый объект (элемент управления "горизонтальная полоса прокрутки")
CCanvasBase *base_obj=this.GetContainer();
//--- Если для ползунка не установлен флаг перемещаемости, либо указатель на базовый объект не получен - уходим
if(!this.IsMovable() || base_obj==NULL)
return;
//--- Получаем ширину базового объекта и рассчитываем границы пространства для ползунка
int base_w=base_obj.Width();
int base_left=base_obj.X()+base_obj.Height();
int base_right=base_obj.Right()-base_obj.Height()+1;
//--- Из координат курсора и размеров ползунка рассчитываем ограничения для перемещения
int x=(int)lparam-this.m_cursor_delta_x;
if(x<base_left)
x=base_left;
if(x+this.Width()>base_right)
x=base_right-this.Width();
//--- Сдвигаем ползунок на рассчитанную координату X
if(!this.MoveX(x))
return;
//--- Рассчитываем позицию ползунка
int thumb_pos=this.X()-base_left;
//--- Отправляем пользовательское событие на график с позицией ползунка в lparam и именем объекта в sparam
::EventChartCustom(this.m_chart_id, (ushort)CHARTEVENT_MOUSE_MOVE, thumb_pos, dparam, this.NameFG());
//--- Перерисовываем график
if(this.m_chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CScrollBarThumbH::Обработчик прокрутки колёсика |
//+------------------------------------------------------------------+
void CScrollBarThumbH::OnWheelEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Получаем указатель на базовый объект (элемент управления "горизонтальная полоса прогрутки")
CCanvasBase *base_obj=this.GetContainer();
//--- Если для ползунка не установлен флаг перемещаемости, либо указатель на базовый объект не получен - уходим
if(!this.IsMovable() || base_obj==NULL)
return;
//--- Получаем ширину базового объекта и рассчитываем границы пространства для ползунка
int base_w=base_obj.Width();
int base_left=base_obj.X()+base_obj.Height();
int base_right=base_obj.Right()-base_obj.Height()+1;
//--- Задаём направление смещения в зависимости от направления вращения колёсика мышки
int dx=(dparam<0 ? 2 : dparam>0 ? -2 : 0);
if(dx==0)
dx=(int)lparam;
//--- Если при смещении ползунок выйдет за левый край своей области - устанавливаем его на левый край
if(dx<0 && this.X()+dx<=base_left)
this.MoveX(base_left);
//--- иначе, если при смещении ползунок выйдет за правый край своей области - позиционируем его по правому краю
else if(dx>0 && this.Right()+dx>=base_right)
this.MoveX(base_right-this.Width());
//--- Иначе, если ползунок в пределах своей области - смещаем его на величину смещения
else if(this.ShiftX(dx))
this.OnFocusEvent(id,lparam,dparam,sparam);
//--- Рассчитываем позицию ползунка
int thumb_pos=this.X()-base_left;
//--- Отправляем пользовательское событие на график с позицией ползунка в lparam и именем объекта в sparam
::EventChartCustom(this.m_chart_id, (ushort)CHARTEVENT_MOUSE_WHEEL, thumb_pos, dparam, this.NameFG());
//--- Перерисовываем график
if(this.m_chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CScrollBarThumbH::Сохранение в файл |
//+------------------------------------------------------------------+
bool CScrollBarThumbH::Save(const int file_handle)
{
//--- Сохраняем данные родительского объекта
if(!CButton::Save(file_handle))
return false;
//--- Сохраняем флаг обновления графика
if(::FileWriteInteger(file_handle,this.m_chart_redraw,INT_VALUE)!=INT_VALUE)
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CScrollBarThumbH::Загрузка из файла |
//+------------------------------------------------------------------+
bool CScrollBarThumbH::Load(const int file_handle)
{
//--- Загружаем данные родительского объекта
if(!CButton::Load(file_handle))
return false;
//--- Загружаем флаг обновления графика
this.m_chart_redraw=::FileReadInteger(file_handle,INT_VALUE);
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс ползунка вертикальной полосы прокрутки |
//+------------------------------------------------------------------+
class CScrollBarThumbV : public CButton
{
protected:
bool m_chart_redraw; // Флаг обновления графика
public:
//--- (1) Устанавливает, (2) возвращает флаг обновления графика
void SetChartRedrawFlag(const bool flag) { this.m_chart_redraw=flag; }
bool ChartRedrawFlag(void) const { return this.m_chart_redraw; }
//--- Виртуальные методы (1) сохранения в файл, (2) загрузки из файла, (3) тип объекта
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
virtual int Type(void) const { return(ELEMENT_TYPE_SCROLLBAR_THUMB_V); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(const string text);
//--- Обработчики событий (1) перемещения курсора, (2) прокрутки колёсика
virtual void OnMoveEvent(const int id, const long lparam, const double dparam, const string sparam);
virtual void OnWheelEvent(const int id, const long lparam, const double dparam, const string sparam);
//--- Конструкторы/деструктор
CScrollBarThumbV(void);
CScrollBarThumbV(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CScrollBarThumbV (void) {}
};
//+------------------------------------------------------------------+
//| CScrollBarThumbV::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CScrollBarThumbV::CScrollBarThumbV(void) : CButton("SBThumb","",::ChartID(),0,0,0,DEF_SCROLLBAR_TH,DEF_PANEL_W)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CScrollBarThumbV::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CScrollBarThumbV::CScrollBarThumbV(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CButton(object_name,text,chart_id,wnd,x,y,w,h)
{
//--- Инициализация
this.Init("");
}
//+------------------------------------------------------------------+
//| CScrollBarThumbV::Инициализация |
//+------------------------------------------------------------------+
void CScrollBarThumbV::Init(const string text)
{
//--- Инициализация родительского класса
CButton::Init("");
//--- Устанавливаем флаги перемещаемости и обновления графика
this.SetMovable(true);
this.SetChartRedrawFlag(false);
}
//+------------------------------------------------------------------+
//| CScrollBarThumbV::Обработчик перемещения курсора |
//+------------------------------------------------------------------+
void CScrollBarThumbV::OnMoveEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Обработчик перемещения курсора базового объекта
CCanvasBase::OnMoveEvent(id,lparam,dparam,sparam);
//--- Получаем указатель на базовый объект (элемент управления "вертикальная полоса прогрутки")
CCanvasBase *base_obj=this.GetContainer();
//--- Если для ползунка не установлен флаг перемещаемости, либо указатель на базовый объект не получен - уходим
if(!this.IsMovable() || base_obj==NULL)
return;
//--- Получаем высоту базового объекта и рассчитываем границы пространства для ползунка
int base_h=base_obj.Height();
int base_top=base_obj.Y()+base_obj.Width();
int base_bottom=base_obj.Bottom()-base_obj.Width()+1;
//--- Из координат курсора и размеров ползунка рассчитываем ограничения для перемещения
int y=(int)dparam-this.m_cursor_delta_y;
if(y<base_top)
y=base_top;
if(y+this.Height()>base_bottom)
y=base_bottom-this.Height();
//--- Сдвигаем ползунок на рассчитанную координату Y
if(!this.MoveY(y))
return;
//--- Рассчитываем позицию ползунка
int thumb_pos=this.Y()-base_top;
//--- Отправляем пользовательское событие на график с позицией ползунка в lparam и именем объекта в sparam
::EventChartCustom(this.m_chart_id, (ushort)CHARTEVENT_MOUSE_MOVE, thumb_pos, dparam, this.NameFG());
//--- Перерисовываем график
if(this.m_chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CScrollBarThumbV::Обработчик прокрутки колёсика |
//+------------------------------------------------------------------+
void CScrollBarThumbV::OnWheelEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Получаем указатель на базовый объект (элемент управления "вертикальная полоса прогрутки")
CCanvasBase *base_obj=this.GetContainer();
//--- Если для ползунка не установлен флаг перемещаемости, либо указатель на базовый объект не получен - уходим
if(!this.IsMovable() || base_obj==NULL)
return;
//--- Получаем высоту базового объекта и рассчитываем границы пространства для ползунка
int base_h=base_obj.Height();
int base_top=base_obj.Y()+base_obj.Width();
int base_bottom=base_obj.Bottom()-base_obj.Width()+1;
//--- Задаём направление смещения в зависимости от направления вращения колёсика мышки
int dy=(dparam<0 ? 2 : dparam>0 ? -2 : 0);
if(dy==0)
dy=(int)lparam;
//--- Если при смещении ползунок выйдет за верхний край своей области - устанавливаем его на верхний край
if(dy<0 && this.Y()+dy<=base_top)
this.MoveY(base_top);
//--- иначе, если при смещении ползунок выйдет за нижний край своей области - позиционируем его по нижнему краю
else if(dy>0 && this.Bottom()+dy>=base_bottom)
this.MoveY(base_bottom-this.Height());
//--- Иначе, если ползунок в пределах своей области - смещаем его на величину смещения
else if(this.ShiftY(dy))
this.OnFocusEvent(id,lparam,dparam,sparam);
//--- Рассчитываем позицию ползунка
int thumb_pos=this.Y()-base_top;
//--- Отправляем пользовательское событие на график с позицией ползунка в lparam и именем объекта в sparam
::EventChartCustom(this.m_chart_id, (ushort)CHARTEVENT_MOUSE_WHEEL, thumb_pos, dparam, this.NameFG());
//--- Перерисовываем график
if(this.m_chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CScrollBarThumbV::Сохранение в файл |
//+------------------------------------------------------------------+
bool CScrollBarThumbV::Save(const int file_handle)
{
//--- Сохраняем данные родительского объекта
if(!CButton::Save(file_handle))
return false;
//--- Сохраняем флаг обновления графика
if(::FileWriteInteger(file_handle,this.m_chart_redraw,INT_VALUE)!=INT_VALUE)
return false;
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//| CScrollBarThumbV::Загрузка из файла |
//+------------------------------------------------------------------+
bool CScrollBarThumbV::Load(const int file_handle)
{
//--- Загружаем данные родительского объекта
if(!CButton::Load(file_handle))
return false;
//--- Загружаем флаг обновления графика
this.m_chart_redraw=::FileReadInteger(file_handle,INT_VALUE);
//--- Всё успешно
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс горизонтальной полосы прокрутки |
//+------------------------------------------------------------------+
class CScrollBarH : public CPanel
{
protected:
CButtonArrowLeft *m_butt_left; // Кнопка со стрелкой влево
CButtonArrowRight*m_butt_right; // Кнопка со стрелкой вправо
CScrollBarThumbH *m_thumb; // Ползунок скроллбара
public:
//--- Возвращает указатель на (1) левую, (2) правую кнопку, (3) ползунок
CButtonArrowLeft *GetButtonLeft(void) { return this.m_butt_left; }
CButtonArrowRight*GetButtonRight(void) { return this.m_butt_right; }
CScrollBarThumbH *GetThumb(void) { return this.m_thumb; }
//--- (1) Устанавливает, (2) возвращает флаг обновления графика
void SetChartRedrawFlag(const bool flag) { if(this.m_thumb!=NULL) this.m_thumb.SetChartRedrawFlag(flag); }
bool ChartRedrawFlag(void) const { return(this.m_thumb!=NULL ? this.m_thumb.ChartRedrawFlag() : false); }
//--- Возвращает (1) длину (2) начало трека, (3) позицию ползунка
int TrackLength(void) const;
int TrackBegin(void) const;
int ThumbPosition(void) const;
//--- Изменяет размер ползунка
bool SetThumbSize(const uint size) const { return(this.m_thumb!=NULL ? this.m_thumb.ResizeW(size) : false); }
//--- Изменяет ширину объекта
virtual bool ResizeW(const int size);
//--- Рисует внешний вид
virtual void Draw(const bool chart_redraw);
//--- Тип объекта
virtual int Type(void) const { return(ELEMENT_TYPE_SCROLLBAR_H); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(void);
virtual void InitColors(void);
//--- Обработчик прокрутки колёсика (Wheel)
virtual void OnWheelEvent(const int id, const long lparam, const double dparam, const string sparam);
//--- Конструкторы/деструктор
CScrollBarH(void);
CScrollBarH(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CScrollBarH(void) {}
};
//+------------------------------------------------------------------+
//| CScrollBarH::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CScrollBarH::CScrollBarH(void) : CPanel("ScrollBarH","",::ChartID(),0,0,0,DEF_PANEL_W,DEF_PANEL_H),m_butt_left(NULL),m_butt_right(NULL),m_thumb(NULL)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CScrollBarH::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CScrollBarH::CScrollBarH(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,chart_id,wnd,x,y,w,h),m_butt_left(NULL),m_butt_right(NULL),m_thumb(NULL)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CScrollBarH::Инициализация |
//+------------------------------------------------------------------+
void CScrollBarH::Init(void)
{
//--- Инициализация родительского класса
CPanel::Init();
//--- Фон - непрозрачный
this.SetAlphaBG(255);
//--- Ширина рамки и текст
this.SetBorderWidth(0);
this.SetText("");
//--- Элемент не обрезается по границам контейнера
this.m_trim_flag=false;
//--- Создаём кнопки прокрутки
int w=this.Height();
int h=this.Height();
this.m_butt_left = this.InsertNewElement(ELEMENT_TYPE_BUTTON_ARROW_LEFT, "","ButtL",0,0,w,h);
this.m_butt_right= this.InsertNewElement(ELEMENT_TYPE_BUTTON_ARROW_RIGHT,"","ButtR",this.Width()-w,0,w,h);
if(this.m_butt_left==NULL || this.m_butt_right==NULL)
{
::PrintFormat("%s: Init failed",__FUNCTION__);
return;
}
//--- Настраиваем цвета и вид кнопки со стрелкой влево
this.m_butt_left.SetImageBound(1,1,w-2,h-4);
this.m_butt_left.InitBackColors(this.m_butt_left.BackColorFocused());
this.m_butt_left.ColorsToDefault();
this.m_butt_left.InitBorderColors(this.BorderColor(),this.m_butt_left.BackColorFocused(),this.m_butt_left.BackColorPressed(),this.m_butt_left.BackColorBlocked());
this.m_butt_left.ColorsToDefault();
//--- Настраиваем цвета и вид кнопки со стрелкой вправо
this.m_butt_right.SetImageBound(1,1,w-2,h-4);
this.m_butt_right.InitBackColors(this.m_butt_right.BackColorFocused());
this.m_butt_right.ColorsToDefault();
this.m_butt_right.InitBorderColors(this.BorderColor(),this.m_butt_right.BackColorFocused(),this.m_butt_right.BackColorPressed(),this.m_butt_right.BackColorBlocked());
this.m_butt_right.ColorsToDefault();
//--- Создаём ползунок
int tsz=this.Width()-w*2;
this.m_thumb=this.InsertNewElement(ELEMENT_TYPE_SCROLLBAR_THUMB_H,"","ThumbH",w,1,tsz-w*4,h-2);
if(this.m_thumb==NULL)
{
::PrintFormat("%s: Init failed",__FUNCTION__);
return;
}
//--- Настраиваем цвета ползунка и устанавливаем ему флаг перемещаемости
this.m_thumb.InitBackColors(this.m_thumb.BackColorFocused());
this.m_thumb.ColorsToDefault();
this.m_thumb.InitBorderColors(this.m_thumb.BackColor(),this.m_thumb.BackColorFocused(),this.m_thumb.BackColorPressed(),this.m_thumb.BackColorBlocked());
this.m_thumb.ColorsToDefault();
this.m_thumb.SetMovable(true);
//--- запрещаем самостоятельную перерисовку графика
this.m_thumb.SetChartRedrawFlag(false);
}
//+------------------------------------------------------------------+
//| CScrollBarH::Инициализация цветов объекта по умолчанию |
//+------------------------------------------------------------------+
void CScrollBarH::InitColors(void)
{
//--- Инициализируем цвета заднего плана для обычного и активированного состояний и делаем его текущим цветом фона
this.InitBackColors(clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke);
this.InitBackColorsAct(clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke);
this.BackColorToDefault();
//--- Инициализируем цвета переднего плана для обычного и активированного состояний и делаем его текущим цветом текста
this.InitForeColors(clrBlack,clrBlack,clrBlack,clrSilver);
this.InitForeColorsAct(clrBlack,clrBlack,clrBlack,clrSilver);
this.ForeColorToDefault();
//--- Инициализируем цвета рамки для обычного и активированного состояний и делаем его текущим цветом рамки
this.InitBorderColors(clrLightGray,clrLightGray,clrLightGray,clrSilver);
this.InitBorderColorsAct(clrLightGray,clrLightGray,clrLightGray,clrSilver);
this.BorderColorToDefault();
//--- Инициализируем цвет рамки и цвет переднего плана для заблокированного элемента
this.InitBorderColorBlocked(clrSilver);
this.InitForeColorBlocked(clrSilver);
}
//+------------------------------------------------------------------+
//| CScrollBarH::Рисует внешний вид |
//+------------------------------------------------------------------+
void CScrollBarH::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Обновляем канвас фона без перерисовки графика
this.m_background.Update(false);
//--- Рисуем элементы списка без перерисовки графика
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.Draw(false);
}
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CScrollBarH::Возвращает длину трека |
//+------------------------------------------------------------------+
int CScrollBarH::TrackLength(void) const
{
if(this.m_butt_left==NULL || this.m_butt_right==NULL)
return 0;
return(this.m_butt_right.X()-this.m_butt_left.Right());
}
//+------------------------------------------------------------------+
//| CScrollBarH::Возвращает начало трека |
//+------------------------------------------------------------------+
int CScrollBarH::TrackBegin(void) const
{
return(this.m_butt_left!=NULL ? this.m_butt_left.Width() : 0);
}
//+------------------------------------------------------------------+
//| CScrollBarH::Возвращает позицию ползунка |
//+------------------------------------------------------------------+
int CScrollBarH::ThumbPosition(void) const
{
return(this.m_thumb!=NULL ? this.m_thumb.X()-this.TrackBegin()-this.X() : 0);
}
//+------------------------------------------------------------------+
//| CScrollBarH::Изменяет ширину объекта |
//+------------------------------------------------------------------+
bool CScrollBarH::ResizeW(const int size)
{
//--- Получаем указатели на левую и правую кнопки
if(this.m_butt_left==NULL || this.m_butt_right==NULL)
return false;
//--- Изменяем ширину объекта
if(!CCanvasBase::ResizeW(size))
return false;
//--- Смещаем кнопки на новое расположение относительно левой и правой границ изменившего размер элемента
if(!this.m_butt_left.MoveX(this.X()))
return false;
return(this.m_butt_right.MoveX(this.Right()-this.m_butt_right.Width()+1));
}
//+------------------------------------------------------------------+
//| CScrollBarH::Обработчик прокрутки колёсика |
//+------------------------------------------------------------------+
void CScrollBarH::OnWheelEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Вызываем обработчик прокрутки для ползунка
if(this.m_thumb!=NULL)
this.m_thumb.OnWheelEvent(id,this.ThumbPosition(),dparam,this.NameFG());
//--- Отправляем пользовательское событие на график с позицией ползунка в lparam и именем объекта в sparam
::EventChartCustom(this.m_chart_id,CHARTEVENT_MOUSE_WHEEL,this.ThumbPosition(),dparam,this.NameFG());
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс вертикальной полосы прокрутки |
//+------------------------------------------------------------------+
class CScrollBarV : public CPanel
{
protected:
CButtonArrowUp *m_butt_up; // Кнопка со стрелкой вверх
CButtonArrowDown *m_butt_down; // Кнопка со стрелкой вниз
CScrollBarThumbV *m_thumb; // Ползунок скроллбара
public:
//--- Возвращает указатель на (1) левую, (2) правую кнопку, (3) ползунок
CButtonArrowUp *GetButtonUp(void) { return this.m_butt_up; }
CButtonArrowDown *GetButtonDown(void) { return this.m_butt_down; }
CScrollBarThumbV *GetThumb(void) { return this.m_thumb; }
//--- (1) Устанавливает, (2) возвращает флаг обновления графика
void SetChartRedrawFlag(const bool flag) { if(this.m_thumb!=NULL) this.m_thumb.SetChartRedrawFlag(flag); }
bool ChartRedrawFlag(void) const { return(this.m_thumb!=NULL ? this.m_thumb.ChartRedrawFlag() : false); }
//--- Возвращает (1) длину (2) начало трека, (3) позицию ползунка
int TrackLength(void) const;
int TrackBegin(void) const;
int ThumbPosition(void) const;
//--- Изменяет размер ползунка
bool SetThumbSize(const uint size) const { return(this.m_thumb!=NULL ? this.m_thumb.ResizeH(size) : false); }
//--- Изменяет высоту объекта
virtual bool ResizeH(const int size);
//--- Рисует внешний вид
virtual void Draw(const bool chart_redraw);
//--- Тип объекта
virtual int Type(void) const { return(ELEMENT_TYPE_SCROLLBAR_V); }
//--- Инициализация (1) объекта класса, (2) цветов объекта по умолчанию
void Init(void);
virtual void InitColors(void);
//--- Обработчик прокрутки колёсика (Wheel)
virtual void OnWheelEvent(const int id, const long lparam, const double dparam, const string sparam);
//--- Конструкторы/деструктор
CScrollBarV(void);
CScrollBarV(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CScrollBarV(void) {}
};
//+------------------------------------------------------------------+
//| CScrollBarV::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CScrollBarV::CScrollBarV(void) : CPanel("ScrollBarV","",::ChartID(),0,0,0,DEF_PANEL_W,DEF_PANEL_H),m_butt_up(NULL),m_butt_down(NULL),m_thumb(NULL)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CScrollBarV::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CScrollBarV::CScrollBarV(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,chart_id,wnd,x,y,w,h),m_butt_up(NULL),m_butt_down(NULL),m_thumb(NULL)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CScrollBarV::Инициализация |
//+------------------------------------------------------------------+
void CScrollBarV::Init(void)
{
//--- Инициализация родительского класса
CPanel::Init();
//--- Фон - непрозрачный
this.SetAlphaBG(255);
//--- Ширина рамки и текст
this.SetBorderWidth(0);
this.SetText("");
//--- Элемент не обрезается по границам контейнера
this.m_trim_flag=false;
//--- Создаём кнопки прокрутки
int w=this.Width();
int h=this.Width();
this.m_butt_up = this.InsertNewElement(ELEMENT_TYPE_BUTTON_ARROW_UP, "","ButtU",0,0,w,h);
this.m_butt_down= this.InsertNewElement(ELEMENT_TYPE_BUTTON_ARROW_DOWN,"","ButtD",0,this.Height()-w,w,h);
if(this.m_butt_up==NULL || this.m_butt_down==NULL)
{
::PrintFormat("%s: Init failed",__FUNCTION__);
return;
}
//--- Настраиваем цвета и вид кнопки со стрелкой вверх
this.m_butt_up.SetImageBound(1,0,w-4,h-2);
this.m_butt_up.InitBackColors(this.m_butt_up.BackColorFocused());
this.m_butt_up.ColorsToDefault();
this.m_butt_up.InitBorderColors(this.BorderColor(),this.m_butt_up.BackColorFocused(),this.m_butt_up.BackColorPressed(),this.m_butt_up.BackColorBlocked());
this.m_butt_up.ColorsToDefault();
//--- Настраиваем цвета и вид кнопки со стрелкой вниз
this.m_butt_down.SetImageBound(1,0,w-4,h-2);
this.m_butt_down.InitBackColors(this.m_butt_down.BackColorFocused());
this.m_butt_down.ColorsToDefault();
this.m_butt_down.InitBorderColors(this.BorderColor(),this.m_butt_down.BackColorFocused(),this.m_butt_down.BackColorPressed(),this.m_butt_down.BackColorBlocked());
this.m_butt_down.ColorsToDefault();
//--- Создаём ползунок
int tsz=this.Height()-w*2;
this.m_thumb=this.InsertNewElement(ELEMENT_TYPE_SCROLLBAR_THUMB_V,"","ThumbV",1,w,w-2,tsz/2);
if(this.m_thumb==NULL)
{
::PrintFormat("%s: Init failed",__FUNCTION__);
return;
}
//--- Настраиваем цвета ползунка и устанавливаем ему флаг перемещаемости
this.m_thumb.InitBackColors(this.m_thumb.BackColorFocused());
this.m_thumb.ColorsToDefault();
this.m_thumb.InitBorderColors(this.m_thumb.BackColor(),this.m_thumb.BackColorFocused(),this.m_thumb.BackColorPressed(),this.m_thumb.BackColorBlocked());
this.m_thumb.ColorsToDefault();
this.m_thumb.SetMovable(true);
//--- запрещаем самостоятельную перерисовку графика
this.m_thumb.SetChartRedrawFlag(false);
}
//+------------------------------------------------------------------+
//| CScrollBarV::Инициализация цветов объекта по умолчанию |
//+------------------------------------------------------------------+
void CScrollBarV::InitColors(void)
{
//--- Инициализируем цвета заднего плана для обычного и активированного состояний и делаем его текущим цветом фона
this.InitBackColors(clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke);
this.InitBackColorsAct(clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke,clrWhiteSmoke);
this.BackColorToDefault();
//--- Инициализируем цвета переднего плана для обычного и активированного состояний и делаем его текущим цветом текста
this.InitForeColors(clrBlack,clrBlack,clrBlack,clrSilver);
this.InitForeColorsAct(clrBlack,clrBlack,clrBlack,clrSilver);
this.ForeColorToDefault();
//--- Инициализируем цвета рамки для обычного и активированного состояний и делаем его текущим цветом рамки
this.InitBorderColors(clrLightGray,clrLightGray,clrLightGray,clrSilver);
this.InitBorderColorsAct(clrLightGray,clrLightGray,clrLightGray,clrSilver);
this.BorderColorToDefault();
//--- Инициализируем цвет рамки и цвет переднего плана для заблокированного элемента
this.InitBorderColorBlocked(clrSilver);
this.InitForeColorBlocked(clrSilver);
}
//+------------------------------------------------------------------+
//| CScrollBarV::Рисует внешний вид |
//+------------------------------------------------------------------+
void CScrollBarV::Draw(const bool chart_redraw)
{
//--- Заливаем кнопку цветом фона, рисуем рамку и обновляем канвас фона
this.Fill(this.BackColor(),false);
this.m_background.Rectangle(this.AdjX(0),this.AdjY(0),this.AdjX(this.Width()-1),this.AdjY(this.Height()-1),::ColorToARGB(this.BorderColor(),this.AlphaBG()));
this.m_background.Update(false);
//--- Обновляем канвас фона без перерисовки графика
this.m_background.Update(false);
//--- Рисуем элементы списка без перерисовки графика
for(int i=0;i<this.m_list_elm.Total();i++)
{
CElementBase *elm=this.GetAttachedElementAt(i);
if(elm!=NULL)
elm.Draw(false);
}
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CScrollBarV::Возвращает длину трека |
//+------------------------------------------------------------------+
int CScrollBarV::TrackLength(void) const
{
if(this.m_butt_up==NULL || this.m_butt_down==NULL)
return 0;
return(this.m_butt_down.Y()-this.m_butt_up.Bottom());
}
//+------------------------------------------------------------------+
//| CScrollBarV::Возвращает начало ползунка |
//+------------------------------------------------------------------+
int CScrollBarV::TrackBegin(void) const
{
return(this.m_butt_up!=NULL ? this.m_butt_up.Height() : 0);
}
//+------------------------------------------------------------------+
//| CScrollBarV::Возвращает позицию ползунка |
//+------------------------------------------------------------------+
int CScrollBarV::ThumbPosition(void) const
{
return(this.m_thumb!=NULL ? this.m_thumb.Y()-this.TrackBegin()-this.Y() : 0);
}
//+------------------------------------------------------------------+
//| CScrollBarV::Изменяет высоту объекта |
//+------------------------------------------------------------------+
bool CScrollBarV::ResizeH(const int size)
{
//--- Получаем указатели на верхнюю и нижнюю кнопки
if(this.m_butt_up==NULL || this.m_butt_down==NULL)
return false;
//--- Изменяем высоту объекта
if(!CCanvasBase::ResizeH(size))
return false;
//--- Смещаем кнопки на новое расположение относительно верхней и нижней границ изменившего размер элемента
if(!this.m_butt_up.MoveY(this.Y()))
return false;
return(this.m_butt_down.MoveY(this.Bottom()-this.m_butt_down.Height()+1));
}
//+------------------------------------------------------------------+
//| CScrollBarV::Обработчик прокрутки колёсика |
//+------------------------------------------------------------------+
void CScrollBarV::OnWheelEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- Вызываем обработчик прокрутки для ползунка
if(this.m_thumb!=NULL)
this.m_thumb.OnWheelEvent(id,this.ThumbPosition(),dparam,this.NameFG());
//--- Отправляем пользовательское событие на график с позицией ползунка в lparam и именем объекта в sparam
::EventChartCustom(this.m_chart_id,CHARTEVENT_MOUSE_WHEEL,this.ThumbPosition(),dparam,this.NameFG());
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Класс Контейнер |
//+------------------------------------------------------------------+
class CContainer : public CPanel
{
private:
bool m_visible_scrollbar_h; // Флаг видимости горизонтальной полосы прокрутки
bool m_visible_scrollbar_v; // Флаг видимости вертикальной полосы прокрутки
//--- Возвращает тип элемента, отправившего событие
ENUM_ELEMENT_TYPE GetEventElementType(const string name);
protected:
CScrollBarH *m_scrollbar_h; // Указатель на горизонтальную полосу прокрутки
CScrollBarV *m_scrollbar_v; // Указатель на вертикальную полосу прокрутки
//--- Проверяет размеры элемента для отображения полос прокрутки
void CheckElementSizes(CElementBase *element);
//--- Рассчитывает и возвращает размер (1) ползунка, (2) полный, (3) рабочий размер трека горизонтального скроллбара
int ThumbSizeHor(void);
int TrackLengthHor(void) const { return(this.m_scrollbar_h!=NULL ? this.m_scrollbar_h.TrackLength() : 0); }
int TrackEffectiveLengthHor(void) { return(this.TrackLengthHor()-this.ThumbSizeHor()); }
//--- Рассчитывает и возвращает размер (1) ползунка, (2) полный, (3) рабочий размер трека вертикального скроллбара
int ThumbSizeVer(void);
int TrackLengthVer(void) const { return(this.m_scrollbar_v!=NULL ? this.m_scrollbar_v.TrackLength() : 0); }
int TrackEffectiveLengthVer(void) { return(this.TrackLengthVer()-this.ThumbSizeVer()); }
//--- Размер видимой области содержимого по (1) горизонтали, (2) вертикали
int ContentVisibleHor(void) const { return int(this.Width()-this.BorderWidthLeft()-this.BorderWidthRight()); }
int ContentVisibleVer(void) const { return int(this.Height()-this.BorderWidthTop()-this.BorderWidthBottom()); }
//--- Полный размер содержимого по (1) горизонтали, (2) вертикали
int ContentSizeHor(void);
int ContentSizeVer(void);
//--- Позиция содержимого по (1) горизонтали, (2) вертикали
int ContentPositionHor(void);
int ContentPositionVer(void);
//--- Рассчитывает и возвращает величину смещения содержимого по (1) горизонтали, (2) вертикали в зависимости от положения ползунка
int CalculateContentOffsetHor(const uint thumb_position);
int CalculateContentOffsetVer(const uint thumb_position);
//--- Рассчитывает и возвращает величину смещения ползунка по (1) горизонтали, (2) вертикали в зависимости от положения контента
int CalculateThumbOffsetHor(const uint content_position);
int CalculateThumbOffsetVer(const uint content_position);
//--- Смещает содержимое по (1) горизонтали, (2) вертикали на указанное значение
bool ContentShiftHor(const int value);
bool ContentShiftVer(const int value);
public:
//--- Возврат указателей на скроллбары, кнопки и ползунки скроллбаров
CScrollBarH *GetScrollBarH(void) { return this.m_scrollbar_h; }
CScrollBarV *GetScrollBarV(void) { return this.m_scrollbar_v; }
CButtonArrowUp *GetScrollBarButtonUp(void) { return(this.m_scrollbar_v!=NULL ? this.m_scrollbar_v.GetButtonUp() : NULL); }
CButtonArrowDown *GetScrollBarButtonDown(void) { return(this.m_scrollbar_v!=NULL ? this.m_scrollbar_v.GetButtonDown() : NULL); }
CButtonArrowLeft *GetScrollBarButtonLeft(void) { return(this.m_scrollbar_h!=NULL ? this.m_scrollbar_h.GetButtonLeft() : NULL); }
CButtonArrowRight*GetScrollBarButtonRight(void) { return(this.m_scrollbar_h!=NULL ? this.m_scrollbar_h.GetButtonRight(): NULL); }
CScrollBarThumbH *GetScrollBarThumbH(void) { return(this.m_scrollbar_h!=NULL ? this.m_scrollbar_h.GetThumb() : NULL); }
CScrollBarThumbV *GetScrollBarThumbV(void) { return(this.m_scrollbar_v!=NULL ? this.m_scrollbar_v.GetThumb() : NULL); }
//--- Устанавливает флаг прокрутки содержимого
void SetScrolling(const bool flag) { this.m_scroll_flag=flag; }
//--- Возвращает флаг видимости (1) горизонтального, (2) вертикального скроллбара
bool ScrollBarHorIsVisible(void) const { return this.m_visible_scrollbar_h; }
bool ScrollBarVerIsVisible(void) const { return this.m_visible_scrollbar_v; }
//--- Создаёт и добавляет (1) новый, (2) ранее созданный элемент в список
virtual CElementBase *InsertNewElement(const ENUM_ELEMENT_TYPE type,const string text,const string user_name,const int dx,const int dy,const int w,const int h);
virtual CElementBase *InsertElement(CElementBase *element,const int dx,const int dy);
//--- Рисует внешний вид
virtual void Draw(const bool chart_redraw);
//--- Тип объекта
virtual int Type(void) const { return(ELEMENT_TYPE_CONTAINER); }
//--- Обработчики пользовательских событий элемента при наведении курсора, щелчке и прокрутке колёсика в области объекта
virtual void MouseMoveHandler(const int id, const long lparam, const double dparam, const string sparam);
virtual void MousePressHandler(const int id, const long lparam, const double dparam, const string sparam);
virtual void MouseWheelHandler(const int id, const long lparam, const double dparam, const string sparam);
//--- Инициализация объекта класса
void Init(void);
//--- Конструкторы/деструктор
CContainer(void);
CContainer(const string object_name, const string text, const int x, const int y, const int w, const int h);
CContainer(const string object_name, const string text, const int wnd, const int x, const int y, const int w, const int h);
CContainer(const string object_name, const string text, const long chart_id, const int wnd, const int x, const int y, const int w, const int h);
~CContainer (void) {}
};
//+------------------------------------------------------------------+
//| CContainer::Конструктор по умолчанию. |
//| Строит элемент в главном окне текущего графика |
//| в координатах 0,0 с размерами по умолчанию |
//+------------------------------------------------------------------+
CContainer::CContainer(void) : CPanel("Container","",::ChartID(),0,0,0,DEF_PANEL_W,DEF_PANEL_H), m_visible_scrollbar_h(false), m_visible_scrollbar_v(false)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CContainer::Конструктор параметрический. |
//| Строит элемент в главном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CContainer::CContainer(const string object_name,const string text,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,::ChartID(),0,x,y,w,h), m_visible_scrollbar_h(false), m_visible_scrollbar_v(false)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CContainer::Конструктор параметрический. |
//| Строит элемент в указанном окне текущего графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CContainer::CContainer(const string object_name,const string text,const int wnd,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,::ChartID(),wnd,x,y,w,h), m_visible_scrollbar_h(false), m_visible_scrollbar_v(false)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CContainer::Конструктор параметрический. |
//| Строит элемент в указанном окне указанного графика |
//| с указанными текстом, координами и размерами |
//+------------------------------------------------------------------+
CContainer::CContainer(const string object_name,const string text,const long chart_id,const int wnd,const int x,const int y,const int w,const int h) :
CPanel(object_name,text,chart_id,wnd,x,y,w,h), m_visible_scrollbar_h(false), m_visible_scrollbar_v(false)
{
//--- Инициализация
this.Init();
}
//+------------------------------------------------------------------+
//| CContainer::Инициализация |
//+------------------------------------------------------------------+
void CContainer::Init(void)
{
//--- Инициализация родительского объекта
CPanel::Init();
//--- Ширина рамки
this.SetBorderWidth(0);
//--- Создаём горизонтальный скроллбар
this.m_scrollbar_h=dynamic_cast<CScrollBarH *>(CPanel::InsertNewElement(ELEMENT_TYPE_SCROLLBAR_H,"","ScrollBarH",0,this.Height()-DEF_SCROLLBAR_TH-1,this.Width()-1,DEF_SCROLLBAR_TH));
if(m_scrollbar_h!=NULL)
{
//--- Скрываем элемент и устанавливаем запрет самостоятельной перерисовки графика
this.m_scrollbar_h.Hide(false);
this.m_scrollbar_h.SetChartRedrawFlag(false);
}
//--- Создаём вертикальный скроллбар
this.m_scrollbar_v=dynamic_cast<CScrollBarV *>(CPanel::InsertNewElement(ELEMENT_TYPE_SCROLLBAR_V,"","ScrollBarV",this.Width()-DEF_SCROLLBAR_TH-1,0,DEF_SCROLLBAR_TH,this.Height()-1));
if(m_scrollbar_v!=NULL)
{
//--- Скрываем элемент и устанавливаем запрет самостоятельной перерисовки графика
this.m_scrollbar_v.Hide(false);
this.m_scrollbar_v.SetChartRedrawFlag(false);
}
//--- Разрешаем прокрутку содержимого
this.m_scroll_flag=true;
}
//+------------------------------------------------------------------+
//| CContainer::Рисует внешний вид |
//+------------------------------------------------------------------+
void CContainer::Draw(const bool chart_redraw)
{
//--- Рисуем внешний вид
CPanel::Draw(false);
//--- Если прокрутка разрешена
if(this.m_scroll_flag)
{
//--- Если оба скроллбара видимы
if(this.m_visible_scrollbar_h && this.m_visible_scrollbar_v)
{
//--- получаем указатели на две кнопки правого нижнего угла
CButtonArrowDown *butt_dn=this.GetScrollBarButtonDown();
CButtonArrowRight*butt_rt=this.GetScrollBarButtonRight();
//--- Получаем указатель на горизонтальную полосу прокрутки и берём цвет её фона
CScrollBarH *scroll_bar=this.GetScrollBarH();
color clr=(scroll_bar!=NULL ? scroll_bar.BackColor() : clrWhiteSmoke);
//--- Определяем размеры прямоугольника в нижнем правом углу по размерам двух кнопок
int bw=(butt_rt!=NULL ? butt_rt.Width() : DEF_SCROLLBAR_TH-3);
int bh=(butt_dn!=NULL ? butt_dn.Height(): DEF_SCROLLBAR_TH-3);
//--- Устанавливаем координаты, в которых будет нарисован закрашенный прямоугольник
int x1=this.Width()-bw-1;
int y1=this.Height()-bh-1;
int x2=this.Width()-3;
int y2=this.Height()-3;
//--- Рисуем прямоугольник цветом фона скроллбара в нижнем правом углу
this.m_foreground.FillRectangle(x1,y1,x2,y2,::ColorToARGB(clr));
this.m_foreground.Update(false);
}
}
//--- Если указано - обновляем график
if(chart_redraw)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CContainer::Создаёт и добавляет новый элемент в список |
//+------------------------------------------------------------------+
CElementBase *CContainer::InsertNewElement(const ENUM_ELEMENT_TYPE type,const string text,const string user_name,const int dx,const int dy,const int w,const int h)
{
//--- Проверяем, чтобы в списке было не более трёх объектов - две полосы прокрутки и добавляемый
if(this.m_list_elm.Total()>2)
{
::PrintFormat("%s: Error. You can only add one element to a container\nTo add multiple elements, use the panel",__FUNCTION__);
return NULL;
}
//--- Создаём и добавляем новый элемент при помощи метода родительского класса
//--- Элемент помещается в координаты 0,0 независимо от указанных в параметрах
CElementBase *elm=CPanel::InsertNewElement(type,text,user_name,0,0,w,h);
//--- Проверяем размеры элемента для отображения полос прокрутки
this.CheckElementSizes(elm);
//--- Возвращаем указатель на элемент
return elm;
}
//+------------------------------------------------------------------+
//| CContainer::Добавляет указанный элемент в список |
//+------------------------------------------------------------------+
CElementBase *CContainer::InsertElement(CElementBase *element,const int dx,const int dy)
{
//--- Проверяем, чтобы в списке было не более трёх объектов - две полосы прокрутки и добавляемый
if(this.m_list_elm.Total()>2)
{
::PrintFormat("%s: Error. You can only add one element to a container\nTo add multiple elements, use the panel",__FUNCTION__);
return NULL;
}
//--- Добавляем указанный элемент при помощи метода родительского класса
//--- Элемент помещается в координаты 0,0 независимо от указанных в параметрах
CElementBase *elm=CPanel::InsertElement(element,0,0);
//--- Проверяем размеры элемента для отображения полос прокрутки
this.CheckElementSizes(elm);
//--- Возвращаем указатель на элемент
return elm;
}
//+------------------------------------------------------------------+
//| CContainer::Проверяет размеры элемента |
//| для отображения полос прокрутки |
//+------------------------------------------------------------------+
void CContainer::CheckElementSizes(CElementBase *element)
{
//--- Если передан пустой элемент, или прокрутка запрещена - уходим
if(element==NULL || !this.m_scroll_flag)
return;
//--- Получаем тип элемента и, если это скроллбар - уходим
ENUM_ELEMENT_TYPE type=(ENUM_ELEMENT_TYPE)element.Type();
if(type==ELEMENT_TYPE_SCROLLBAR_H || type==ELEMENT_TYPE_SCROLLBAR_V)
return;
//--- Инициализируем флаги отображения полос прокрутки
this.m_visible_scrollbar_h=false;
this.m_visible_scrollbar_v=false;
//--- Если ширина элемента больше ширины видимой области контейнера -
//--- устанавливаем флаг отображения горизонтальной полосы прокрутки
if(element.Width()>this.ContentVisibleHor())
this.m_visible_scrollbar_h=true;
//--- Если высота элемента больше высоты видимой области контейнера -
//--- устанавливаем флаг отображения вертикальной полосы прокрутки
if(element.Height()>this.ContentVisibleVer())
this.m_visible_scrollbar_v=true;
//--- Если обе полосы прокрутки должны быть отображены
if(this.m_visible_scrollbar_h && this.m_visible_scrollbar_v)
{
//--- Получаем указатели на две кнопки прокрутки в нижнем правом углу
CButtonArrowRight *br=this.m_scrollbar_h.GetButtonRight();
CButtonArrowDown *bd=this.m_scrollbar_v.GetButtonDown();
//--- Получаем размеры кнопок прокрутки в высоту и ширину,
//--- на которые необходимо уменьшить полосы прокрутки, и
int v=(bd!=NULL ? bd.Height() : DEF_SCROLLBAR_TH);
int h=(br!=NULL ? br.Width() : DEF_SCROLLBAR_TH);
//--- изменяем размеры обеих полос прокрутки на размер кнопок
this.m_scrollbar_v.ResizeH(this.m_scrollbar_v.Height()-v);
this.m_scrollbar_h.ResizeW(this.m_scrollbar_h.Width() -h);
}
//--- Если горизонтальная полоса прокрутки должна быть показана
if(this.m_visible_scrollbar_h)
{
//--- Уменьшаем размер видимого окна контейнера снизу на толщину полосы прокрутки + 1 пиксель
this.SetBorderWidthBottom(this.m_scrollbar_h.Height()+1);
//--- Корректируем размер ползунка под новый размер полосы прокрутки и
//--- переносим скроллбар на передний план, делая его при этом видимым
this.m_scrollbar_h.SetThumbSize(this.ThumbSizeHor());
this.m_scrollbar_h.BringToTop(false);
}
//--- Если вертикальная полоса прокрутки должна быть показана
if(this.m_visible_scrollbar_v)
{
//--- Уменьшаем размер видимого окна контейнера справа на толщину полосы прокрутки + 1 пиксель
this.SetBorderWidthRight(this.m_scrollbar_v.Width()+1);
//--- Корректируем размер ползунка под новый размер полосы прокрутки и
//--- переносим скроллбар на передний план, делая его при этом видимым
this.m_scrollbar_v.SetThumbSize(this.ThumbSizeVer());
this.m_scrollbar_v.BringToTop(false);
}
//--- Если любая из полос прокрутки видима - обрезаем привязанный элемент по новым размерам видимой области
if(this.m_visible_scrollbar_h || this.m_visible_scrollbar_v)
{
CElementBase *elm=this.GetAttachedElementAt(2);
if(elm!=NULL)
elm.ObjectTrim();
}
}
//+-------------------------------------------------------------------+
//|CContainer::Рассчитывает размер ползунка горизонтального скроллбара|
//+-------------------------------------------------------------------+
int CContainer::ThumbSizeHor(void)
{
CElementBase *elm=this.GetAttachedElementAt(2);
if(elm==NULL || elm.Width()==0 || this.TrackLengthHor()==0)
return 0;
return int(::round(::fmax(((double)this.ContentVisibleHor() / (double)elm.Width()) * (double)this.TrackLengthHor(), DEF_THUMB_MIN_SIZE)));
}
//+------------------------------------------------------------------+
//| CContainer::Рассчитывает размер ползунка вертикального скроллбара|
//+------------------------------------------------------------------+
int CContainer::ThumbSizeVer(void)
{
CElementBase *elm=this.GetAttachedElementAt(2);
if(elm==NULL || elm.Height()==0 || this.TrackLengthVer()==0)
return 0;
return int(::round(::fmax(((double)this.ContentVisibleVer() / (double)elm.Height()) * (double)this.TrackLengthVer(), DEF_THUMB_MIN_SIZE)));
}
//+------------------------------------------------------------------+
//| CContainer::Полный размер содержимого по горизонтали |
//+------------------------------------------------------------------+
int CContainer::ContentSizeHor(void)
{
CElementBase *elm=this.GetAttachedElementAt(2);
return(elm!=NULL ? elm.Width() : 0);
}
//+------------------------------------------------------------------+
//| CContainer::Полный размер содержимого по вертикали |
//+------------------------------------------------------------------+
int CContainer::ContentSizeVer(void)
{
CElementBase *elm=this.GetAttachedElementAt(2);
return(elm!=NULL ? elm.Height() : 0);
}
//+--------------------------------------------------------------------+
//|CContainer::Возвращает позицию содержимого контейнера по горизонтали|
//+--------------------------------------------------------------------+
int CContainer::ContentPositionHor(void)
{
CElementBase *elm=this.GetAttachedElementAt(2);
return(elm!=NULL ? elm.X()-this.X() : 0);
}
//+------------------------------------------------------------------+
//|CContainer::Возвращает позицию содержимого контейнера по вертикали|
//+------------------------------------------------------------------+
int CContainer::ContentPositionVer(void)
{
CElementBase *elm=this.GetAttachedElementAt(2);
return(elm!=NULL ? elm.Y()-this.Y() : 0);
}
//+------------------------------------------------------------------+
//| CContainer::Рассчитывает и возвращает величину смещения |
//| содержимого контейнера по горизонтали по положению ползунка |
//+------------------------------------------------------------------+
int CContainer::CalculateContentOffsetHor(const uint thumb_position)
{
CElementBase *elm=this.GetAttachedElementAt(2);
int effective_track_length=this.TrackEffectiveLengthHor();
if(elm==NULL || effective_track_length==0)
return 0;
return (int)::round(((double)thumb_position / (double)effective_track_length) * ((double)elm.Width() - (double)this.ContentVisibleHor()));
}
//+------------------------------------------------------------------+
//| CContainer::Рассчитывает и возвращает величину смещения |
//| содержимого контейнера по вертикали по положению ползунка |
//+------------------------------------------------------------------+
int CContainer::CalculateContentOffsetVer(const uint thumb_position)
{
CElementBase *elm=this.GetAttachedElementAt(2);
int effective_track_length=this.TrackEffectiveLengthVer();
if(elm==NULL || effective_track_length==0)
return 0;
return (int)::round(((double)thumb_position / (double)effective_track_length) * ((double)elm.Height() - (double)this.ContentVisibleVer()));
}
//+------------------------------------------------------------------+
//| CContainer::Рассчитывает и возвращает величину смещения ползунка |
//| по горизонтали в зависимости от положения контента |
//+------------------------------------------------------------------+
int CContainer::CalculateThumbOffsetHor(const uint content_position)
{
CElementBase *elm=this.GetAttachedElementAt(2);
if(elm==NULL)
return 0;
int value=elm.Width()-this.ContentVisibleHor();
if(value==0)
return 0;
return (int)::round(((double)content_position / (double)value) * (double)this.TrackEffectiveLengthHor());
}
//+------------------------------------------------------------------+
//| CContainer::Рассчитывает и возвращает величину смещения ползунка |
//| по вертикали в зависимости от положения контента |
//+------------------------------------------------------------------+
int CContainer::CalculateThumbOffsetVer(const uint content_position)
{
CElementBase *elm=this.GetAttachedElementAt(2);
if(elm==NULL)
return 0;
int value=elm.Height()-this.ContentVisibleVer();
if(value==0)
return 0;
return (int)::round(((double)content_position / (double)value) * (double)this.TrackEffectiveLengthVer());
}
//+-------------------------------------------------------------------+
//|CContainer::Смещает содержимое по горизонтали на указанное значение|
//+-------------------------------------------------------------------+
bool CContainer::ContentShiftHor(const int value)
{
//--- Получаем указатель на содержимое контейнера
CElementBase *elm=this.GetAttachedElementAt(2);
if(elm==NULL)
return false;
//--- Рассчитываем величину смещения по положению ползунка
int content_offset=this.CalculateContentOffsetHor(value);
//--- Возвращаем результат сдвига содержимого на рассчитанную величину
return(elm.MoveX(this.X()-content_offset));
}
//+------------------------------------------------------------------+
//| CContainer::Смещает содержимое по вертикали на указанное значение|
//+------------------------------------------------------------------+
bool CContainer::ContentShiftVer(const int value)
{
//--- Получаем указатель на содержимое контейнера
CElementBase *elm=this.GetAttachedElementAt(2);
if(elm==NULL)
return false;
//--- Рассчитываем величину смещения по положению ползунка
int content_offset=this.CalculateContentOffsetVer(value);
//--- Возвращаем результат сдвига содержимого на рассчитанную величину
return(elm.MoveY(this.Y()-content_offset));
}
//+------------------------------------------------------------------+
//| Возвращает тип элемента, отправившего событие |
//+------------------------------------------------------------------+
ENUM_ELEMENT_TYPE CContainer::GetEventElementType(const string name)
{
//--- Получаем имена всех элементов в иерархии (при ошибке - возвращаем -1)
string names[]={};
int total = GetElementNames(name,"_",names);
if(total==WRONG_VALUE)
return WRONG_VALUE;
//--- Если имя базового элемента в иерархии не совпадает с именем контейнера, то это не наше событие - уходим
string base_name=names[0];
if(base_name!=this.NameFG())
return WRONG_VALUE;
//--- События, пришедшие не от скроллбаров, пропускаем
string check_name=::StringSubstr(names[1],0,4);
if(check_name!="SCBH" && check_name!="SCBV")
return WRONG_VALUE;
//--- Получаем имя элемента, от которого пришло событие и инициализируем тип элемента
string elm_name=names[names.Size()-1];
ENUM_ELEMENT_TYPE type=WRONG_VALUE;
//--- Проверяем и записываем тип элемента
//--- Кнопка со стрелкой вверх
if(::StringFind(elm_name,"BTARU")==0)
type=ELEMENT_TYPE_BUTTON_ARROW_UP;
//--- Кнопка со стрелкой вниз
else if(::StringFind(elm_name,"BTARD")==0)
type=ELEMENT_TYPE_BUTTON_ARROW_DOWN;
//--- Кнопка со стрелкой влево
else if(::StringFind(elm_name,"BTARL")==0)
type=ELEMENT_TYPE_BUTTON_ARROW_LEFT;
//--- Кнопка со стрелкой вправо
else if(::StringFind(elm_name,"BTARR")==0)
type=ELEMENT_TYPE_BUTTON_ARROW_RIGHT;
//--- Ползунок горизонтальной полосы прокрутки
else if(::StringFind(elm_name,"THMBH")==0)
type=ELEMENT_TYPE_SCROLLBAR_THUMB_H;
//--- Ползунок вертикальной полосы прокрутки
else if(::StringFind(elm_name,"THMBV")==0)
type=ELEMENT_TYPE_SCROLLBAR_THUMB_V;
//--- Элемент управления ScrollBarHorisontal
else if(::StringFind(elm_name,"SCBH")==0)
type=ELEMENT_TYPE_SCROLLBAR_H;
//--- Элемент управления ScrollBarVertical
else if(::StringFind(elm_name,"SCBV")==0)
type=ELEMENT_TYPE_SCROLLBAR_V;
//--- Возвращаем тип элемента
return type;
}
//+------------------------------------------------------------------+
//| CContainer::Обработчик пользовательского события элемента |
//| при перемещении курсора в области объекта |
//+------------------------------------------------------------------+
void CContainer::MouseMoveHandler(const int id,const long lparam,const double dparam,const string sparam)
{
bool res=false;
//--- Получаем указатель на содержимое контейнера
CElementBase *elm=this.GetAttachedElementAt(2);
//--- Получаем тип элемента, от которого пришло событие
ENUM_ELEMENT_TYPE type=this.GetEventElementType(sparam);
//--- Если не удалось получить тип элемента или указатель на содержимое - уходим
if(type==WRONG_VALUE || elm==NULL)
return;
//--- Если событие ползунка горизонтального скроллбара - сдвигаем содержимое по горизонтали
if(type==ELEMENT_TYPE_SCROLLBAR_THUMB_H)
res=this.ContentShiftHor((int)lparam);
//--- Если событие ползунка вертикального скроллбара - сдвигаем содержимое по вертикали
if(type==ELEMENT_TYPE_SCROLLBAR_THUMB_V)
res=this.ContentShiftVer((int)lparam);
//--- Если содержимое успешно сдвинуто - обновляем график
if(res)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CContainer::Обработчик пользовательского события элемента |
//| при щелчке в области объекта |
//+------------------------------------------------------------------+
void CContainer::MousePressHandler(const int id,const long lparam,const double dparam,const string sparam)
{
bool res=false;
//--- Получаем указатель на содержимое контейнера
CElementBase *elm=this.GetAttachedElementAt(2);
//--- Получаем тип элемента, от которого пришло событие
ENUM_ELEMENT_TYPE type=this.GetEventElementType(sparam);
//--- Если не удалось получить тип элемента или указатель на содержимое - уходим
if(type==WRONG_VALUE || elm==NULL)
return;
//--- Если события кнопок горизонтального скроллбара,
if(type==ELEMENT_TYPE_BUTTON_ARROW_LEFT || type==ELEMENT_TYPE_BUTTON_ARROW_RIGHT)
{
//--- Проверяем указатель на горизонтальный скроллбар
if(this.m_scrollbar_h==NULL)
return;
//--- получаем указатель на ползунок скроллбара
CScrollBarThumbH *obj=this.m_scrollbar_h.GetThumb();
if(obj==NULL)
return;
//--- определяем направление смещения ползунка по типу нажатой кнопки
int direction=(type==ELEMENT_TYPE_BUTTON_ARROW_LEFT ? 120 : -120);
//--- вызываем обработчик прокрутки объекта ползунка для смещения ползунка в направлении direction
obj.OnWheelEvent(id,0,direction,this.NameFG());
//--- Успешно
res=true;
}
//--- Если события кнопок вертикального скроллбара,
if(type==ELEMENT_TYPE_BUTTON_ARROW_UP || type==ELEMENT_TYPE_BUTTON_ARROW_DOWN)
{
//--- Проверяем указатель на вертикальный скроллбар
if(this.m_scrollbar_v==NULL)
return;
//--- получаем указатель на ползунок скроллбара
CScrollBarThumbV *obj=this.m_scrollbar_v.GetThumb();
if(obj==NULL)
return;
//--- определяем направление смещения ползунка по типу нажатой кнопки
int direction=(type==ELEMENT_TYPE_BUTTON_ARROW_UP ? 120 : -120);
//--- вызываем обработчик прокрутки объекта ползунка для смещения ползунка в направлении direction
obj.OnWheelEvent(id,0,direction,this.NameFG());
//--- Успешно
res=true;
}
//--- Если событие щелчка по горизонтальному скроллбару (между ползунком и кнопками прокрутки),
if(type==ELEMENT_TYPE_SCROLLBAR_H)
{
//--- Проверяем указатель на горизонтальный скроллбар
if(this.m_scrollbar_h==NULL)
return;
//--- получаем указатель на ползунок скроллбара
CScrollBarThumbH *thumb=this.m_scrollbar_h.GetThumb();
if(thumb==NULL)
return;
//--- Направление смещения ползунка
int direction=(lparam>=thumb.Right() ? 1 : lparam<=thumb.X() ? -1 : 0);
//--- Проверяем делитель на нулевое значение
if(this.ContentSizeHor()-this.ContentVisibleHor()==0)
return;
//--- Рассчитываем смещение ползунка, пропорциональное смещению содержимого на один экран
int thumb_shift=(int)::round(direction * ((double)this.ContentVisibleHor() / double(this.ContentSizeHor()-this.ContentVisibleHor())) * (double)this.TrackEffectiveLengthHor());
//--- вызываем обработчик прокрутки объекта ползунка для смещения ползунка в направлении смещения
thumb.OnWheelEvent(id,thumb_shift,0,this.NameFG());
//--- Записываем результат смещения содержимого контейнера
res=this.ContentShiftHor(thumb_shift);
}
//--- Если событие щелчка по вертикальному скроллбару (между ползунком и кнопками прокрутки),
if(type==ELEMENT_TYPE_SCROLLBAR_V)
{
//--- Проверяем указатель на вертикальный скроллбар
if(this.m_scrollbar_v==NULL)
return;
//--- получаем указатель на ползунок скроллбара
CScrollBarThumbV *thumb=this.m_scrollbar_v.GetThumb();
if(thumb==NULL)
return;
//--- Направление смещения ползунка
int cursor=int(dparam-this.m_wnd_y);
int direction=(cursor>=thumb.Bottom() ? 1 : cursor<=thumb.Y() ? -1 : 0);
//--- Проверяем делитель на нулевое значение
if(this.ContentSizeVer()-this.ContentVisibleVer()==0)
return;
//--- Рассчитываем смещение ползунка, пропорциональное смещению содержимого на один экран
int thumb_shift=(int)::round(direction * ((double)this.ContentVisibleVer() / double(this.ContentSizeVer()-this.ContentVisibleVer())) * (double)this.TrackEffectiveLengthVer());
//--- вызываем обработчик прокрутки объекта ползунка для смещения ползунка в направлении смещения
thumb.OnWheelEvent(id,thumb_shift,0,this.NameFG());
//--- Записываем результат смещения содержимого контейнера
res=this.ContentShiftVer(thumb_shift);
}
//--- Если всё успешно - обновляем график
if(res)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//| CContainer::Обработчик пользовательского события элемента |
//| при прокрутке колёсика в области ползунка скроллбара |
//+------------------------------------------------------------------+
void CContainer::MouseWheelHandler(const int id,const long lparam,const double dparam,const string sparam)
{
bool res=false;
//--- Получаем указатель на содержимое контейнера
CElementBase *elm=this.GetAttachedElementAt(2);
//--- Получаем тип элемента, от которого пришло событие
ENUM_ELEMENT_TYPE type=this.GetEventElementType(sparam);
//--- Если не удалось получить указатель на содержимое, или тип элемента - уходим
if(type==WRONG_VALUE || elm==NULL)
return;
//--- Если событие ползунка горизонтального скроллбара - сдвигаем содержимое по горизонтали
if(type==ELEMENT_TYPE_SCROLLBAR_THUMB_H)
res=this.ContentShiftHor((int)lparam);
//--- Если событие ползунка вертикального скроллбара - сдвигаем содержимое по вертикали
if(type==ELEMENT_TYPE_SCROLLBAR_THUMB_V)
res=this.ContentShiftVer((int)lparam);
//--- Если содержимое успешно сдвинуто - обновляем график
if(res)
::ChartRedraw(this.m_chart_id);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+