//+------------------------------------------------------------------+ //| 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; iobj.Name() ? 1 : this.Name() obj.Alpha() ? 1 : this.Alpha() obj.X() ? 1 : this.X() obj.Y() ? 1 : this.Y() obj.Width() ? 1 : this.Width() obj.Height() ? 1 : this.Height() obj.ID() ? 1 : this.ID() 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.X() ? 1 : this.X() obj.Y() ? 1 : this.Y() obj.Width() ? 1 : this.Width() obj.Height() ? 1 : this.Height() obj.BackColor() ? 1 : this.BackColor() obj.ForeColor() ? 1 : this.ForeColor() obj.AlphaBG() ? 1 : this.AlphaBG() obj.AlphaFG() ? 1 : this.AlphaFG() obj.State() ? 1 : this.State() obj.Group() ? 1 : this.Group() obj.ObjectZOrder() ? 1 : this.ObjectZOrder() obj.ID() ? 1 : this.ID() obj.Name() ? 1 : this.Name() obj.Text() ? 1 : this.Text() obj.X() ? 1 : this.X() obj.Y() ? 1 : this.Y() obj.Width() ? 1 : this.Width() obj.Height() ? 1 : this.Height() obj.BackColor() ? 1 : this.BackColor() obj.ForeColor() ? 1 : this.ForeColor() obj.AlphaBG() ? 1 : this.AlphaBG() obj.AlphaFG() ? 1 : this.AlphaFG() obj.State() ? 1 : this.State() obj.ObjectZOrder() ? 1 : this.ObjectZOrder() obj.ID() ? 1 : this.ID() 0 && h>0) this.m_foreground.FillRectangle(this.AdjX(this.m_text_x),this.AdjY(this.m_text_y),this.AdjX(this.m_text_x+w),this.AdjY(this.m_text_y+h),clrNULL); //--- Иначе - очищаем полностью весь передний план else this.m_foreground.Erase(clrNULL); } //+------------------------------------------------------------------+ //| CLabel::Выводит текст | //+------------------------------------------------------------------+ void CLabel::DrawText(const int dx,const int dy,const string text,const bool chart_redraw) { //--- Очищаем прошлый текст и устанавливаем новый this.ClearText(); this.SetText(text); //--- Выводим установленный текст this.m_foreground.TextOut(this.AdjX(dx),this.AdjY(dy),this.Text(),::ColorToARGB(this.ForeColor(),this.AlphaFG())); //--- Если текст выходит за правую границу объекта if(this.Width()-dx0 && h>0) { //--- Стираем текст у правой границы объекта по размеру текста "троеточие" и заменяем троеточием окончание текста метки this.m_foreground.FillRectangle(this.AdjX(this.Width()-w),this.AdjY(this.m_text_y),this.AdjX(this.Width()),this.AdjY(this.m_text_y+h),clrNULL); this.m_foreground.TextOut(this.AdjX(this.Width()-w),this.AdjY(dy),"...",::ColorToARGB(this.ForeColor(),this.AlphaFG())); } } //--- Обновляем канвас переднего плана и запоминаем новые координаты текста this.m_foreground.Update(chart_redraw); this.m_text_x=dx; this.m_text_y=dy; //--- Запоминаем нарисованный текст как прошлый this.SetTextPrev(text); } //+------------------------------------------------------------------+ //| CLabel::Рисует внешний вид | //+------------------------------------------------------------------+ void CLabel::Draw(const bool chart_redraw) { this.DrawText(this.m_text_x,this.m_text_y,this.Text(),chart_redraw); } //+------------------------------------------------------------------+ //| CLabel::Сохранение в файл | //+------------------------------------------------------------------+ bool CLabel::Save(const int file_handle) { //--- Сохраняем данные родительского объекта if(!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-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;ibase_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(ybase_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(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(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); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+